Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does url.Parse not populate URL.RawPath?

Tags:

url

escaping

go

While with similar input, URL.RawQuery seems to be properly populated.

Playground

u, err := url.Parse("https://example.com/foo%2fbar")
if err != nil {
    log.Fatal(err)
}
fmt.Println(u.Path)
fmt.Println(u.RawPath)
fmt.Println(u.String(), "\n")

u, err = url.Parse("https://example.com/foo%25fbar?q=morefoo%25bar")
if err != nil {
    log.Fatal(err)
}
fmt.Println(u.Path)
fmt.Println(u.RawPath)
fmt.Println(u.RawQuery)
fmt.Println(u.String())
like image 265
Sridhar Avatar asked Sep 01 '16 11:09

Sridhar


People also ask

What is RawPath?

RawPath is the empty string (because "/foo%25fbar" is an invalid escaped path), but EscapedPath() returns you the original escaped path.

What does URL parse do in Golang?

Go has good support for url parsing. URL contains a scheme, authentication info, host, port, path, query params, and query fragment. we can parse URL and deduce what are the parameter is coming to the server and then process the request accordingly.


2 Answers

Note that URL.RawPath is not the raw (escaped) path. It may be, but not always. It's just a hint. Its doc says:

RawPath    string // encoded path hint (Go 1.5 and later only; see EscapedPath method)

So when you need the escaped path, always use URL.EscapedPath() and don't rely on the URL.RawPath field. Doc of URL.EscapedPath() says:

EscapedPath returns u.RawPath when it is a valid escaping of u.Path.

This is your case. A raw path is invalid if it contains bytes that need escaping during URL encoding. Your path is such an example because it contains %25 which is the URL escaped text of the percent symbol itself '%', and percent symbols need to be escaped if part of URL paths.

Your first example contained %2f which is the URL escaped text of the slash'/' which if present in a path does not need to be escaped ('/' is a valid character in paths and is treated as a separator).

See this example:

u, err = url.Parse("https://example.com/foo%25fbar?q=morefoo%25bar")
if err != nil {
    log.Fatal(err)
}
fmt.Println("Path:       ", u.Path)
fmt.Println("RawPath:    ", u.RawPath)
fmt.Println("EscapedPath:", u.EscapedPath())
fmt.Println("RawQuery:   ", u.RawQuery)
fmt.Println("String:     ", u.String())

Output (try it on the Go Playground):

Path:        /foo%fbar
RawPath:     
EscapedPath: /foo%25fbar
RawQuery:    q=morefoo%25bar
String:      https://example.com/foo%25fbar?q=morefoo%25bar

RawPath is the empty string (because "/foo%25fbar" is an invalid escaped path), but EscapedPath() returns you the original escaped path.

like image 78
icza Avatar answered Sep 19 '22 18:09

icza


Just use func(*URL)EscapedPath()

fmt.Println(u.EscapedPath()) //give you expected result

From package spec

In general, code should call EscapedPath instead of reading u.RawPath directly.

And from source comments

// RawPath is a hint as to the encoding of Path to use
// in url.EscapedPath. If that method already gets the
// right answer without RawPath, leave it empty.
// This will help make sure that people don't rely on it in general. 
like image 21
Uvelichitel Avatar answered Sep 22 '22 18:09

Uvelichitel