gin
gin copied to clipboard
Fail to POST when omitting slash at the end with asterisk path parameter
-
With issues:
- Use the search tool before opening a new issue.
- Please provide source code and commit sha if you found a bug.
- Review existing issues and provide feedback or react to them.
-
go version: 1.11
-
gin version (or commit ref): 1.3.0
-
operating system: Ubuntu 18.04 & Ubuntu 16.04 & macOS 10.14(Mojave)
Description
Hi, guys. I use the POST function to handle an uploading request. The router part of my code is like this
Router.MaxMultipartMemory = 8 << 20 // 8 MiB
v1 := Router.Group("/api/v1")
{
// some other routes
v1.POST("/default/*contentPath", v1handlers.HandlePost)
}
The HandlePost function handles an uploading process. However, when I tried to request with the url api/v1/default
. The following message showed up in the console:
redirecting request 307: /api/v1/default --> /api/v1/default/
and there was an error:
get form err: multipart: NextPart: bufio: buffer full
After that, I tried uploading a super small file. The console said redirecting request 307: /api/v1/default --> /api/v1/default/
and the request was just pending there forever... I breakpointed the handling function and found out that the function was never called.
By the way, everything works fine if I use the full path /api/v1/default/
or /api/v1/default/some/other/path
.
How can I solve this problem? Is it a bug or is it because I didn't use the correct path parameters?
Screenshots
redirecting request 307: /api/v1/default --> /api/v1/default/
had told you 307
, so you should use api/v1/default/
not api/v1/default
@thinkerou With other method like GET
, the url api/v1/default
is successfully redirected to api/v1/default/
. Why does the redirecting mechanism not work when POSTing a file?
url api/v1/default is successfully redirected to api/v1/default/
what's mean?
r.GET("/get/*y", func(c *gin.Context) {
c.JSON(200, gin.H{"msg": "hello"})
})
curl:
➜ ~ curl -v localhost:8080/get
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /get HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Content-Type: text/html; charset=utf-8
< Location: /get/
< Date: Fri, 12 Oct 2018 11:44:17 GMT
< Content-Length: 40
<
<a href="/get/">Moved Permanently</a>.
* Connection #0 to host localhost left intact
➜ ~ curl -v localhost:8080/get/
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /get/ 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: Fri, 12 Oct 2018 11:44:31 GMT
< Content-Length: 15
<
* Connection #0 to host localhost left intact
{"msg":"hello"}
BTW, please post one mini simple which I can reproduce it?
@thinkerou Thanks for your reply. This is a history version of my project where I use gin and get this issue. https://github.com/yuqingc/rmdashrf/tree/v0.2.0
This is the router file. Original file: https://github.com/yuqingc/rmdashrf/blob/v0.2.0/pkg/routes/api.go
var Router = gin.Default()
func init() {
Router.MaxMultipartMemory = 8 << 20 // 8 MiB
v1 := Router.Group("/api/v1")
{
v1.GET("/default/*contentPath", v1handlers.HandleGet)
// some other routes
v1.POST("/default/*contentPath", v1handlers.HandlePost)
}
}
This is the handling function which processes uploading a file. Original file: https://github.com/yuqingc/rmdashrf/blob/v0.2.0/pkg/v1handlers/post.go
func handlePost(c *gin.Context) {
paramContentPath := c.Param("contentPath")
// upload filey
file, err := c.FormFile("file")
if err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error()))
return
}
dst := path.Join(MountedVolume, paramContentPath, file.Filename)
if err := c.SaveUploadedFile(file, dst); err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("upload file err: %s", err.Error()))
return
}
c.String(http.StatusOK, "file uploaded")
}
I tested my API with Postman. Everything works fine when I request with http://localhost:8080/api/v1/default/
or http://localhost:8080/api/v1/default/another/path
. However, when I request http://localhost:8080/api/v1/default
, I get the following problems.
- Uploading a large file causes this error:
get form err: multipart: NextPart: bufio: buffer full

- Uploading a small file makes the request stuck over there and no response is received.

This is the output of gin

I breakpointed the handling function. It seems that the handling function handlePost
is never called when uploading a small file.
I understand the correct route should contain a slash at the end, but Gin should automatically redirect /api/v1/default
to /api/v1/default/
according to gin doc. The redirecting works fine with other method, say, GET
, PATCH
and without uploading a file, etc.
@yuqingc probably that's a problem of Postman
not following the redirect (or there is an option to follow the redirects). The server responded with the redirect (see the log), it's the client that should make a new request
@isgj Hey, I'm following this thread due to a similar problem with redirect, I'm requesting using curl
and I'm getting 301 redirecting and the client side request just fails.
Image reference:
Left terminal: Server
Right terminal: Client