func NewHTTPError(code int, msg ...string) *HTTPError { he := &HTTPError{code: code, message: fasthttp.StatusMessage(code)} if len(msg) > 0 { m := msg[0] he.message = m } return he }
// BasicAuth is the basic auth handler func BasicAuth(h fasthttprouter.Handle, user, pass []byte) fasthttprouter.Handle { return fasthttprouter.Handle(func(ctx *fasthttp.RequestCtx, ps fasthttprouter.Params) { // Get the Basic Authentication credentials auth := ctx.Request.Header.Peek("Authorization") if bytes.HasPrefix(auth, basicAuthPrefix) { // Check credentials payload, err := base64.StdEncoding.DecodeString(string(auth[len(basicAuthPrefix):])) if err == nil { pair := bytes.SplitN(payload, []byte(":"), 2) if len(pair) == 2 && bytes.Equal(pair[0], user) && bytes.Equal(pair[1], pass) { // Delegate request to the given handle h(ctx, ps) return } } } // Request Basic Authentication otherwise ctx.Response.Header.Set("WWW-Authenticate", "Basic realm=Restricted") ctx.Error(fasthttp.StatusMessage(fasthttp.StatusUnauthorized), fasthttp.StatusUnauthorized) }) }
func New() (g *Goka) { g = &Goka{maxParam: new(int)} g.pool.New = func() interface{} { return NewContext(nil, g) } g.router = NewRouter(g) g.defaultHTTPErrorHandler = func(err error, c *Context) { code := fasthttp.StatusInternalServerError msg := fasthttp.StatusMessage(code) if he, ok := err.(*HTTPError); ok { code = he.code msg = he.message } if g.debug { msg = err.Error() } c.RequestCtx().Error(msg, code) return } g.SetHTTPErrorHandler(g.defaultHTTPErrorHandler) return }
// Handler makes the router implement the fasthttp.ListenAndServe interface. func (r *Router) Handler(ctx *fasthttp.RequestCtx) { if r.PanicHandler != nil { defer r.recv(ctx) } method := string(ctx.Method()) if root := r.trees[method]; root != nil { path := string(ctx.Path()) if f, ps, tsr := root.getValue(path); f != nil { f(ctx, ps) return } else if method != "CONNECT" && path != "/" { code := 301 // Permanent redirect, request with GET method if method != "GET" { // Temporary redirect, request with same method // As of Go 1.3, Go does not support status code 308. code = 307 } if tsr && r.RedirectTrailingSlash { var uri string if len(path) > 1 && path[len(path)-1] == '/' { uri = path[:len(path)-1] } else { uri = path + "/" } ctx.Redirect(uri, code) return } // Try to fix the request path if r.RedirectFixedPath { fixedPath, found := root.findCaseInsensitivePath( CleanPath(path), r.RedirectTrailingSlash, ) if found { uri := string(fixedPath) ctx.Redirect(uri, code) return } } } } // Handle 405 if r.HandleMethodNotAllowed { for method := range r.trees { // Skip the requested method - we already tried this one if method == string(ctx.Method()) { continue } f, _, _ := r.trees[method].getValue(string(ctx.Path())) if f != nil { if r.MethodNotAllowed != nil { r.MethodNotAllowed(ctx) } else { ctx.Error(fasthttp.StatusMessage(fasthttp.StatusMethodNotAllowed), fasthttp.StatusMethodNotAllowed) } return } } } // Handle 404 if r.NotFound != nil { r.NotFound(ctx) } else { ctx.Error(fasthttp.StatusMessage(fasthttp.StatusNotFound), fasthttp.StatusNotFound) } }
// Handler makes the router implement the fasthttp.ListenAndServe interface. func (r *Router) Handler(ctx *fasthttp.RequestCtx) { if r.PanicHandler != nil { defer r.recv(ctx) } path := string(ctx.Path()) method := string(ctx.Method()) if root := r.trees[method]; root != nil { if f, ps, tsr := root.getValue(path); f != nil { f(ctx, ps) return } else if method != "CONNECT" && path != "/" { code := 301 // Permanent redirect, request with GET method if method != "GET" { // Temporary redirect, request with same method // As of Go 1.3, Go does not support status code 308. code = 307 } if tsr && r.RedirectTrailingSlash { var uri string if len(path) > 1 && path[len(path)-1] == '/' { uri = path[:len(path)-1] } else { uri = path + "/" } ctx.Redirect(uri, code) return } // Try to fix the request path if r.RedirectFixedPath { fixedPath, found := root.findCaseInsensitivePath( CleanPath(path), r.RedirectTrailingSlash, ) if found { uri := string(fixedPath) ctx.Redirect(uri, code) return } } } } if method == "OPTIONS" { // Handle OPTIONS requests if r.HandleOPTIONS { if allow := r.allowed(path, method); len(allow) > 0 { ctx.Response.Header.Set("Allow", allow) return } } } else { // Handle 405 if r.HandleMethodNotAllowed { if allow := r.allowed(path, method); len(allow) > 0 { ctx.Response.Header.Set("Allow", allow) if r.MethodNotAllowed != nil { r.MethodNotAllowed(ctx) } else { ctx.SetStatusCode(fasthttp.StatusMethodNotAllowed) ctx.SetContentTypeBytes(defaultContentType) ctx.SetBodyString(fasthttp.StatusMessage(fasthttp.StatusMethodNotAllowed)) } return } } } // Handle 404 if r.NotFound != nil { r.NotFound(ctx) } else { ctx.Error(fasthttp.StatusMessage(fasthttp.StatusNotFound), fasthttp.StatusNotFound) } }