From d48d399fb39cd534f23d85f215182b0bfdc1752b Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 13 Jun 2016 22:11:26 +0900 Subject: [PATCH] nghttpx: Allow query in API endpoint --- integration-tests/nghttpx_http1_test.go | 37 +++++++++++++++++++++++++ integration-tests/nghttpx_http2_test.go | 37 +++++++++++++++++++++++++ integration-tests/nghttpx_spdy_test.go | 37 +++++++++++++++++++++++++ integration-tests/server_tester.go | 5 ++-- src/shrpx_api_downstream_connection.cc | 6 +++- 5 files changed, 119 insertions(+), 3 deletions(-) diff --git a/integration-tests/nghttpx_http1_test.go b/integration-tests/nghttpx_http1_test.go index 59d3d8d8..bb97a26b 100644 --- a/integration-tests/nghttpx_http1_test.go +++ b/integration-tests/nghttpx_http1_test.go @@ -832,6 +832,43 @@ backend=127.0.0.1,3011 } } +// TestH1APIBackendReplaceQuery exercise backendconfig API endpoint +// routine with query. +func TestH1APIBackendReplaceQuery(t *testing.T) { + st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }, 3010) + defer st.Close() + + res, err := st.http1(requestParam{ + name: "TestH1APIBackendReplaceQuery", + path: "/api/v1beta1/backendconfig?foo=bar", + method: "PUT", + body: []byte(`# comment +backend=127.0.0.1,3011 + +`), + }) + if err != nil { + t.Fatalf("Error st.http1() = %v", err) + } + if got, want := res.status, 200; got != want { + t.Errorf("res.status: %v; want %v", got, want) + } + + var apiResp APIResponse + err = json.Unmarshal(res.body, &apiResp) + if err != nil { + t.Fatalf("Error unmarshaling API response: %v", err) + } + if got, want := apiResp.Status, "Success"; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } + if got, want := apiResp.Code, 200; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } +} + // TestH1APIBackendReplaceBadMethod exercise backendconfig API // endpoint routine with bad method. func TestH1APIBackendReplaceBadMethod(t *testing.T) { diff --git a/integration-tests/nghttpx_http2_test.go b/integration-tests/nghttpx_http2_test.go index c39a7ad4..8367b8b9 100644 --- a/integration-tests/nghttpx_http2_test.go +++ b/integration-tests/nghttpx_http2_test.go @@ -1882,6 +1882,43 @@ backend=127.0.0.1,3011 } } +// TestH2APIBackendReplaceQuery exercise backendconfig API endpoint +// routine with query. +func TestH2APIBackendReplaceQuery(t *testing.T) { + st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }, 3010) + defer st.Close() + + res, err := st.http2(requestParam{ + name: "TestH2APIBackendReplaceQuery", + path: "/api/v1beta1/backendconfig?foo=bar", + method: "PUT", + body: []byte(`# comment +backend=127.0.0.1,3011 + +`), + }) + if err != nil { + t.Fatalf("Error st.http2() = %v", err) + } + if got, want := res.status, 200; got != want { + t.Errorf("res.status: %v; want %v", got, want) + } + + var apiResp APIResponse + err = json.Unmarshal(res.body, &apiResp) + if err != nil { + t.Fatalf("Error unmarshaling API response: %v", err) + } + if got, want := apiResp.Status, "Success"; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } + if got, want := apiResp.Code, 200; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } +} + // TestH2APIBackendReplaceBadMethod exercise backendconfig API // endpoint routine with bad method. func TestH2APIBackendReplaceBadMethod(t *testing.T) { diff --git a/integration-tests/nghttpx_spdy_test.go b/integration-tests/nghttpx_spdy_test.go index f26f97da..96df0ddb 100644 --- a/integration-tests/nghttpx_spdy_test.go +++ b/integration-tests/nghttpx_spdy_test.go @@ -513,6 +513,43 @@ backend=127.0.0.1,3011 } } +// TestS3APIBackendReplaceQuery exercise backendconfig API endpoint +// routine with query. +func TestS3APIBackendReplaceQuery(t *testing.T) { + st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) { + t.Fatalf("request should not be forwarded") + }, 3010) + defer st.Close() + + res, err := st.spdy(requestParam{ + name: "TestS3APIBackendReplaceQuery", + path: "/api/v1beta1/backendconfig?foo=bar", + method: "PUT", + body: []byte(`# comment +backend=127.0.0.1,3011 + +`), + }) + if err != nil { + t.Fatalf("Error st.spdy() = %v", err) + } + if got, want := res.status, 200; got != want { + t.Errorf("res.status: %v; want %v", got, want) + } + + var apiResp APIResponse + err = json.Unmarshal(res.body, &apiResp) + if err != nil { + t.Fatalf("Error unmarshaling API response: %v", err) + } + if got, want := apiResp.Status, "Success"; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } + if got, want := apiResp.Code, 200; got != want { + t.Errorf("apiResp.Status: %v; want %v", got, want) + } +} + // TestS3APIBackendReplaceBadMethod exercise backendconfig API // endpoint routine with bad method. func TestS3APIBackendReplaceBadMethod(t *testing.T) { diff --git a/integration-tests/server_tester.go b/integration-tests/server_tester.go index 50859cbb..ae80861e 100644 --- a/integration-tests/server_tester.go +++ b/integration-tests/server_tester.go @@ -379,8 +379,9 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) { if err != nil { st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err) } - u.Path = rp.path - reqURL = u.String() + u.Path = "" + u.RawQuery = "" + reqURL = u.String() + rp.path } req, err := http.NewRequest(method, reqURL, body) diff --git a/src/shrpx_api_downstream_connection.cc b/src/shrpx_api_downstream_connection.cc index 9b36d4f2..b8aadbde 100644 --- a/src/shrpx_api_downstream_connection.cc +++ b/src/shrpx_api_downstream_connection.cc @@ -131,7 +131,11 @@ int APIDownstreamConnection::push_request_headers() { auto &req = downstream_->request(); auto &resp = downstream_->response(); - if (req.path != StringRef::from_lit("/api/v1beta1/backendconfig")) { + auto path = + StringRef{std::begin(req.path), + std::find(std::begin(req.path), std::end(req.path), '?')}; + + if (path != StringRef::from_lit("/api/v1beta1/backendconfig")) { send_reply(404, API_FAILURE); return 0;