Reputation:
I have two tasks I need to fulfill when the "/" pattern is present in a request, both of which require using http handlers.
They are:
http.Handle("/", http.FileServer(http.Dir("dtfw-tool/build/")))
http.HandleFunc("/", index)
The index handler checks for proper authentication to access a webpage, and the handler above it serves up a directory (in the future I will make it to where it will only serve the directory if authentication requirements are met).
Is it possible to have two handlers for the same pattern (currently gives error)? If not, is there any other way to check authentication and serve up the directory with a single handler?
Upvotes: 4
Views: 5717
Reputation:
I'm going to have to retract my previous answer acceptance because this is much closer to what I was looking for (have to import github.com/abbot/go-http-auth):
package main
import (
"fmt"
"net/http"
auth "github.com/abbot/go-http-auth"
)
func Secret(user, realm string) string {
if user == "john" {
// password is "hello"
return "$1$dlPL2MqE$oQmn16q49SqdmhenQuNgs1"
}
return ""
}
func main() {
fmt.Println("-----> Starting HTTP server...")
authenticator := auth.NewBasicAuthenticator("secret.com", Secret)
http.HandleFunc("/", authenticator.Wrap(func(res http.ResponseWriter, req *auth.AuthenticatedRequest) {
http.FileServer(http.Dir(".")).ServeHTTP(res, &req.Request)
}))
http.ListenAndServe(":5042", nil)
}
This method is much easier to follow and more intutive (for me at least).
Upvotes: 2
Reputation: 12675
Create a middleware to authenticate users and return the handler to main Handle
which will wrap your final handler
package main
import (
"log"
"net/http"
)
func main() {
finalHandler := http.HandlerFunc(final)
http.Handle("/", authentication(finalHandler))
http.ListenAndServe(":3000", nil)
}
func authentication(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("Executing authentication")
next.ServeHTTP(w, r) //`next.ServeHTTP(w, r)` will forward the request and response to next handler.
})
}
func final(w http.ResponseWriter, r *http.Request) {
log.Println("Executing finalHandler")
w.Write([]byte("User authenticated"))
}
In Golang HanlderFunc
is used to return hanlder which will become a middlware to wrap the main function:
// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)
It is also defined in the source code for server.go
Upvotes: 7