func (sbf *StringBodyFilter) FilterRequest(request *falcore.Request) *http.Response { req := request.HttpRequest // This caches the request body so that multiple filters can iterate it if req.Method == "POST" || req.Method == "PUT" { sb, err := sbf.readRequestBody(req) if sb == nil || err != nil { request.CurrentStage.Status = 3 // Skip falcore.Debug("%s No Req Body or Ignored: %v", request.ID, err) } } else { request.CurrentStage.Status = 1 // Skip } return nil }
func (f *FileFilter) FilterRequest(req *falcore.Request) (res *http.Response) { // Clean asset path asset_path := filepath.Clean(filepath.FromSlash(req.HttpRequest.URL.Path)) // Resolve PathPrefix if strings.HasPrefix(asset_path, f.PathPrefix) { asset_path = asset_path[len(f.PathPrefix):] } else { falcore.Debug("%v doesn't match prefix %v", asset_path, f.PathPrefix) res = falcore.StringResponse(req.HttpRequest, 404, nil, "Not found.") return } // Resolve FSBase if f.BasePath != "" { asset_path = filepath.Join(f.BasePath, asset_path) } else { falcore.Error("file_filter requires a BasePath") return falcore.StringResponse(req.HttpRequest, 500, nil, "Server Error\n") } // Open File if file, err := os.Open(asset_path); err == nil { // Make sure it's an actual file if stat, err := file.Stat(); err == nil && stat.Mode()&os.ModeType == 0 { res = &http.Response{ Request: req.HttpRequest, StatusCode: 200, Proto: "HTTP/1.1", ProtoMajor: 1, ProtoMinor: 1, Body: file, Header: make(http.Header), ContentLength: stat.Size(), } if ct := mime.TypeByExtension(filepath.Ext(asset_path)); ct != "" { res.Header.Set("Content-Type", ct) } } else { file.Close() } } else { falcore.Finest("Can't open %v: %v", asset_path, err) } return }
func (u *Upstream) FilterRequest(request *falcore.Request) (res *http.Response) { var err error req := request.HttpRequest if u.Name != "" { request.CurrentStage.Name = fmt.Sprintf("%s[%s]", request.CurrentStage.Name, u.Name) } // Throttle // Wait for an opening, then increment in flight counter u.throttleC.L.Lock() u.throttleQueue += 1 for u.throttleMax > 0 && u.throttleInFlight >= u.throttleMax { u.throttleC.Wait() } u.throttleQueue -= 1 u.throttleInFlight += 1 u.throttleC.L.Unlock() // Decrement and signal when done defer func() { u.throttleC.L.Lock() u.throttleInFlight -= 1 u.throttleC.Signal() u.throttleC.L.Unlock() }() // Force the upstream to use http if u.ForceHttp || req.URL.Scheme == "" { req.URL.Scheme = "http" req.URL.Host = req.Host } before := time.Now() req.Header.Set("Connection", "Keep-Alive") var upstrRes *http.Response upstrRes, err = u.Transport.transport.RoundTrip(req) diff := falcore.TimeDiff(before, time.Now()) if err == nil { // Copy response over to new record. Remove connection noise. Add some sanity. res = falcore.StringResponse(req, upstrRes.StatusCode, nil, "") if upstrRes.ContentLength > 0 { res.ContentLength = upstrRes.ContentLength res.Body = upstrRes.Body } else if res.ContentLength == -1 { res.Body = upstrRes.Body res.ContentLength = -1 res.TransferEncoding = []string{"chunked"} } else { // Any bytes? var testBuf [1]byte n, _ := io.ReadFull(upstrRes.Body, testBuf[:]) if n == 1 { // Yes there are. Chunked it is. res.TransferEncoding = []string{"chunked"} res.ContentLength = -1 rc := &passThruReadCloser{ io.MultiReader(bytes.NewBuffer(testBuf[:]), upstrRes.Body), upstrRes.Body, } res.Body = rc } else { // There was an error reading the body upstrRes.Body.Close() res.ContentLength = 0 res.Body = nil } } // Copy over headers with a few exceptions res.Header = make(http.Header) for hn, hv := range upstrRes.Header { switch hn { case "Content-Length": case "Connection": case "Transfer-Encoding": default: res.Header[hn] = hv } } } else { if nerr, ok := err.(net.Error); ok && nerr.Timeout() { falcore.Error("%s [%s] Upstream Timeout error: %v", request.ID, u.Name, err) res = falcore.StringResponse(req, 504, nil, "Gateway Timeout\n") request.CurrentStage.Status = 2 // Fail } else { falcore.Error("%s [%s] Upstream error: %v", request.ID, u.Name, err) res = falcore.StringResponse(req, 502, nil, "Bad Gateway\n") request.CurrentStage.Status = 2 // Fail } } falcore.Debug("%s %s [%s] [%s] %s s=%d Time=%.4f", request.ID, u.Name, req.Method, u.Transport.host, req.URL, res.StatusCode, diff) return }