Merge pull request #1782 from tianon/accept-lists
Update "Accept" header parsing for list valuesmaster
						commit
						05083bbef8
					
				| 
						 | 
					@ -1586,8 +1586,8 @@ func testManifestAPIManifestList(t *testing.T, env *testEnv, args manifestArgs)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatalf("Error constructing request: %s", err)
 | 
							t.Fatalf("Error constructing request: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	req.Header.Set("Accept", manifestlist.MediaTypeManifestList)
 | 
						// multiple headers in mixed list format to ensure we parse correctly server-side
 | 
				
			||||||
	req.Header.Add("Accept", schema1.MediaTypeSignedManifest)
 | 
						req.Header.Set("Accept", fmt.Sprintf(` %s ; q=0.8 , %s ; q=0.5 `, manifestlist.MediaTypeManifestList, schema1.MediaTypeSignedManifest))
 | 
				
			||||||
	req.Header.Add("Accept", schema2.MediaTypeManifest)
 | 
						req.Header.Add("Accept", schema2.MediaTypeManifest)
 | 
				
			||||||
	resp, err = http.DefaultClient.Do(req)
 | 
						resp, err = http.DefaultClient.Do(req)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/docker/distribution"
 | 
						"github.com/docker/distribution"
 | 
				
			||||||
	ctxu "github.com/docker/distribution/context"
 | 
						ctxu "github.com/docker/distribution/context"
 | 
				
			||||||
| 
						 | 
					@ -98,8 +99,23 @@ func (imh *imageManifestHandler) GetImageManifest(w http.ResponseWriter, r *http
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	supportsSchema2 := false
 | 
						supportsSchema2 := false
 | 
				
			||||||
	supportsManifestList := false
 | 
						supportsManifestList := false
 | 
				
			||||||
	if acceptHeaders, ok := r.Header["Accept"]; ok {
 | 
						// this parsing of Accept headers is not quite as full-featured as godoc.org's parser, but we don't care about "q=" values
 | 
				
			||||||
		for _, mediaType := range acceptHeaders {
 | 
						// https://github.com/golang/gddo/blob/e91d4165076d7474d20abda83f92d15c7ebc3e81/httputil/header/header.go#L165-L202
 | 
				
			||||||
 | 
						for _, acceptHeader := range r.Header["Accept"] {
 | 
				
			||||||
 | 
							// r.Header[...] is a slice in case the request contains the same header more than once
 | 
				
			||||||
 | 
							// if the header isn't set, we'll get the zero value, which "range" will handle gracefully
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// we need to split each header value on "," to get the full list of "Accept" values (per RFC 2616)
 | 
				
			||||||
 | 
							// https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
 | 
				
			||||||
 | 
							for _, mediaType := range strings.Split(acceptHeader, ",") {
 | 
				
			||||||
 | 
								// remove "; q=..." if present
 | 
				
			||||||
 | 
								if i := strings.Index(mediaType, ";"); i >= 0 {
 | 
				
			||||||
 | 
									mediaType = mediaType[:i]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// it's common (but not required) for Accept values to be space separated ("a/b, c/d, e/f")
 | 
				
			||||||
 | 
								mediaType = strings.TrimSpace(mediaType)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if mediaType == schema2.MediaTypeManifest {
 | 
								if mediaType == schema2.MediaTypeManifest {
 | 
				
			||||||
				supportsSchema2 = true
 | 
									supportsSchema2 = true
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue