gin-gonic / gin

Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.
https://gin-gonic.com/
MIT License
78.96k stars 8.02k forks source link

Slashes in parameter #1446

Open framps opened 6 years ago

framps commented 6 years ago

I found #641 which is exactly my issue. This issue is from June 2016. Looks like it's still not supported :cry:

As an alternative I think I can use an optional parameter because my parameter will have at least one slash. Is there any other known more general approach available?

thinkerou commented 6 years ago

example code:

r := gin.Default()
r.Use(gin.Logger())
// r.RedirectFixedPath = true
r.GET("/test/:name/hi/:age", func(c *gin.Context) {
    n := c.Param("name")
    h := c.Param("age")

    c.JSON(200, gin.H{
        "msg": "hello " + n + "=" + h,
    })
})

and run it:

➜  ~ curl -v 'http://localhost:8080/test/thinkerou/hi/30'
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /test/tianou/hi/30 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Date: Tue, 07 Aug 2018 06:24:03 GMT
< Content-Length: 39
<
* Connection #0 to host localhost left intact
{"msg":"hello thinkerou=30"}%
framps commented 6 years ago

Thank you very much for your example code. But it's not accepting slashes in a parameter in the url.

That's my current workaround:

package main

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

    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    r.Use(gin.Logger())
    r.GET("/test/:name/*nametrail", func(c *gin.Context) {
        n := c.Param("name")
        t := c.Param("nametrail")

        c.JSON(200, gin.H{
            "msg": "hello " + n + t,
        })
    })

    req, err := http.NewRequest("GET", "http://localhost/test/this/is/a/path/which/uses/slashes", nil)
    if err != nil {
        panic(err)
    }
    rec := httptest.NewRecorder()
    r.ServeHTTP(rec, req)
    if err != nil {
        panic(err)
    }
    b, err := ioutil.ReadAll(rec.Body)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Response: %s\n", string(b))

}
Response: {"msg":"hello this/is/a/path/which/uses/slashes"}

I just want to know whether that's the way to go with gin or another more elegant way to solve the issue is possible.

thinkerou commented 6 years ago

@framps sorry, I don't understand what's your expect result?

router: r.GET("/test/:name/*trail", func (c *gin.Context) {} input: curl -v 'localhost:8080/test/thinkerou/this/is/a/path your expect result???

hiveminded commented 6 years ago

@framps @thinkerou why not to expect a result like this? on iris the app.Get("/test/{name}/{trail:path}", func(ciris.Context){} is alive for curl -v 'localhost:8080/test/thinkerou/this/is/a/path because the parameter type :path can accept any number of slashes as its parameter.

thinkerou commented 6 years ago

Yes, *nametrail will accept any number of slashes as its parameter.

framps commented 6 years ago

@thinkerou It's possible to have slashes in url parms witgh now with gin (See my example above). Would be great to have more control like r.GET("/test/:name/*1justOneArgBetweenSlashes/*2justOneArgWithOnSlashBetweenSlashes" which will return for /test/one/two/three/four

  1. name: one
  2. justOneArgBetweenSlashes: two
  3. justOneArgWithOneSlashBetweenSlashes: three/four

But all this is possible to handle right now already but will required some additional hand crafting code. Maybe this is a very unlikely use case and it doesn't make sense to spend any time on this. But maybe somebody has some spare time to create a PR for this :smile:

JokerQyou commented 4 years ago

In this case:

r.GET("/test/:name/*trail", func (c *gin.Context) {}

The trail parameter seems to always contain a slash as the first character, which is rather confusing.

tmm1 commented 3 years ago

One option is to set r.UseRawPath = true, and then send the parameter with slashes using %2F encoding.

JK-97 commented 1 year ago

same problem

thincal commented 4 months ago

In this case:

r.GET("/test/:name/*trail", func (c *gin.Context) {}

The trail parameter seems to always contain a slash as the first character, which is rather confusing.

Same problem, is there any fix for this issue ?