2017-07-23 09:20:22 +01:00
/ * webserver . go
*
* This is the webserver handler for White Rabbit , and handles
* all incoming connections , including authentication .
* /
2017-06-14 06:57:02 +01:00
package main
import (
2017-06-18 21:57:43 +01:00
"fmt"
"io/ioutil"
"log"
"net/http"
2017-07-15 16:06:37 +01:00
"crypto/subtle"
2017-06-15 17:21:22 +01:00
2017-06-18 21:57:43 +01:00
"github.com/gorilla/mux"
2017-07-23 09:20:22 +01:00
"github.com/spf13/viper"
2017-06-14 06:57:02 +01:00
)
2017-06-18 21:57:43 +01:00
2017-07-23 09:20:22 +01:00
// Prints out contects of feed.rss
2017-06-15 17:21:22 +01:00
func RssHandler ( w http . ResponseWriter , r * http . Request ) {
2017-06-18 21:57:43 +01:00
w . Header ( ) . Set ( "Content-Type" , "application/rss+xml" )
w . WriteHeader ( http . StatusOK )
data , err := ioutil . ReadFile ( "feed.rss" )
if err != nil {
panic ( err )
}
w . Header ( ) . Set ( "Content-Length" , fmt . Sprint ( len ( data ) ) )
fmt . Fprint ( w , string ( data ) )
2017-06-14 06:57:02 +01:00
}
2017-07-23 09:20:22 +01:00
// Does the same as above method, only with the JSON feed data
2017-06-18 21:57:43 +01:00
func JsonHandler ( w http . ResponseWriter , r * http . Request ) {
w . Header ( ) . Set ( "Content-Type" , "application/json" )
w . WriteHeader ( http . StatusOK )
data , err := ioutil . ReadFile ( "feed.json" )
if err != nil {
panic ( err )
}
w . Header ( ) . Set ( "Content-Length" , fmt . Sprint ( len ( data ) ) )
fmt . Fprint ( w , string ( data ) )
2017-06-15 17:21:22 +01:00
}
2017-07-23 09:20:22 +01:00
// Serve up homepage
2017-06-18 21:57:43 +01:00
func HomeHandler ( w http . ResponseWriter , r * http . Request ) {
data , err := ioutil . ReadFile ( "assets/index.html" )
if err == nil {
w . Write ( data )
} else {
w . WriteHeader ( 404 )
w . Write ( [ ] byte ( "404 Something went wrong - " + http . StatusText ( 404 ) ) )
}
2017-06-15 17:21:22 +01:00
}
2017-07-23 09:20:22 +01:00
// Authenticate user using basic webserver authentication
2017-07-15 16:06:37 +01:00
/ *
* Code from stackoverflow by user Timmmm
* https : //stackoverflow.com/questions/21936332/idiomatic-way-of-requiring-http-basic-auth-in-go/39591234#39591234
* /
func BasicAuth ( handler http . HandlerFunc , username , password , realm string ) http . HandlerFunc {
return func ( w http . ResponseWriter , r * http . Request ) {
user , pass , ok := r . BasicAuth ( )
if ! ok || subtle . ConstantTimeCompare ( [ ] byte ( user ) , [ ] byte ( username ) ) != 1 || subtle . ConstantTimeCompare ( [ ] byte ( pass ) , [ ] byte ( password ) ) != 1 {
w . Header ( ) . Set ( "WWW-Authenticate" , ` Basic realm="White Rabbit" ` )
w . WriteHeader ( 401 )
w . Write ( [ ] byte ( "Unauthorised.\n" ) )
return
}
handler ( w , r )
}
}
2017-07-23 09:20:22 +01:00
// Handler for serving up admin page
2017-07-15 16:06:37 +01:00
func AdminHandler ( w http . ResponseWriter , r * http . Request ) {
data , err := ioutil . ReadFile ( "assets/admin.html" )
if err == nil {
w . Write ( data )
} else {
w . WriteHeader ( 404 )
w . Write ( [ ] byte ( "404 Something went wrong - " + http . StatusText ( 404 ) ) )
}
}
2017-07-23 09:20:22 +01:00
// Main function that defines routes
2017-06-14 06:57:02 +01:00
func main ( ) {
2017-07-23 09:20:22 +01:00
viper . SetConfigName ( "config" )
viper . AddConfigPath ( "." )
err := viper . ReadInConfig ( ) // Find and read the config file
if err != nil { // Handle errors reading the config file
panic ( fmt . Errorf ( "Fatal error config file: %s \n" , err ) )
}
// Start the watch() function in generate_rss.go, which
// watches for file changes and regenerates the feed
2017-06-18 21:57:43 +01:00
go watch ( )
2017-07-23 09:20:22 +01:00
// Define routes
2017-06-18 21:57:43 +01:00
r := mux . NewRouter ( )
2017-07-23 09:20:22 +01:00
// "Static" paths
2017-06-18 21:57:43 +01:00
r . PathPrefix ( "/assets/" ) . Handler ( http . StripPrefix ( "/assets/" , http . FileServer ( http . Dir ( "assets/static" ) ) ) )
r . PathPrefix ( "/download/" ) . Handler ( http . StripPrefix ( "/download/" , http . FileServer ( http . Dir ( "podcasts" ) ) ) )
2017-07-23 09:20:22 +01:00
// Paths that require specific handlers
http . Handle ( "/" , r ) // Pass everything to gorilla mux
2017-06-18 21:57:43 +01:00
r . HandleFunc ( "/" , HomeHandler )
r . HandleFunc ( "/rss" , RssHandler )
r . HandleFunc ( "/json" , JsonHandler )
2017-07-23 09:20:22 +01:00
r . HandleFunc ( "/admin" , BasicAuth ( AdminHandler , viper . GetString ( "AdminUsername" ) , viper . GetString ( "AdminPassword" ) , "Login to White Rabbit admin interface" ) )
2017-07-16 18:43:47 +01:00
r . HandleFunc ( "/admin/publish" , CreateEpisode )
2017-07-23 09:20:22 +01:00
// We're live!
2017-06-18 21:57:43 +01:00
log . Fatal ( http . ListenAndServe ( ":8000" , r ) )
}