lib/httputils/status.go (75 lines of code) (raw):
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package httputils
import (
"net/http"
"google.golang.org/grpc/codes" /* copybara-comment */
"google.golang.org/grpc/status" /* copybara-comment */
)
// WARNING: do not change the mappings in this file.
// 499 is a non-standard code for "Client Closed Request" and is the code
// mapped to Canceled in C++, so we do that here too for consistency.
const canceled = 499
// Notes:
// 1. FailedPrecondtion: 416 "Requested range not satisfiable" is not used
// because it has HTTP-specific semantics that will not always apply.
// 2. OutOfRange: 416 "Requested range not satisfiable" is not used because it
// has HTTP-specific semantics that will not always apply.
var rpc2http = map[codes.Code]int{
codes.OK: http.StatusOK,
codes.Canceled: canceled,
codes.InvalidArgument: http.StatusBadRequest,
codes.DeadlineExceeded: http.StatusGatewayTimeout,
codes.NotFound: http.StatusNotFound,
codes.AlreadyExists: http.StatusConflict,
codes.PermissionDenied: http.StatusForbidden,
codes.ResourceExhausted: http.StatusTooManyRequests,
codes.FailedPrecondition: http.StatusBadRequest,
codes.Aborted: http.StatusConflict,
codes.OutOfRange: http.StatusBadRequest,
codes.Unimplemented: http.StatusNotImplemented,
codes.Unavailable: http.StatusServiceUnavailable,
codes.Unauthenticated: http.StatusUnauthorized,
// DataLoss, Internal, and Unknown map to the default
}
// In the mappings above, some Codes are mapped to the same HTTP
// status. Here, the HTTP status is mapped to the most general codes.Code.
var http2rpc = map[int]codes.Code{
http.StatusOK: codes.OK,
http.StatusBadRequest: codes.InvalidArgument,
http.StatusForbidden: codes.PermissionDenied,
http.StatusNotFound: codes.NotFound,
http.StatusConflict: codes.Aborted,
http.StatusRequestedRangeNotSatisfiable: codes.OutOfRange,
http.StatusTooManyRequests: codes.ResourceExhausted,
canceled: codes.Canceled,
http.StatusGatewayTimeout: codes.DeadlineExceeded,
http.StatusNotImplemented: codes.Unimplemented,
http.StatusServiceUnavailable: codes.Unavailable,
http.StatusUnauthorized: codes.Unauthenticated,
}
// RPCCode translates an HTTP status into a codes.Code
func RPCCode(code int) codes.Code {
if code, ok := http2rpc[code]; ok {
return code
}
switch {
case code >= 200 && code < 300:
return codes.OK
case code >= 400 && code < 500:
return codes.FailedPrecondition
case code >= 500 && code < 600:
return codes.Internal
}
return codes.Unknown
}
// HTTPStatus translates a codes.Code into an HTTP status.
func HTTPStatus(code codes.Code) int {
if code, ok := rpc2http[code]; ok {
return code
}
return http.StatusInternalServerError
}
// FromError translates a canonical error into an HTTP status.
func FromError(err error) int {
return HTTPStatus(status.Code(err))
}
// IsHTTPSuccess check if http code is success code: 2xx
// See: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
func IsHTTPSuccess(code int) bool {
return code >= 200 && code < 300
}
// IsHTTPRedirect check if http code is redirect code: 3xx
func IsHTTPRedirect(code int) bool {
return code >= 300 && code < 400
}
// IsHTTPClientError check if http code is client error code: 4xx
func IsHTTPClientError(code int) bool {
return code >= 400 && code < 500
}
// IsHTTPServerError check if http code is server error code: 5xx
func IsHTTPServerError(code int) bool {
return code >= 500 && code < 600
}
// IsHTTPError check if http code is error code: 4xx or 5xx
func IsHTTPError(code int) bool {
return IsHTTPClientError(code) || IsHTTPServerError(code)
}