Change:
t.Fatalf("expected '%#v', got '%#v'", e, a) } } <ins> func TestRedirectOnMissingTrailingSlash(t *testing.T) { table := []struct { // The requested path path string // The path requested on the proxy server. proxyServerPath string }{ {"/trailing/slash/", "/trailing/slash/"}, {"/", "/"}, // "/" should be added at the end. {"", "/"}, // "/" should not be added at a non-root path. {"/some/path", "/some/path"}, } for _, item := range table { proxyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if req.URL.Path != item.proxyServerPath { t.Errorf("Unexpected request on path: %s, expected path: %s, item: %v", req.URL.Path, item.proxyServerPath, item) } })) defer proxyServer.Close() serverURL, _ := url.Parse(proxyServer.URL) simpleStorage := &SimpleRESTStorage{ errors:                    map[string]error{}, resourceLocation:          serverURL, expectedResourceNamespace: "ns", } handler := handleNamespaced(map[string]rest.Storage{"foo": simpleStorage}) server := httptest.NewServer(handler) defer server.Close() proxyTestPattern := "/api/version2/proxy/namespaces/ns/foo/id" + item.path req, err := http.NewRequest( "GET", server.URL+proxyTestPattern, strings.NewReader(""), ) if err != nil { t.Errorf("unexpected error %v", err) continue } // Note: We are using a default client here, that follows redirects. resp, err := http.DefaultClient.Do(req) if err != nil { t.Errorf("unexpected error %v", err) continue } if resp.StatusCode != http.StatusOK { t.Errorf("Unexpected errorCode: %v, expected: 200. Response: %v, item: %v", resp.StatusCode, resp, item) } } } </ins>

Discussion:
This works: but this does not: We should somehow emphasize the need for the trailing slash for now, and then work out what is going wrong (client side scripting?) to fix this (our fault in the proxy or Grafana's?)
Likewise for Kibana.
For the Kibana case, I observe a sequence of correctly proxied GETs e.g. to: but then I see: which fails because I assume what was really needed is: and a curl against that gives a pile of plausible Javascript.
After a little thought, I think what's going on here is that web clients can't tell that is a directory without the trailing slash. One thing we could potentially do to help is to redirect (301) from to , since I don't think the former is useful for anyone.
cc
How are we generating that URL? Can we append a "/" at the end while generating the URL? Doing a redirect or auto-adding "/" in the proxy for all requests could break other requests.
The URL is not generated anywhere. It is assumed that '/proxy/service/<service name' would work. , Nikhil Jindal wrote:
I discussed this with and To clarify, proxy server does not require a trailing slash. It works as expected (gives the same response with or without a trailing slash) The client code, on the other hand, expects it to be rendered on a path with a trailing slash and breaks when that is not the case. Ideally, we should fix the client code. For now, we decided to update proxy to send a 301 redirect from a path without a trailing slash to a path with a trailing slash. I will send a PR for this.
By "client code" do you mean things like Elasticsearch and Kibana?
Yes. The code being rendered on those paths.
I agree with what said, I just want to clarify that it's not necessarily a "broken" client, just one with different expectations. Adding the 301 redirect seems like an easy way to satisfy such clients and reduce user pain.
Not fixed because of
On GCE, the redirection is still not happening because the request is upgraded before we get a chance to redirect On localhost, the redirection works fine but we are unable to load the css and js files because of
Is proxy still supported in v1beta3? I vaguely remember that we wanted to remove it.

I tried this: but got NotFound error.
Access to cluster-level logging components depends on the proxy so avoid making ELBs. Elasticsearch and Kibana are accessed via the v1beta3 service proxy.
Although the trailing slashes are no longer required.