traefik/vendor/github.com/vulcand/oxy/stream/stream.go

93 lines
2.3 KiB
Go
Raw Normal View History

2017-02-07 21:33:23 +00:00
/*
2017-11-22 17:20:03 +00:00
package stream provides http.Handler middleware that passes-through the entire request
2017-02-07 21:33:23 +00:00
2017-11-22 17:20:03 +00:00
Stream works around several limitations caused by buffering implementations, but
also introduces certain risks.
Workarounds for buffering limitations:
1. Streaming really large chunks of data (large file transfers, or streaming videos,
etc.)
2. Streaming (chunking) sparse data. For example, an implementation might
send a health check or a heart beat over a long-lived connection. This
does not play well with buffering.
Risks:
1. Connections could survive for very long periods of time.
2. There is no easy way to enforce limits on size/time of a connection.
2017-02-07 21:33:23 +00:00
Examples of a streaming middleware:
// sample HTTP handler
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("hello"))
})
2017-11-22 17:20:03 +00:00
// Stream will literally pass through to the next handler without ANY buffering
// or validation of the data.
2017-02-07 21:33:23 +00:00
stream.New(handler)
*/
package stream
import (
"net/http"
2017-11-22 17:20:03 +00:00
log "github.com/Sirupsen/logrus"
2017-02-07 21:33:23 +00:00
"github.com/vulcand/oxy/utils"
)
const (
// No limit by default
DefaultMaxBodyBytes = -1
)
2017-11-22 17:20:03 +00:00
// Stream is responsible for buffering requests and responses
// It buffers large requests and responses to disk,
type Stream struct {
2017-02-07 21:33:23 +00:00
maxRequestBodyBytes int64
maxResponseBodyBytes int64
retryPredicate hpredicate
next http.Handler
errHandler utils.ErrorHandler
}
// New returns a new streamer middleware. New() function supports optional functional arguments
2017-11-22 17:20:03 +00:00
func New(next http.Handler, setters ...optSetter) (*Stream, error) {
strm := &Stream{
2017-02-07 21:33:23 +00:00
next: next,
maxRequestBodyBytes: DefaultMaxBodyBytes,
maxResponseBodyBytes: DefaultMaxBodyBytes,
}
for _, s := range setters {
if err := s(strm); err != nil {
return nil, err
}
}
return strm, nil
}
2017-11-22 17:20:03 +00:00
type optSetter func(s *Stream) error
2017-02-07 21:33:23 +00:00
// Wrap sets the next handler to be called by stream handler.
2017-11-22 17:20:03 +00:00
func (s *Stream) Wrap(next http.Handler) error {
2017-02-07 21:33:23 +00:00
s.next = next
return nil
}
2017-11-22 17:20:03 +00:00
func (s *Stream) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if log.GetLevel() >= log.DebugLevel {
logEntry := log.WithField("Request", utils.DumpHttpRequest(req))
logEntry.Debug("vulcand/oxy/stream: begin ServeHttp on request")
defer logEntry.Debug("vulcand/oxy/stream: competed ServeHttp on request")
2017-02-07 21:33:23 +00:00
}
2017-11-22 17:20:03 +00:00
s.next.ServeHTTP(w, req)
2017-02-07 21:33:23 +00:00
}