fix(header): Allow header according to RFC 7231 (HTTP 405) (#3759)
Co-authored-by: Helios <i@shangyes.net>
This commit is contained in:
		
							
								
								
									
										10
									
								
								gin.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								gin.go
									
									
									
									
									
								
							| @ -633,17 +633,25 @@ func (engine *Engine) handleHTTPRequest(c *Context) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if engine.HandleMethodNotAllowed { | 	if engine.HandleMethodNotAllowed { | ||||||
|  | 		// According to RFC 7231 section 6.5.5, MUST generate an Allow header field in response | ||||||
|  | 		// containing a list of the target resource's currently supported methods. | ||||||
|  | 		allowed := make([]string, 0, len(t)-1) | ||||||
| 		for _, tree := range engine.trees { | 		for _, tree := range engine.trees { | ||||||
| 			if tree.method == httpMethod { | 			if tree.method == httpMethod { | ||||||
| 				continue | 				continue | ||||||
| 			} | 			} | ||||||
| 			if value := tree.root.getValue(rPath, nil, c.skippedNodes, unescape); value.handlers != nil { | 			if value := tree.root.getValue(rPath, nil, c.skippedNodes, unescape); value.handlers != nil { | ||||||
|  | 				allowed = append(allowed, tree.method) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if len(allowed) > 0 { | ||||||
| 			c.handlers = engine.allNoMethod | 			c.handlers = engine.allNoMethod | ||||||
|  | 			c.writermem.Header().Set("Allow", strings.Join(allowed, ", ")) | ||||||
| 			serveError(c, http.StatusMethodNotAllowed, default405Body) | 			serveError(c, http.StatusMethodNotAllowed, default405Body) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| 	c.handlers = engine.allNoRoute | 	c.handlers = engine.allNoRoute | ||||||
| 	serveError(c, http.StatusNotFound, default404Body) | 	serveError(c, http.StatusNotFound, default404Body) | ||||||
| } | } | ||||||
|  | |||||||
| @ -514,6 +514,18 @@ func TestRouteNotAllowedEnabled2(t *testing.T) { | |||||||
| 	assert.Equal(t, http.StatusMethodNotAllowed, w.Code) | 	assert.Equal(t, http.StatusMethodNotAllowed, w.Code) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestRouteNotAllowedEnabled3(t *testing.T) { | ||||||
|  | 	router := New() | ||||||
|  | 	router.HandleMethodNotAllowed = true | ||||||
|  | 	router.GET("/path", func(c *Context) {}) | ||||||
|  | 	router.POST("/path", func(c *Context) {}) | ||||||
|  | 	w := PerformRequest(router, http.MethodPut, "/path") | ||||||
|  | 	assert.Equal(t, http.StatusMethodNotAllowed, w.Code) | ||||||
|  | 	allowed := w.Header().Get("Allow") | ||||||
|  | 	assert.Contains(t, allowed, "GET") | ||||||
|  | 	assert.Contains(t, allowed, "POST") | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestRouteNotAllowedDisabled(t *testing.T) { | func TestRouteNotAllowedDisabled(t *testing.T) { | ||||||
| 	router := New() | 	router := New() | ||||||
| 	router.HandleMethodNotAllowed = false | 	router.HandleMethodNotAllowed = false | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user