forked from TrueCloudLab/distribution
Add http.host parameter
This allows the administrator to specify an externally-reachable URL for the registry. It takes precedence over the X-Forwarded-Proto and X-Forwarded-Host headers, and the hostname in the request. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
5a8fabfee3
commit
6573d5c119
2 changed files with 58 additions and 9 deletions
|
@ -160,6 +160,7 @@ func TestBuilderFromRequest(t *testing.T) {
|
|||
testRequests := []struct {
|
||||
request *http.Request
|
||||
base string
|
||||
configHost url.URL
|
||||
}{
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host},
|
||||
|
@ -177,10 +178,23 @@ func TestBuilderFromRequest(t *testing.T) {
|
|||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedHostHeader2},
|
||||
base: "http://first.example.com",
|
||||
},
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedHostHeader2},
|
||||
base: "https://third.example.com:5000",
|
||||
configHost: url.URL{
|
||||
Scheme: "https",
|
||||
Host: "third.example.com:5000",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tr := range testRequests {
|
||||
builder := NewURLBuilderFromRequest(tr.request)
|
||||
var builder *URLBuilder
|
||||
if tr.configHost.Scheme != "" && tr.configHost.Host != "" {
|
||||
builder = NewURLBuilder(&tr.configHost)
|
||||
} else {
|
||||
builder = NewURLBuilderFromRequest(tr.request)
|
||||
}
|
||||
|
||||
for _, testCase := range makeURLBuilderTestCases(builder) {
|
||||
url, err := testCase.build()
|
||||
|
@ -209,6 +223,7 @@ func TestBuilderFromRequestWithPrefix(t *testing.T) {
|
|||
testRequests := []struct {
|
||||
request *http.Request
|
||||
base string
|
||||
configHost url.URL
|
||||
}{
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host},
|
||||
|
@ -218,10 +233,23 @@ func TestBuilderFromRequestWithPrefix(t *testing.T) {
|
|||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader},
|
||||
base: "https://example.com/prefix/",
|
||||
},
|
||||
{
|
||||
request: &http.Request{URL: u, Host: u.Host, Header: forwardedProtoHeader},
|
||||
base: "https://subdomain.example.com/prefix/",
|
||||
configHost: url.URL{
|
||||
Scheme: "https",
|
||||
Host: "subdomain.example.com/prefix",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tr := range testRequests {
|
||||
builder := NewURLBuilderFromRequest(tr.request)
|
||||
var builder *URLBuilder
|
||||
if tr.configHost.Scheme != "" && tr.configHost.Host != "" {
|
||||
builder = NewURLBuilder(&tr.configHost)
|
||||
} else {
|
||||
builder = NewURLBuilderFromRequest(tr.request)
|
||||
}
|
||||
|
||||
for _, testCase := range makeURLBuilderTestCases(builder) {
|
||||
url, err := testCase.build()
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
|
@ -54,6 +55,10 @@ type App struct {
|
|||
registry distribution.Namespace // registry is the primary registry backend for the app instance.
|
||||
accessController auth.AccessController // main access controller for application
|
||||
|
||||
// httpHost is a parsed representation of the http.host parameter from
|
||||
// the configuration. Only the Scheme and Host fields are used.
|
||||
httpHost url.URL
|
||||
|
||||
// events contains notification related configuration.
|
||||
events struct {
|
||||
sink notifications.Sink
|
||||
|
@ -120,6 +125,14 @@ func NewApp(ctx context.Context, configuration *configuration.Configuration) *Ap
|
|||
app.configureRedis(configuration)
|
||||
app.configureLogHook(configuration)
|
||||
|
||||
if configuration.HTTP.Host != "" {
|
||||
u, err := url.Parse(configuration.HTTP.Host)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf(`could not parse http "host" parameter: %v`, err))
|
||||
}
|
||||
app.httpHost = *u
|
||||
}
|
||||
|
||||
options := []storage.RegistryOption{}
|
||||
|
||||
if app.isCache {
|
||||
|
@ -641,7 +654,15 @@ func (app *App) context(w http.ResponseWriter, r *http.Request) *Context {
|
|||
context := &Context{
|
||||
App: app,
|
||||
Context: ctx,
|
||||
urlBuilder: v2.NewURLBuilderFromRequest(r),
|
||||
}
|
||||
|
||||
if app.httpHost.Scheme != "" && app.httpHost.Host != "" {
|
||||
// A "host" item in the configuration takes precedence over
|
||||
// X-Forwarded-Proto and X-Forwarded-Host headers, and the
|
||||
// hostname in the request.
|
||||
context.urlBuilder = v2.NewURLBuilder(&app.httpHost)
|
||||
} else {
|
||||
context.urlBuilder = v2.NewURLBuilderFromRequest(r)
|
||||
}
|
||||
|
||||
return context
|
||||
|
|
Loading…
Reference in a new issue