Allow registry clients to connect via http2

Http2 will be enabled by default and can be disabled with a configuration option.

Signed-off-by: Adam Duke <adam.v.duke@gmail.com>
This commit is contained in:
Adam Duke 2016-07-14 15:48:03 -04:00
parent c9fd26e9ef
commit ac009c86f1
5 changed files with 82 additions and 1 deletions

View file

@ -123,6 +123,13 @@ type Configuration struct {
// Addr specifies the bind address for the debug server. // Addr specifies the bind address for the debug server.
Addr string `yaml:"addr,omitempty"` Addr string `yaml:"addr,omitempty"`
} `yaml:"debug,omitempty"` } `yaml:"debug,omitempty"`
// HTTP2 configuration options
HTTP2 struct {
// Specifies wether the registry should disallow clients attempting
// to connect via http2. If set to true, only http/1.1 is supported.
Disabled bool `yaml:"disabled,omitempty"`
} `yaml:"http2,omitempty"`
} `yaml:"http,omitempty"` } `yaml:"http,omitempty"`
// Notifications specifies configuration about various endpoint to which // Notifications specifies configuration about various endpoint to which

View file

@ -82,6 +82,9 @@ var configStruct = Configuration{
Debug struct { Debug struct {
Addr string `yaml:"addr,omitempty"` Addr string `yaml:"addr,omitempty"`
} `yaml:"debug,omitempty"` } `yaml:"debug,omitempty"`
HTTP2 struct {
Disabled bool `yaml:"disabled,omitempty"`
} `yaml:"http2,omitempty"`
}{ }{
TLS: struct { TLS: struct {
Certificate string `yaml:"certificate,omitempty"` Certificate string `yaml:"certificate,omitempty"`
@ -97,6 +100,11 @@ var configStruct = Configuration{
Headers: http.Header{ Headers: http.Header{
"X-Content-Type-Options": []string{"nosniff"}, "X-Content-Type-Options": []string{"nosniff"},
}, },
HTTP2: struct {
Disabled bool `yaml:"disabled,omitempty"`
}{
Disabled: false,
},
}, },
} }

View file

@ -198,6 +198,8 @@ information about each option that appears later in this page.
addr: localhost:5001 addr: localhost:5001
headers: headers:
X-Content-Type-Options: [nosniff] X-Content-Type-Options: [nosniff]
http2:
disabled: false
notifications: notifications:
endpoints: endpoints:
- name: alistener - name: alistener
@ -910,6 +912,8 @@ configuration may contain both.
addr: localhost:5001 addr: localhost:5001
headers: headers:
X-Content-Type-Options: [nosniff] X-Content-Type-Options: [nosniff]
http2:
disabled: false
The `http` option details the configuration for the HTTP server that hosts the registry. The `http` option details the configuration for the HTTP server that hosts the registry.
@ -1112,6 +1116,29 @@ Including `X-Content-Type-Options: [nosniff]` is recommended, so that browsers
will not interpret content as HTML if they are directed to load a page from the will not interpret content as HTML if they are directed to load a page from the
registry. This header is included in the example configuration files. registry. This header is included in the example configuration files.
### http2
The `http2` struct within `http` is **optional**. Use this to control http2
settings for the registry.
<table>
<tr>
<th>Parameter</th>
<th>Required</th>
<th>Description</th>
</tr>
<tr>
<td>
<code>disabled</code>
</td>
<td>
no
</td>
<td>
A boolean that determines if http2 support should be disabled
</td>
</tr>
</table>
## notifications ## notifications

View file

@ -116,7 +116,7 @@ func (registry *Registry) ListenAndServe() error {
if config.HTTP.TLS.Certificate != "" || config.HTTP.TLS.LetsEncrypt.CacheFile != "" { if config.HTTP.TLS.Certificate != "" || config.HTTP.TLS.LetsEncrypt.CacheFile != "" {
tlsConf := &tls.Config{ tlsConf := &tls.Config{
ClientAuth: tls.NoClientCert, ClientAuth: tls.NoClientCert,
NextProtos: []string{"http/1.1"}, NextProtos: nextProtos(config),
MinVersion: tls.VersionTLS10, MinVersion: tls.VersionTLS10,
PreferServerCipherSuites: true, PreferServerCipherSuites: true,
CipherSuites: []uint16{ CipherSuites: []uint16{
@ -343,3 +343,12 @@ func resolveConfiguration(args []string) (*configuration.Configuration, error) {
return config, nil return config, nil
} }
func nextProtos(config *configuration.Configuration) []string {
switch config.HTTP.HTTP2.Disabled {
case true:
return []string{"http/1.1"}
default:
return []string{"h2", "http/1.1"}
}
}

30
registry/registry_test.go Normal file
View file

@ -0,0 +1,30 @@
package registry
import (
"reflect"
"testing"
"github.com/docker/distribution/configuration"
)
// Tests to ensure nextProtos returns the correct protocols when:
// * config.HTTP.HTTP2.Disabled is not explicitly set => [h2 http/1.1]
// * config.HTTP.HTTP2.Disabled is explicitly set to false [h2 http/1.1]
// * config.HTTP.HTTP2.Disabled is explicitly set to true [http/1.1]
func TestNextProtos(t *testing.T) {
config := &configuration.Configuration{}
protos := nextProtos(config)
if !reflect.DeepEqual(protos, []string{"h2", "http/1.1"}) {
t.Fatalf("expected protos to equal [h2 http/1.1], got %s", protos)
}
config.HTTP.HTTP2.Disabled = false
protos = nextProtos(config)
if !reflect.DeepEqual(protos, []string{"h2", "http/1.1"}) {
t.Fatalf("expected protos to equal [h2 http/1.1], got %s", protos)
}
config.HTTP.HTTP2.Disabled = true
protos = nextProtos(config)
if !reflect.DeepEqual(protos, []string{"http/1.1"}) {
t.Fatalf("expected protos to equal [http/1.1], got %s", protos)
}
}