func (mux *serveMux) ServeRequest() fasthttp.RequestHandler { // initialize the router once mux.build() // optimize this once once, we could do that: context.RequestPath(mux.escapePath), but we lose some nanoseconds on if :) getRequestPath := func(reqCtx *fasthttp.RequestCtx) string { return utils.BytesToString(reqCtx.Path()) } if !mux.escapePath { getRequestPath = func(reqCtx *fasthttp.RequestCtx) string { return utils.BytesToString(reqCtx.RequestURI()) } } return func(reqCtx *fasthttp.RequestCtx) { context := mux.cPool.Get().(*Context) context.Reset(reqCtx) routePath := getRequestPath(reqCtx) tree := mux.tree for tree != nil { if !bytes.Equal(tree.method, reqCtx.Method()) { // we break any CORS OPTIONS method // but for performance reasons if user wants http method OPTIONS to be served // then must register it with .Options(...) tree = tree.next continue } // we have at least one subdomain on the root if mux.hosts && tree.subdomain != "" { // context.VirtualHost() is a slow method because it makes string.Replaces but user can understand that if subdomain then server will have some nano/or/milleseconds performance cost requestHost := context.VirtualHostname() if requestHost != mux.hostname { // we have a subdomain if strings.Index(tree.subdomain, dynamicSubdomainIndicator) != -1 { } else { // mux.host = iris-go.com:8080, the subdomain for example is api., // so the host must be api.iris-go.com:8080 if tree.subdomain+mux.hostname != requestHost { // go to the next tree, we have a subdomain but it is not the correct tree = tree.next continue } } } else { //("it's subdomain but the request is the same as the listening addr mux.host == requestHost =>" + mux.host + "=" + requestHost + " ____ and tree's subdomain was: " + tree.subdomain) tree = tree.next continue } } middleware, params, mustRedirect := tree.entry.get(routePath, context.Params) // pass the parameters here for 0 allocation if middleware != nil { // ok we found the correct route, serve it and exit entirely from here context.Params = params context.middleware = middleware //ctx.Request.Header.SetUserAgentBytes(DefaultUserAgent) context.Do() mux.cPool.Put(context) return } else if mustRedirect && mux.correctPath && !bytes.Equal(reqCtx.Method(), methodConnectBytes) { reqPath := routePath pathLen := len(reqPath) if pathLen > 1 { if reqPath[pathLen-1] == '/' { reqPath = reqPath[:pathLen-1] //remove the last / } else { //it has path prefix, it doesn't ends with / and it hasn't be found, then just add the slash reqPath = reqPath + "/" } context.Request.URI().SetPath(reqPath) urlToRedirect := utils.BytesToString(context.Request.RequestURI()) context.Redirect(urlToRedirect, StatusMovedPermanently) // StatusMovedPermanently // RFC2616 recommends that a short note "SHOULD" be included in the // response because older user agents may not understand 301/307. // Shouldn't send the response for POST or HEAD; that leaves GET. if bytes.Equal(tree.method, methodGetBytes) { note := "<a href=\"" + utils.HTMLEscape(urlToRedirect) + "\">Moved Permanently</a>.\n" context.Write(note) } mux.cPool.Put(context) return } } // not found break } mux.fireError(StatusNotFound, context) mux.cPool.Put(context) } }
// RequestHeader returns the request header's value // accepts one parameter, the key of the header (string) // returns string func (ctx *Context) RequestHeader(k string) string { return utils.BytesToString(ctx.RequestCtx.Request.Header.Peek(k)) }
// HostString returns the Host of the request( the url as string ) func (ctx *Context) HostString() string { return utils.BytesToString(ctx.Host()) }
// RequestPath returns the requested path func (ctx *Context) RequestPath(escape bool) string { if escape { return utils.BytesToString(ctx.RequestCtx.Path()) } return utils.BytesToString(ctx.RequestCtx.RequestURI()) }
// MethodString returns the HTTP Method func (ctx *Context) MethodString() string { return utils.BytesToString(ctx.Method()) }