zeromicro / go-zero

A cloud-native Go microservices framework with cli tool for productivity.
https://go-zero.dev
MIT License
29.35k stars 3.96k forks source link

go-zero can't support two different Methods with the same path. #4391

Open cliffwoodave14 opened 1 month ago

cliffwoodave14 commented 1 month ago

Describe the bug If I define two routes with the same path content, but with different Method, then go-zero always returns 405 Method Not Allowed for one method. As we know, for a resource, we should support GET, PUT, even HEAD method on the same resource. We should not expect 405 error unless the method is not in the list(Head, Get, Put, Patch, Post...).

To Reproduce Steps to reproduce the behavior, if applicable:

  1. The code is

    server.AddRoutes( []rest.Route{ { Method: http.MethodHead, Path: "/subscriptions/:ID/groups/:groupName", Handler: HeadGroupHandler(serverCtx), }, { Method: http.MethodPut, Path: "/subscriptions/:ID/groups/:groupName", Handler: GetGroupHandler(serverCtx), },

  2. The error is PUT https://xxxx.com/subscriptions/8ecadfc9-d1a3-4ea4-b844-0d9f87e4d7c8/groups/test-group\n--------------------------------------------------------------------------------\nRESPONSE 405: 405 Method Not Allowed\nERROR CODE

Expected behavior Should not return 405 error.

Screenshots If applicable, add screenshots to help explain your problem.

Environments (please complete the following information):

More description Add any other context about the problem here.

ywanbing commented 1 month ago

hi, I tested your route without 405. Do you need to check the path of the request, or the request method? @cliffwoodave14

ywanbing commented 1 month ago

routers.go


func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
    server.AddRoutes(
        []rest.Route{
            {
                Method:  http.MethodGet,
                Path:    "/from/:name",
                Handler: TestHandler(serverCtx),
            },
            {
                Method:  http.MethodHead,
                Path:    "/subscriptions/:ID/groups/:groupName",
                Handler: HeadGroupHandler(serverCtx),
            },
            {
                Method:  http.MethodPut,
                Path:    "/subscriptions/:ID/groups/:groupName",
                Handler: GetGroupHandler(serverCtx),
            },
        },
    )
}

test.api

syntax = "v1"

type Request {
    Name string `path:"name,options=you|me"`
}

type Response {
    Message string `json:"message"`
}

type Req {
    ID        string `path:"ID"`
    GroupName string `path:"groupName"`
}

service test-api {
    @handler TestHandler
    get /from/:name (Request) returns (Response)

    @handler HeadGroupHandler
    head /subscriptions/:ID/groups/:groupName (Req) returns (Response)

    @handler GetGroupHandler
    put /subscriptions/:ID/groups/:groupName (Req) returns (Response)
}

resp

PUT http://localhost:8888/subscriptions/8ecadfc9-d1a3-4ea4-b844-0d9f87e4d7c8/groups/test-group

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Traceparent: 00-983f255746ec6ad63358152cd36dd570-9c67769c02128902-00
Date: Fri, 27 Sep 2024 06:55:10 GMT
Content-Length: 33

{
  "code": 0,
  "msg": "ok",
  "data": null
}