diff --git a/pkg/apiserver/proxy.go b/pkg/apiserver/proxy.go index 6ee6d250f75..02ebf9c39d4 100644 --- a/pkg/apiserver/proxy.go +++ b/pkg/apiserver/proxy.go @@ -178,11 +178,16 @@ func (t *proxyTransport) updateURLs(n *html.Node, sourceURL *url.URL) { continue } // Is this URL relative? - if url.Host == "" || url.Host == sourceURL.Host { + if url.Host == "" { url.Scheme = t.proxyScheme url.Host = t.proxyHost url.Path = path.Join(t.proxyPathPrepend, path.Dir(sourceURL.Path), url.Path, "/") n.Attr[i].Val = url.String() + } else if url.Host == sourceURL.Host { + url.Scheme = t.proxyScheme + url.Host = t.proxyHost + url.Path = path.Join(t.proxyPathPrepend, url.Path) + n.Attr[i].Val = url.String() } } } diff --git a/pkg/apiserver/proxy_test.go b/pkg/apiserver/proxy_test.go index aea841344e1..b50eb67264d 100644 --- a/pkg/apiserver/proxy_test.go +++ b/pkg/apiserver/proxy_test.go @@ -17,6 +17,7 @@ limitations under the License. package apiserver import ( + "bytes" "fmt" "io/ioutil" "net/http" @@ -24,56 +25,108 @@ import ( "net/url" "strings" "testing" + + "code.google.com/p/go.net/html" ) +func parseURLOrDie(inURL string) *url.URL { + parsed, err := url.Parse(inURL) + if err != nil { + panic(err) + } + return parsed +} + +// fmtHTML parses and re-emits 'in', effectively canonicalizing it. +func fmtHTML(in string) string { + doc, err := html.Parse(strings.NewReader(in)) + if err != nil { + panic(err) + } + out := &bytes.Buffer{} + if err := html.Render(out, doc); err != nil { + panic(err) + } + return string(out.Bytes()) +} + func TestProxyTransport_fixLinks(t *testing.T) { - content := string(`
kubelet.loggoogle.log`) - transport := &proxyTransport{ + testTransport := &proxyTransport{ proxyScheme: "http", proxyHost: "foo.com", proxyPathPrepend: "/proxy/minion/minion1:10250/", } - - // Test /logs/ - request := &http.Request{ - Method: "GET", - URL: &url.URL{ - Path: "/logs/", - }, - } - response := &http.Response{ - Status: "200 OK", - StatusCode: http.StatusOK, - Body: ioutil.NopCloser(strings.NewReader(content)), - Close: true, - } - updated_resp, _ := transport.fixLinks(request, response) - body, _ := ioutil.ReadAll(updated_resp.Body) - expected := string(`
kubelet.loggoogle.log`) - if !strings.Contains(string(body), expected) { - t.Errorf("Received wrong content: %s", string(body)) + testTransport2 := &proxyTransport{ + proxyScheme: "https", + proxyHost: "foo.com", + proxyPathPrepend: "/proxy/minion/minion1:8080/", } - // Test subdir under /logs/ - request = &http.Request{ - Method: "GET", - URL: &url.URL{ - Path: "/whatever/apt/somelog.log", + table := map[string]struct { + input string + sourceURL string + transport *proxyTransport + output string + }{ + "normal": { + input: `
kubelet.loggoogle.log`, + sourceURL: "http://myminion.com/logs/log.log", + transport: testTransport, + output: `
kubelet.loggoogle.log`, + }, + "subdir": { + input: `kubelet.loggoogle.log`, + sourceURL: "http://myminion.com/whatever/apt/somelog.log", + transport: testTransport2, + output: `kubelet.loggoogle.log`, + }, + "image": { + input: `
`, + sourceURL: "http://myminion.com/", + transport: testTransport, + output: `
`, + }, + "abs": { + input: ``, + sourceURL: "http://myminion.com/any/path/", + transport: testTransport, + output: ``, + }, + "abs but same host": { + input: ``, + sourceURL: "http://myminion.com/any/path/", + transport: testTransport, + output: ``, }, } - transport.proxyScheme = "https" - transport.proxyPathPrepend = "/proxy/minion/minion1:8080/" - response = &http.Response{ - Status: "200 OK", - StatusCode: http.StatusOK, - Body: ioutil.NopCloser(strings.NewReader(content)), - Close: true, - } - updated_resp, _ = transport.fixLinks(request, response) - body, _ = ioutil.ReadAll(updated_resp.Body) - expected = string(`
kubelet.loggoogle.log`) - if !strings.Contains(string(body), expected) { - t.Errorf("Received wrong content: %s", string(body)) + + for name, item := range table { + // Canonicalize the html so we can diff. + item.input = fmtHTML(item.input) + item.output = fmtHTML(item.output) + req := &http.Request{ + Method: "GET", + URL: parseURLOrDie(item.sourceURL), + } + resp := &http.Response{ + Status: "200 OK", + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(strings.NewReader(item.input)), + Close: true, + } + updatedResp, err := item.transport.fixLinks(req, resp) + if err != nil { + t.Errorf("%v: Unexpected error: %v", name, err) + continue + } + body, err := ioutil.ReadAll(updatedResp.Body) + if err != nil { + t.Errorf("%v: Unexpected error: %v", name, err) + continue + } + if e, a := item.output, string(body); e != a { + t.Errorf("%v: expected %v, but got %v", name, e, a) + } } }