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

[BUG] Router does not distinguish between / and %2F in the request path #740

Closed
1 task done
domcermak opened this issue Nov 11, 2023 · 1 comment
Closed
1 task done
Labels

Comments

@domcermak
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Router does parses %2F (URL-encoded /) as a regular / and uses that as a delimiter in the path.

Expected Behavior

I would expect the router to treat the URL-encoded %2F as an encoded value in the path that is not the same as /. See the test below. That should explain the expected behaviour the best.

Steps To Reproduce

package whatever

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"sync"
	"testing"
	"time"

	"github.com/gorilla/mux"
)

func TestRouter(t *testing.T) {
	client := http.Client{
		Timeout: time.Second * 3,
	}
	stringToBeEscaped := "123/ \\ :+ -;& ěščřžýáíé=§¨ů|" // you can try deleting the number and the tests fails because the expected strings do not match
	pathEscaped := url.PathEscape(stringToBeEscaped)
	queryEscaped := url.QueryEscape(stringToBeEscaped)

	fmt.Println("Original string: ", stringToBeEscaped)
	fmt.Println("Path escaped: ", pathEscaped)
	fmt.Println("Query escaped: ", queryEscaped)

	pathUnescaped, _ := url.PathUnescape(pathEscaped)
	queryUnescaped, _ := url.QueryUnescape(queryEscaped)

	fmt.Println("Path unescaped: ", pathUnescaped)
	fmt.Println("Query unescaped: ", queryUnescaped)
	fmt.Println("Path unescaped match: ", pathUnescaped == stringToBeEscaped)
	fmt.Println("Query unescaped match: ", queryUnescaped == stringToBeEscaped)
	serviceUrl := fmt.Sprintf("http://localhost:8080/path/%s?foo=%s", pathEscaped, queryEscaped)

	fmt.Println("Service URL: ", serviceUrl)

	request, err := http.NewRequest(http.MethodGet, serviceUrl, nil)
	if err != nil {
		t.Fatal(err)
	}

	router := mux.NewRouter()
	router.HandleFunc("/path/{positional_argument}", func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		if vars["positional_argument"] != stringToBeEscaped {
			t.Fatalf("expected positional argument to be `%s` but got `%s`", stringToBeEscaped, vars["positional_argument"])
		}

		queryParam := r.URL.Query().Get("foo")
		if queryParam != stringToBeEscaped {
			t.Fatalf("expected query parameter to be `%s` but got `%s`", stringToBeEscaped, queryParam)
		}

		w.WriteHeader(http.StatusOK)
		w.Write([]byte("OK"))
	}).Methods(http.MethodGet)

	wg := &sync.WaitGroup{}
	wg.Add(1)
	go func() {
		wg.Done()
		if err := http.ListenAndServe(":8080", router); err != nil {
			t.Error(err)
		}
	}()

	wg.Wait()
	time.Sleep(time.Second)

	response, err := client.Do(request)
	if err != nil {
		t.Fatal(err)
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		t.Fatalf("expected status code %d but got %d", http.StatusOK, response.StatusCode)
	}

	body, err := io.ReadAll(response.Body)
	if err != nil {
		t.Fatal(err)
	}

	if string(body) != "OK" {
		t.Fatalf("expected body to be `%s` but got `%s`", "OK", string(body))
	}
}

Anything else?

No response

@domcermak domcermak added the bug label Nov 11, 2023
@domcermak domcermak changed the title [BUG] Router does now distinguish between / and %2F in the request path [BUG] Router does not distinguish between / and %2F in the request path Nov 11, 2023
@domcermak
Copy link
Author

I just found UseEncodedPath() which solves the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: ✅ Done
Development

No branches or pull requests

1 participant