Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use BindStyledParameterWithLocation for correct path param parsing #777

Open
acabarbaye opened this issue Oct 5, 2022 · 3 comments
Open

Comments

@acabarbaye
Copy link

Using codegen 1.11.0 for chi-server and this is the output for a path parameter:

	// ------------- Path parameter "jobName" -------------
	var jobNameJobParam

	err = runtime.BindStyledParameter("simple", false, "jobName", chi.URLParam(r, "jobName"), &jobName)
	if err != nil {
		siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "jobName", Err: err})
		return
	}
...

although I would have expected BindStyledParameterWithLocation to be used instead as seen in the corresponding template https://github.com/deepmap/oapi-codegen/blob/d38f1c9e74308ba7950657df952d49f97606355f/pkg/codegen/templates/chi/chi-middleware.tmpl#L33

The parsing is incorrect for parameter using + character for instance

To reproduce:
the following test passes

package api

import (
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/deepmap/oapi-codegen/pkg/runtime"
	"github.com/go-chi/chi/v5"
	"github.com/stretchr/testify/assert"
)

func sendRequest(t *testing.T, host string, path string) (body string) {
	t.Log("request", path)
	url := fmt.Sprintf("%v%v", host, path)
	r, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return
	}
	c := http.DefaultClient
	resp, err := c.Do(r)
	if err != nil {
		return
	}
	defer func() { _ = resp.Body.Close() }()
	b, err := io.ReadAll(resp.Body)
	if err != nil {
		return
	}
	body = string(b)
	return
}

func TestEscapedURLParams(t *testing.T) {

	m := chi.NewRouter()
	m.Get("/api/{identifier}", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(200)
		var identifier string
		_ = runtime.BindStyledParameterWithLocation("simple", false, "identifier", runtime.ParamLocationPath, chi.URLParam(r, "identifier"), &identifier)
		//_ = runtime.BindStyledParameter("simple", false, "identifier", chi.URLParam(r, "identifier"), &identifier)

		_, _ = w.Write([]byte(identifier))
	})

	ts := httptest.NewServer(m)
	defer ts.Close()

	assert.Equal(t, "hello world", sendRequest(t, ts.URL, "/api/hello world"))
	assert.Equal(t, "hello world", sendRequest(t, ts.URL, "/api/hello%20world"))
	assert.Equal(t, "hello world", sendRequest(t, ts.URL, "/api/hello%2520world"))
	assert.Equal(t, "hello/world", sendRequest(t, ts.URL, "/api/hello%2Fworld"))
	assert.Equal(t, "hello+world.hello world", sendRequest(t, ts.URL, "/api/hello+world.hello world"))
}

whereas if swapping runtime.BindStyledParameterWithLocation("simple", false, "identifier", runtime.ParamLocationPath, chi.URLParam(r, "identifier"), &identifier) with runtime.BindStyledParameter("simple", false, "identifier", chi.URLParam(r, "identifier"), &identifier)

We get the following errors

        	Error:      	Not equal: 
        	            	expected: "hello+world.hello world"
        	            	actual  : "hello world.hello world"
        	            	
        	            	Diff:
        	            	--- Expected
        	            	+++ Actual
        	            	@@ -1 +1 @@
        	            	-hello+world.hello world
        	            	+hello world.hello world
        	Test:       	TestEscapedURLParams
--- FAIL: TestEscapedURLParams (0.01s)


Expected :hello+world.hello world
Actual   :hello world.hello world
@riccardos77
Copy link

same problem exists in gin gin-wrappers.tmpl

@reinkrul
Copy link
Contributor

reinkrul commented Feb 13, 2024

Given

assert.Equal(t, "hello world", sendRequest(t, ts.URL, "/api/hello%2520world"))

I'd expect sendRequest(t, ts.URL, "/api/hello%2520world") to yield hello%20world, not hello world.

Related to oapi-codegen/runtime#35 ?

@neo502721
Copy link

neo502721 commented May 27, 2024

Same here. I am using the gorilla/mux. + in path covert to ' '. Because BindStyledParameterWithOptions call url.QueryUnescape with no ParamLocationPath optition.
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants