WebDAV 的 PROPFIND、缓存清理的 PURGE、浏览器预检的 OPTIONS——这些在 Gin 里该怎么注册?Any 会不会把不该开放的方法也开放了?HEAD 请求为什么 404?这篇用真实的 curl 请求把 Handle、Any、Match 以及 HEAD / OPTIONS 的行为逐个验证。
curl -X PURGE /cache/a/b.png → HTTP/1.1 200 OK | Content-Type: text/plain; charset=utf-8 | X-Handler: purge | Content-Length: 44 || 正文: purge: method=PURGE path=/cache/*key body="" curl -X PROPFIND /dav/folder -d <xml/> → HTTP/1.1 200 OK | Content-Type: text/plain; charset=utf-8 | X-Handler: propfind | Content-Length: 55 || 正文: propfind: method=PROPFIND path=/dav/:name body="<xml/>" curl -X REPORT /dav/folder → HTTP/1.1 200 OK | Content-Type: text/plain; charset=utf-8 | X-Handler: report | Content-Length: 45 || 正文: report: method=REPORT path=/dav/:name body="" curl -X PURGE /dav/folder → HTTP/1.1 404 Not Found | Content-Type: text/plain | Content-Length: 18 || 正文: 404 page not found
Handle(method, path, ...) 接受任何全大写的方法名,和内置的 GET/POST 走同样的路由树。同一个路径可以给不同方法注册不同 handler(WebDAV 的 PROPFIND 与 REPORT);请求体照常可读。没注册的方法默认 404。
curl -X TRACE /any → HTTP/1.1 200 OK | Content-Type: text/plain; charset=utf-8 | X-Handler: any | Content-Length: 35 || 正文: any: method=TRACE path=/any body="" curl -X DELETE /any → HTTP/1.1 200 OK | Content-Type: text/plain; charset=utf-8 | X-Handler: any | Content-Length: 36 || 正文: any: method=DELETE path=/any body="" curl -X PATCH /m → HTTP/1.1 404 Not Found | Content-Type: text/plain | Content-Length: 18 || 正文: 404 page not found curl -X POST /m -d x → HTTP/1.1 200 OK | Content-Type: text/plain; charset=utf-8 | X-Handler: match | Content-Length: 35 || 正文: match: method=POST path=/m body="x" curl -X PUT /m → HTTP/1.1 404 Not Found | Content-Type: text/plain | Content-Length: 18 || 正文: 404 page not found
Any 一口气注册 9 个方法,其中包括 TRACE 和 CONNECT。如果这条路径其实只该接受几种方法,Any 会让多余的方法也进入你的 handler(并且在 405 判定里永远命中)。Match([]string{...}) 只注册你列出的方法,更精确。
curl -I /hello → HTTP/1.1 404 Not Found | Content-Type: text/plain | Content-Length: 18 || 无正文
curl -X OPTIONS /hello → HTTP/1.1 404 Not Found | Content-Type: text/plain | Content-Length: 18 || 正文: 404 page not found
curl -X get /hello → HTTP/1.1 404 Not Found | Content-Type: text/plain | Content-Length: 18 || 正文: 404 page not found
curl -X OPTIONS /cors → HTTP/1.1 204 No Content | Allow: GET, POST, OPTIONS || 无正文
curl -I /headonly → HTTP/1.1 200 OK | Content-Type: text/plain; charset=utf-8 | X-Handler: headonly | Content-Length: 30 || 无正文
curl /headonly → HTTP/1.1 200 OK | Content-Type: text/plain; charset=utf-8 | X-Handler: getonly | Content-Length: 42 || 正文: getonly: method=GET path=/headonly body=""
服务端启动时打印的路由表:
GET /hello
GET /headonly
GET /any
GET /m
PURGE /cache/*key
PROPFIND /dav/:name
REPORT /dav/:name
POST /any
POST /m
PUT /any
PATCH /any
HEAD /any
HEAD /headonly
OPTIONS /any
OPTIONS /cors
DELETE /any
CONNECT /any
TRACE /anyGin 不会把 GET 路由自动用于 HEAD,也不会自动响应 OPTIONS:curl -I 访问只注册了 GET 的路径得到 404,CORS 预检要自己注册 OPTIONS(或用中间件)。HEAD 请求即使进了 handler 写了正文,服务器也不会发出,只保留 Content-Length。方法名区分大小写,get 与 GET 是不同的方法。
curl -X DELETE /dav/folder → HTTP/1.1 405 Method Not Allowed | Allow: PROPFIND, REPORT | Content-Type: text/plain | Content-Length: 22 || 正文: 405 method not allowed curl -X GET /cache/x → HTTP/1.1 405 Method Not Allowed | Allow: PURGE | Content-Type: text/plain | Content-Length: 22 || 正文: 405 method not allowed curl -X DELETE /any → HTTP/1.1 200 OK | Content-Type: text/plain; charset=utf-8 | X-Handler: any | Content-Length: 36 || 正文: any: method=DELETE path=/any body="" curl -X DELETE /m → HTTP/1.1 405 Method Not Allowed | Allow: GET, POST | Content-Type: text/plain | Content-Length: 22 || 正文: 405 method not allowed curl -X PURGE /hello → HTTP/1.1 405 Method Not Allowed | Allow: GET | Content-Type: text/plain | Content-Length: 22 || 正文: 405 method not allowed
打开 HandleMethodNotAllowed 后,405 的 Allow 头把自定义方法也列出来,顺序是各方法树第一次创建的顺序(与前面方法树一篇一致)。注册了 Any 的路径不会返回 405,因为所有方法都命中。