Какой код ответа вернуть для неподдерживаемого метода HTTP в REST?

Я использую Gorilla Mux для обработки моих HTTP-маршрутов для моего REST API. Я использую следующую привязку для своего 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".

Есть идеи и советы на эту тему?


person Community    schedule 30.12.2014    source источник
comment
Вы должны получить 404. Мультиплексор настроен на использование http.NotFoundHandler(), когда маршрут не соответствует. Вы указали NotFoundHandler для Router?   -  person jmaloney    schedule 31.12.2014


Ответы (2)


Вы можете установить собственный NotFoundHandler, но он будет применяться ко всем несопоставленным маршрутам.

Если вы хотите, чтобы возвращался конкретный ответ, вы должны явно определить маршрут.

Пример:

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"))
}
person jmaloney    schedule 30.12.2014
comment
Спасибо за ответ @jmaloney. Любая идея, как я могу получить доступ к методам из HandleFunc в статусе (405)? Чего я хочу добиться, так это установить Allow в результате Allow: GET,POST в качестве информации ответа 405. Текущий способ, которым я теряю информацию о маршруте (содержащую установленные методы). Должен ли я хранить глобальную переменную буфера, чтобы отслеживать это, или я могу обнаружить это каким-то другим способом? - person ; 01.01.2015
comment
@Allender, вы можете просто передать разрешенные методы, которые вы хотите, в функцию состояния. Я обновил свой ответ, чтобы проиллюстрировать. - person jmaloney; 02.01.2015
comment
Спасибо @jmaloney. В конце концов я получил дополнительную вспомогательную функцию поверх обычной привязки маршрута, вот так; addAPIRoute("/users/{id:[0-9]+}/", apiUsers, "GET", "POST", "PUT"). Таким образом, я мог бы также сделать так, чтобы больше родителей хотели определить, работает ли Auth/TLS/Etc. требуется для каждого маршрута. Спасибо еще раз :) - person ; 02.01.2015

Код состояния, который вы должны вернуть, — «405 MethodNotAllowed» или http.StatusMethodNowAllowed в работе.

Из википедии:

Был сделан запрос к ресурсу с использованием метода запроса, не поддерживаемого этим ресурсом; например, используя GET для формы, которая требует представления данных через POST, или используя PUT для ресурса, доступного только для чтения.

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

person Arjan    schedule 30.12.2014
comment
Спасибо за ответ Аржан. Это также часто используется для REST API? К сожалению, ограничение Methods было бы бесполезным, если бы я не мог направить 405 на запрещенный метод: P - person ; 30.12.2014
comment
Как правило, рекомендуется по возможности возвращать соответствующий код ответа HTTP. - person Arjan; 31.12.2014