// ServeHTTP is called whenever there is a new request. // This is quite similar to JavaEE Servlet interface. func (h *MyHandler) ServeHTTP(ctx *fasthttp.RequestCtx) { // In the future we can use requester can detect request spammers! // requester := ctx.RemoteAddr() // Increase request count count := &(h.requests) atomic.AddUint64(count, 1) if ctx.IsGet() { url := ctx.URI() operations, format, err, invalid := ParseURI(url, h.imageSource, h.watermarker) if err != nil { ctx.NotFound() logging.Debug(err) return } if invalid != nil { ctx.Error(invalid.Error(), 400) return } blob, err := h.operator.GetBlob(operations...) if err != nil { ctx.NotFound() logging.Debug(err) } else { ctx.SetContentType("image/" + format) ctx.Write(blob) logging.Debug("Blob returned") } } else if ctx.IsPost() { // POST is currently unused so we can use this for testing h.RetrieveHello(ctx) logging.Debug("Post request received") } }
// GetAuthorizeRequest 获取授权请求参数 func (fs *FastServer) GetAuthorizeRequest(ctx *fasthttp.RequestCtx) (authReq *AuthorizeRequest, err error) { if !ctx.IsGet() { err = ErrRequestMethodInvalid return } redirectURI, err := url.QueryUnescape(string(ctx.FormValue("redirect_uri"))) if err != nil { return } authReq = &AuthorizeRequest{ Type: oauth2.ResponseType(string(ctx.FormValue("response_type"))), RedirectURI: redirectURI, State: string(ctx.FormValue("state")), Scope: string(ctx.FormValue("scope")), ClientID: string(ctx.FormValue("client_id")), } if authReq.Type == "" || !fs.checkResponseType(authReq.Type) { err = ErrResponseTypeInvalid } else if authReq.ClientID == "" { err = ErrClientInvalid } return }
func requestHandler(ctx *fasthttp.RequestCtx) { h := &ctx.Request.Header if !ctx.IsGet() { ctx.Error("Method not allowed", fasthttp.StatusMethodNotAllowed) return } if string(ctx.RequestURI()) == *statsRequestPath { var w bytes.Buffer stats.WriteToStream(&w) ctx.Success("text/plain", w.Bytes()) return } if len(h.Peek("If-None-Match")) > 0 { resp := &ctx.Response resp.SetStatusCode(fasthttp.StatusNotModified) resp.Header.Set("Etag", "W/\"CacheForever\"") atomic.AddInt64(&stats.IfNoneMatchHitsCount, 1) return } v := keyPool.Get() if v == nil { v = make([]byte, 128) } key := v.([]byte) key = append(key[:0], getRequestHost(h)...) key = append(key, ctx.RequestURI()...) item, err := cache.GetDeItem(key, time.Second) if err != nil { if err != ybc.ErrCacheMiss { logFatal("Unexpected error when obtaining cache value by key=[%s]: [%s]", key, err) } atomic.AddInt64(&stats.CacheMissesCount, 1) item = fetchFromUpstream(h, key) if item == nil { ctx.Error("Service unavailable", fasthttp.StatusServiceUnavailable) return } } else { atomic.AddInt64(&stats.CacheHitsCount, 1) } defer item.Close() keyPool.Put(v) contentType, err := loadContentType(h, item) if err != nil { ctx.Error("Internal Server Error", fasthttp.StatusInternalServerError) return } rh := &ctx.Response.Header rh.Set("Etag", "W/\"CacheForever\"") rh.Set("Cache-Control", "public, max-age=31536000") buf := item.Value() buf = buf[len(buf)-item.Available():] ctx.Success(contentType, buf) atomic.AddInt64(&stats.BytesSentToClients, int64(len(buf))) }