github.com/flavio/docker@v0.1.3-0.20170117145210-f63d1a6eec47/api/server/httputils/httputils.go (about) 1 package httputils 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 "strings" 8 9 "golang.org/x/net/context" 10 11 "github.com/docker/docker/api" 12 ) 13 14 // APIVersionKey is the client's requested API version. 15 const APIVersionKey = "api-version" 16 17 // APIFunc is an adapter to allow the use of ordinary functions as Docker API endpoints. 18 // Any function that has the appropriate signature can be registered as an API endpoint (e.g. getVersion). 19 type APIFunc func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error 20 21 // HijackConnection interrupts the http response writer to get the 22 // underlying connection and operate with it. 23 func HijackConnection(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) { 24 conn, _, err := w.(http.Hijacker).Hijack() 25 if err != nil { 26 return nil, nil, err 27 } 28 // Flush the options to make sure the client sets the raw mode 29 conn.Write([]byte{}) 30 return conn, conn, nil 31 } 32 33 // CloseStreams ensures that a list for http streams are properly closed. 34 func CloseStreams(streams ...interface{}) { 35 for _, stream := range streams { 36 if tcpc, ok := stream.(interface { 37 CloseWrite() error 38 }); ok { 39 tcpc.CloseWrite() 40 } else if closer, ok := stream.(io.Closer); ok { 41 closer.Close() 42 } 43 } 44 } 45 46 // CheckForJSON makes sure that the request's Content-Type is application/json. 47 func CheckForJSON(r *http.Request) error { 48 ct := r.Header.Get("Content-Type") 49 50 // No Content-Type header is ok as long as there's no Body 51 if ct == "" { 52 if r.Body == nil || r.ContentLength == 0 { 53 return nil 54 } 55 } 56 57 // Otherwise it better be json 58 if api.MatchesContentType(ct, "application/json") { 59 return nil 60 } 61 return fmt.Errorf("Content-Type specified (%s) must be 'application/json'", ct) 62 } 63 64 // ParseForm ensures the request form is parsed even with invalid content types. 65 // If we don't do this, POST method without Content-type (even with empty body) will fail. 66 func ParseForm(r *http.Request) error { 67 if r == nil { 68 return nil 69 } 70 if err := r.ParseForm(); err != nil && !strings.HasPrefix(err.Error(), "mime:") { 71 return err 72 } 73 return nil 74 } 75 76 // VersionFromContext returns an API version from the context using APIVersionKey. 77 // It panics if the context value does not have version.Version type. 78 func VersionFromContext(ctx context.Context) string { 79 if ctx == nil { 80 return "" 81 } 82 83 if val := ctx.Value(APIVersionKey); val != nil { 84 return val.(string) 85 } 86 87 return "" 88 }