在REST中,对于不支持的HTTP方法,应返回哪个响应代码?

huangapple go评论86阅读模式
英文:

What Response Code to return on a non-supported HTTP Method on REST?

问题

我正在使用Gorilla Mux来处理我的REST API的HTTP路由。我正在使用以下绑定来处理我的API:

r := mux.NewRouter()
r.Host(baseUrl)

api := r.PathPrefix("/api").Subrouter()
api.HandleFunc("/users", APIUsers).Methods("GET", "POST")

http.Handle("/", r)
http.ListenAndServe(":8083", nil)

然后我使用CURL进行如下操作:

$ curl -i -X PUT http://127.0.0.1:8083/api/users

预期中,方法APIUsers没有被调用。但我确实收到了200 OK的响应:

HTTP/1.1 200 OK
Date: Tue, 30 Dec 2014 19:03:59 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

我应该如何在Gorilla中进行修改,比如将所有失败的函数绑定到一个指定的函数?另外,我想知道在不支持的函数上返回的典型HTTP状态码是什么。我假设是400范围内的代码,但我不确定应该使用哪个。我不希望它是200,因为请求并不是“OK”。

对此有什么想法和建议吗?

英文:

I'm using Gorilla Mux to handle my HTTP routes for my REST API. I'm using the following binding for my API:

r := mux.NewRouter()
r.Host(baseUrl)

api := r.PathPrefix("/api").Subrouter()
api.HandleFunc("/users", APIUsers).Methods("GET", "POST")

http.Handle("/", r)
http.ListenAndServe(":8083", nil)

Then I do a CURL like this:

$ curl -i -X PUT http://127.0.0.1:8083/api/users

The Method APIUsers doesn't get called, as expected. I do get a 200 OK back tho:

HTTP/1.1 200 OK
Date: Tue, 30 Dec 2014 19:03:59 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8

Should I do this different with Gorilla to, let's say, bind all failing functions to a designated function? Also I wonder what's the typical HTTP code to return on non-supported functions. I'm a assuming a code in the 400 range, but I'm not sure which to use. I don't want it to be 200 tho, as the request was not "OK".

Any ideas and tips on this subject?

答案1

得分: 2

你应该返回的状态码是"405 MethodNotAllowed"或在Go语言中使用http.StatusMethodNowAllowed

根据维基百科的解释:

请求使用了资源不支持的请求方法,例如,在需要通过POST提交数据的表单上使用GET方法,或者在只读资源上使用PUT方法。

你可以参考这个链接了解更多关于HTTP状态码的信息:http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

英文:

The status code you should return is "405 MethodNotAllowed" or http.StatusMethodNowAllowed in go.

From wikipedia:

> A request was made of a resource using a request method not supported
> by that resource; for example, using GET on a form which requires data
> to be presented via POST, or using PUT on a read-only resource.

http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

答案2

得分: 2

你可以设置一个自定义的NotFoundHandler,但这将适用于所有未匹配的路由。

如果你想返回特定的响应,你需要明确定义路由。

示例:

func main() {
    r := mux.NewRouter().PathPrefix("/api").Subrouter()

    // 用于未匹配路由的自定义未找到处理程序
    var notFound NotFound
    r.NotFoundHandler = notFound

    r.HandleFunc("/users", APIUsers).Methods("GET", "POST")

    // 对于PUT、PATCH和DELETE返回405
    r.HandleFunc("/users", status(405, "GET", "POST")).Methods("PUT", "PATCH", "DELETE")

    http.Handle("/", r)

    http.ListenAndServe(":8083", nil)
}

type NotFound func(w http.ResponseWriter, req *http.Request)

func (NotFound) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    w.WriteHeader(404)
    w.Write([]byte(`{"message": "Not Found"}`))
}

// status用于设置特定的状态码
func status(code int, allow ...string) func(w http.ResponseWriter, req *http.Request) {
    return func(w http.ResponseWriter, req *http.Request) {
        w.WriteHeader(code)
        if len(allow) > 0 {
            w.Write([]byte("Allow: " + strings.Join(allow, ", ")))
        }
    }
}

func APIUsers(w http.ResponseWriter, req *http.Request) {
    w.Write([]byte("hello"))
}
英文:

You can set a custom NotFoundHandler but that will apply to all unmatched routes.

If you want a specific response returned you have to define the route explicitly.

Example:

func main() {
    r := mux.NewRouter().PathPrefix("/api").Subrouter()

    // custom not found handler used for unmatched routes
    var notFound NotFound
    r.NotFoundHandler = notFound

    r.HandleFunc("/users", APIUsers).Methods("GET", "POST")

    // return 405 for PUT, PATCH and DELETE
    r.HandleFunc("/users", status(405, "GET", "POST")).Methods("PUT", "PATCH", "DELETE")

    http.Handle("/", r)

    http.ListenAndServe(":8083", nil)
}

type NotFound func(w http.ResponseWriter, req *http.Request)

func (NotFound) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    w.WriteHeader(404)
    w.Write([]byte(`{"message": "Not Found"}`))
}

// status is used to set a specific status code
func status(code int, allow ...string) func(w http.ResponseWriter, req *http.Request) {
    return func(w http.ResponseWriter, req *http.Request) {
        w.WriteHeader(code)
        if len(allow) > 0 {
            w.Write([]byte(`Allow: ` + strings.Join(allow, ", ")))
        }
    }
}

func APIUsers(w http.ResponseWriter, req *http.Request) {
    w.Write([]byte("hello"))
}

huangapple
  • 本文由 发表于 2014年12月31日 03:12:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/27711154.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定