Add utility Handler functions
This commit is contained in:
parent
f81c32a211
commit
b5a3c0adc5
91
handler.go
Normal file
91
handler.go
Normal file
@ -0,0 +1,91 @@
|
||||
package gemini
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A Handler responds to a Gemini request.
|
||||
//
|
||||
// ServeGemini should write the response header and data to the ResponseWriter
|
||||
// and then return. Returning signals that the request is finished; it is not
|
||||
// valid to use the ResponseWriter after or concurrently with the completion
|
||||
// of the ServeGemini call.
|
||||
//
|
||||
// Handlers should not modify the provided Request.
|
||||
//
|
||||
// If ServeGemini panics, the server (the caller of ServeGemini) assumes that
|
||||
// the effect of the panic was isolated to the active request. It recovers
|
||||
// the panic, logs a stack trace to the server error log, and closes the
|
||||
// network connection. To abort a handler so the client sees an interrupted
|
||||
// response but the server doesn't log an error, panic with the value
|
||||
// ErrAbortHandler.
|
||||
type Handler interface {
|
||||
ServeGemini(ResponseWriter, *Request)
|
||||
}
|
||||
|
||||
// The HandlerFunc type is an adapter to allow the use of ordinary functions
|
||||
// as Gemini handlers. If f is a function with the appropriate signature,
|
||||
// HandlerFunc(f) is a Handler that calls f.
|
||||
type HandlerFunc func(ResponseWriter, *Request)
|
||||
|
||||
// ServeGemini calls f(w, r).
|
||||
func (f HandlerFunc) ServeGemini(w ResponseWriter, r *Request) {
|
||||
f(w, r)
|
||||
}
|
||||
|
||||
// RedirectHandler returns a request handler that redirects each request it
|
||||
// receives to the given url using the given status code.
|
||||
//
|
||||
// The provided code should be in the 3x range and is usually
|
||||
// StatusRedirect or StatusPermanentRedirect.
|
||||
func RedirectHandler(url string, code int) Handler {
|
||||
return &redirectHandler{url, code}
|
||||
}
|
||||
|
||||
type redirectHandler struct {
|
||||
url string
|
||||
code int
|
||||
}
|
||||
|
||||
func (h *redirectHandler) ServeGemini(w ResponseWriter, r *Request) {
|
||||
w.WriteHeader(h.code, h.url)
|
||||
}
|
||||
|
||||
// NotFound replies to the request with a Gemini 51 not found error.
|
||||
func NotFound(w ResponseWriter, r *Request) {
|
||||
w.WriteHeader(StatusNotFound, "Not found")
|
||||
}
|
||||
|
||||
// NotFoundHandler returns a simple request handler that replies to each
|
||||
// request with a “51 Not found” reply.
|
||||
func NotFoundHandler() Handler {
|
||||
return HandlerFunc(NotFound)
|
||||
}
|
||||
|
||||
// StripPrefix returns a handler that serves Gemini requests by removing the
|
||||
// given prefix from the request URL's Path (and RawPath if set) and invoking
|
||||
// the handler h. StripPrefix handles a request for a path that doesn't begin
|
||||
// with prefix by replying with a Gemini 51 not found error. The prefix must
|
||||
// match exactly: if the prefix in the request contains escaped characters the
|
||||
// reply is also a Gemini 51 not found error.
|
||||
func StripPrefix(prefix string, h Handler) Handler {
|
||||
if prefix == "" {
|
||||
return h
|
||||
}
|
||||
return HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||
p := strings.TrimPrefix(r.URL.Path, prefix)
|
||||
rp := strings.TrimPrefix(r.URL.RawPath, prefix)
|
||||
if len(p) < len(r.URL.Path) && (r.URL.RawPath == "" || len(rp) < len(r.URL.RawPath)) {
|
||||
r2 := new(Request)
|
||||
*r2 = *r
|
||||
r2.URL = new(url.URL)
|
||||
*r2.URL = *r.URL
|
||||
r2.URL.Path = p
|
||||
r2.URL.RawPath = rp
|
||||
h.ServeGemini(w, r2)
|
||||
} else {
|
||||
NotFound(w, r)
|
||||
}
|
||||
})
|
||||
}
|
29
server.go
29
server.go
@ -430,32 +430,3 @@ func (srv *Server) logf(format string, args ...interface{}) {
|
||||
log.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// A Handler responds to a Gemini request.
|
||||
//
|
||||
// ServeGemini should write the response header and data to the ResponseWriter
|
||||
// and then return. Returning signals that the request is finished; it is not
|
||||
// valid to use the ResponseWriter after or concurrently with the completion
|
||||
// of the ServeGemini call.
|
||||
//
|
||||
// Handlers should not modify the provided Request.
|
||||
//
|
||||
// If ServeGemini panics, the server (the caller of ServeGemini) assumes that
|
||||
// the effect of the panic was isolated to the active request. It recovers
|
||||
// the panic, logs a stack trace to the server error log, and closes the
|
||||
// network connection. To abort a handler so the client sees an interrupted
|
||||
// response but the server doesn't log an error, panic with the value
|
||||
// ErrAbortHandler.
|
||||
type Handler interface {
|
||||
ServeGemini(ResponseWriter, *Request)
|
||||
}
|
||||
|
||||
// The HandlerFunc type is an adapter to allow the use of ordinary functions
|
||||
// as Gemini handlers. If f is a function with the appropriate signature,
|
||||
// HandlerFunc(f) is a Handler that calls f.
|
||||
type HandlerFunc func(ResponseWriter, *Request)
|
||||
|
||||
// ServeGemini calls f(w, r).
|
||||
func (f HandlerFunc) ServeGemini(w ResponseWriter, r *Request) {
|
||||
f(w, r)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user