2018-06-20 07:12:03 +00:00
|
|
|
package pipelining
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
2019-03-18 10:30:07 +00:00
|
|
|
"context"
|
2018-06-20 07:12:03 +00:00
|
|
|
"net"
|
|
|
|
"net/http"
|
2019-03-18 10:30:07 +00:00
|
|
|
|
2019-09-13 17:28:04 +00:00
|
|
|
"github.com/containous/traefik/v2/pkg/log"
|
2019-08-03 01:58:23 +00:00
|
|
|
"github.com/containous/traefik/v2/pkg/middlewares"
|
2019-03-18 10:30:07 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
typeName = "Pipelining"
|
2018-06-20 07:12:03 +00:00
|
|
|
)
|
|
|
|
|
2019-03-18 10:30:07 +00:00
|
|
|
// pipelining returns a middleware
|
|
|
|
type pipelining struct {
|
2018-06-20 07:12:03 +00:00
|
|
|
next http.Handler
|
|
|
|
}
|
|
|
|
|
2019-03-18 10:30:07 +00:00
|
|
|
// New returns a new pipelining instance
|
|
|
|
func New(ctx context.Context, next http.Handler, name string) http.Handler {
|
2019-09-13 17:28:04 +00:00
|
|
|
log.FromContext(middlewares.GetLoggerCtx(ctx, name, typeName)).Debug("Creating middleware")
|
2019-03-18 10:30:07 +00:00
|
|
|
|
|
|
|
return &pipelining{
|
2018-06-20 07:12:03 +00:00
|
|
|
next: next,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-18 10:30:07 +00:00
|
|
|
func (p *pipelining) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
2018-06-20 07:12:03 +00:00
|
|
|
// https://github.com/golang/go/blob/3d59583836630cf13ec4bfbed977d27b1b7adbdc/src/net/http/server.go#L201-L218
|
|
|
|
if r.Method == http.MethodPut || r.Method == http.MethodPost {
|
|
|
|
p.next.ServeHTTP(rw, r)
|
|
|
|
} else {
|
|
|
|
p.next.ServeHTTP(&writerWithoutCloseNotify{rw}, r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// writerWithoutCloseNotify helps to disable closeNotify
|
|
|
|
type writerWithoutCloseNotify struct {
|
|
|
|
W http.ResponseWriter
|
|
|
|
}
|
|
|
|
|
|
|
|
// Header returns the response headers.
|
|
|
|
func (w *writerWithoutCloseNotify) Header() http.Header {
|
|
|
|
return w.W.Header()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write writes the data to the connection as part of an HTTP reply.
|
|
|
|
func (w *writerWithoutCloseNotify) Write(buf []byte) (int, error) {
|
|
|
|
return w.W.Write(buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteHeader sends an HTTP response header with the provided
|
|
|
|
// status code.
|
|
|
|
func (w *writerWithoutCloseNotify) WriteHeader(code int) {
|
|
|
|
w.W.WriteHeader(code)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Flush sends any buffered data to the client.
|
|
|
|
func (w *writerWithoutCloseNotify) Flush() {
|
|
|
|
if f, ok := w.W.(http.Flusher); ok {
|
|
|
|
f.Flush()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hijack hijacks the connection.
|
|
|
|
func (w *writerWithoutCloseNotify) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
|
|
|
return w.W.(http.Hijacker).Hijack()
|
|
|
|
}
|