zoukankan      html  css  js  c++  java
  • gRPC错误码 http状态码 provide your APIs in both gRPC and RESTful style at the same time

    https://github.com/grpc-ecosystem/grpc-gateway/blob/master/runtime/errors.go#L15

    package runtime
    
    import (
    	"context"
    	"io"
    	"net/http"
    
    	"github.com/golang/protobuf/proto"
    	"github.com/golang/protobuf/ptypes/any"
    	"google.golang.org/grpc/codes"
    	"google.golang.org/grpc/grpclog"
    	"google.golang.org/grpc/status"
    )
    
    // HTTPStatusFromCode converts a gRPC error code into the corresponding HTTP response status.
    // See: https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
    func HTTPStatusFromCode(code codes.Code) int {
    	switch code {
    	case codes.OK:
    		return http.StatusOK
    	case codes.Canceled:
    		return http.StatusRequestTimeout
    	case codes.Unknown:
    		return http.StatusInternalServerError
    	case codes.InvalidArgument:
    		return http.StatusBadRequest
    	case codes.DeadlineExceeded:
    		return http.StatusGatewayTimeout
    	case codes.NotFound:
    		return http.StatusNotFound
    	case codes.AlreadyExists:
    		return http.StatusConflict
    	case codes.PermissionDenied:
    		return http.StatusForbidden
    	case codes.Unauthenticated:
    		return http.StatusUnauthorized
    	case codes.ResourceExhausted:
    		return http.StatusTooManyRequests
    	case codes.FailedPrecondition:
    		return http.StatusPreconditionFailed
    	case codes.Aborted:
    		return http.StatusConflict
    	case codes.OutOfRange:
    		return http.StatusBadRequest
    	case codes.Unimplemented:
    		return http.StatusNotImplemented
    	case codes.Internal:
    		return http.StatusInternalServerError
    	case codes.Unavailable:
    		return http.StatusServiceUnavailable
    	case codes.DataLoss:
    		return http.StatusInternalServerError
    	}
    
    	grpclog.Infof("Unknown gRPC error code: %v", code)
    	return http.StatusInternalServerError
    }
    
    var (
    	// HTTPError replies to the request with the error.
    	// You can set a custom function to this variable to customize error format.
    	HTTPError = DefaultHTTPError
    	// OtherErrorHandler handles the following error used by the gateway: StatusMethodNotAllowed StatusNotFound and StatusBadRequest
    	OtherErrorHandler = DefaultOtherErrorHandler
    )
    
    type errorBody struct {
    	Error   string     `protobuf:"bytes,1,name=error" json:"error"`
    	// This is to make the error more compatible with users that expect errors to be Status objects:
    	// https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto
    	// It should be the exact same message as the Error field.
    	Message string     `protobuf:"bytes,1,name=message" json:"message"`
    	Code    int32      `protobuf:"varint,2,name=code" json:"code"`
    	Details []*any.Any `protobuf:"bytes,3,rep,name=details" json:"details,omitempty"`
    }
    
    // Make this also conform to proto.Message for builtin JSONPb Marshaler
    func (e *errorBody) Reset()         { *e = errorBody{} }
    func (e *errorBody) String() string { return proto.CompactTextString(e) }
    func (*errorBody) ProtoMessage()    {}
    
    // DefaultHTTPError is the default implementation of HTTPError.
    // If "err" is an error from gRPC system, the function replies with the status code mapped by HTTPStatusFromCode.
    // If otherwise, it replies with http.StatusInternalServerError.
    //
    // The response body returned by this function is a JSON object,
    // which contains a member whose key is "error" and whose value is err.Error().
    func DefaultHTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, _ *http.Request, err error) {
    	const fallback = `{"error": "failed to marshal error message"}`
    
    	w.Header().Del("Trailer")
    	w.Header().Set("Content-Type", marshaler.ContentType())
    
    	s, ok := status.FromError(err)
    	if !ok {
    		s = status.New(codes.Unknown, err.Error())
    	}
    
    	body := &errorBody{
    		Error:   s.Message(),
    		Message: s.Message(),
    		Code:    int32(s.Code()),
    		Details: s.Proto().GetDetails(),
    	}
    
    	buf, merr := marshaler.Marshal(body)
    	if merr != nil {
    		grpclog.Infof("Failed to marshal error message %q: %v", body, merr)
    		w.WriteHeader(http.StatusInternalServerError)
    		if _, err := io.WriteString(w, fallback); err != nil {
    			grpclog.Infof("Failed to write response: %v", err)
    		}
    		return
    	}
    
    	md, ok := ServerMetadataFromContext(ctx)
    	if !ok {
    		grpclog.Infof("Failed to extract ServerMetadata from context")
    	}
    
    	handleForwardResponseServerMetadata(w, mux, md)
    	handleForwardResponseTrailerHeader(w, md)
    	st := HTTPStatusFromCode(s.Code())
    	w.WriteHeader(st)
    	if _, err := w.Write(buf); err != nil {
    		grpclog.Infof("Failed to write response: %v", err)
    	}
    
    	handleForwardResponseTrailer(w, md)
    }
    
    // DefaultOtherErrorHandler is the default implementation of OtherErrorHandler.
    // It simply writes a string representation of the given error into "w".
    func DefaultOtherErrorHandler(w http.ResponseWriter, _ *http.Request, msg string, code int) {
    	http.Error(w, msg, code)
    }



    https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto

    // Copyright 2017 Google Inc.
    //
    // 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.
    
    syntax = "proto3";
    
    package google.rpc;
    
    option go_package = "google.golang.org/genproto/googleapis/rpc/code;code";
    option java_multiple_files = true;
    option java_outer_classname = "CodeProto";
    option java_package = "com.google.rpc";
    option objc_class_prefix = "RPC";
    
    
    // The canonical error codes for Google APIs.
    //
    //
    // Sometimes multiple error codes may apply.  Services should return
    // the most specific error code that applies.  For example, prefer
    // `OUT_OF_RANGE` over `FAILED_PRECONDITION` if both codes apply.
    // Similarly prefer `NOT_FOUND` or `ALREADY_EXISTS` over `FAILED_PRECONDITION`.
    enum Code {
      // Not an error; returned on success
      //
      // HTTP Mapping: 200 OK
      OK = 0;
    
      // The operation was cancelled, typically by the caller.
      //
      // HTTP Mapping: 499 Client Closed Request
      CANCELLED = 1;
    
      // Unknown error.  For example, this error may be returned when
      // a `Status` value received from another address space belongs to
      // an error space that is not known in this address space.  Also
      // errors raised by APIs that do not return enough error information
      // may be converted to this error.
      //
      // HTTP Mapping: 500 Internal Server Error
      UNKNOWN = 2;
    
      // The client specified an invalid argument.  Note that this differs
      // from `FAILED_PRECONDITION`.  `INVALID_ARGUMENT` indicates arguments
      // that are problematic regardless of the state of the system
      // (e.g., a malformed file name).
      //
      // HTTP Mapping: 400 Bad Request
      INVALID_ARGUMENT = 3;
    
      // The deadline expired before the operation could complete. For operations
      // that change the state of the system, this error may be returned
      // even if the operation has completed successfully.  For example, a
      // successful response from a server could have been delayed long
      // enough for the deadline to expire.
      //
      // HTTP Mapping: 504 Gateway Timeout
      DEADLINE_EXCEEDED = 4;
    
      // Some requested entity (e.g., file or directory) was not found.
      //
      // Note to server developers: if a request is denied for an entire class
      // of users, such as gradual feature rollout or undocumented whitelist,
      // `NOT_FOUND` may be used. If a request is denied for some users within
      // a class of users, such as user-based access control, `PERMISSION_DENIED`
      // must be used.
      //
      // HTTP Mapping: 404 Not Found
      NOT_FOUND = 5;
    
      // The entity that a client attempted to create (e.g., file or directory)
      // already exists.
      //
      // HTTP Mapping: 409 Conflict
      ALREADY_EXISTS = 6;
    
      // The caller does not have permission to execute the specified
      // operation. `PERMISSION_DENIED` must not be used for rejections
      // caused by exhausting some resource (use `RESOURCE_EXHAUSTED`
      // instead for those errors). `PERMISSION_DENIED` must not be
      // used if the caller can not be identified (use `UNAUTHENTICATED`
      // instead for those errors). This error code does not imply the
      // request is valid or the requested entity exists or satisfies
      // other pre-conditions.
      //
      // HTTP Mapping: 403 Forbidden
      PERMISSION_DENIED = 7;
    
      // The request does not have valid authentication credentials for the
      // operation.
      //
      // HTTP Mapping: 401 Unauthorized
      UNAUTHENTICATED = 16;
    
      // Some resource has been exhausted, perhaps a per-user quota, or
      // perhaps the entire file system is out of space.
      //
      // HTTP Mapping: 429 Too Many Requests
      RESOURCE_EXHAUSTED = 8;
    
      // The operation was rejected because the system is not in a state
      // required for the operation's execution.  For example, the directory
      // to be deleted is non-empty, an rmdir operation is applied to
      // a non-directory, etc.
      //
      // Service implementors can use the following guidelines to decide
      // between `FAILED_PRECONDITION`, `ABORTED`, and `UNAVAILABLE`:
      //  (a) Use `UNAVAILABLE` if the client can retry just the failing call.
      //  (b) Use `ABORTED` if the client should retry at a higher level
      //      (e.g., when a client-specified test-and-set fails, indicating the
      //      client should restart a read-modify-write sequence).
      //  (c) Use `FAILED_PRECONDITION` if the client should not retry until
      //      the system state has been explicitly fixed.  E.g., if an "rmdir"
      //      fails because the directory is non-empty, `FAILED_PRECONDITION`
      //      should be returned since the client should not retry unless
      //      the files are deleted from the directory.
      //
      // HTTP Mapping: 400 Bad Request
      FAILED_PRECONDITION = 9;
    
      // The operation was aborted, typically due to a concurrency issue such as
      // a sequencer check failure or transaction abort.
      //
      // See the guidelines above for deciding between `FAILED_PRECONDITION`,
      // `ABORTED`, and `UNAVAILABLE`.
      //
      // HTTP Mapping: 409 Conflict
      ABORTED = 10;
    
      // The operation was attempted past the valid range.  E.g., seeking or
      // reading past end-of-file.
      //
      // Unlike `INVALID_ARGUMENT`, this error indicates a problem that may
      // be fixed if the system state changes. For example, a 32-bit file
      // system will generate `INVALID_ARGUMENT` if asked to read at an
      // offset that is not in the range [0,2^32-1], but it will generate
      // `OUT_OF_RANGE` if asked to read from an offset past the current
      // file size.
      //
      // There is a fair bit of overlap between `FAILED_PRECONDITION` and
      // `OUT_OF_RANGE`.  We recommend using `OUT_OF_RANGE` (the more specific
      // error) when it applies so that callers who are iterating through
      // a space can easily look for an `OUT_OF_RANGE` error to detect when
      // they are done.
      //
      // HTTP Mapping: 400 Bad Request
      OUT_OF_RANGE = 11;
    
      // The operation is not implemented or is not supported/enabled in this
      // service.
      //
      // HTTP Mapping: 501 Not Implemented
      UNIMPLEMENTED = 12;
    
      // Internal errors.  This means that some invariants expected by the
      // underlying system have been broken.  This error code is reserved
      // for serious errors.
      //
      // HTTP Mapping: 500 Internal Server Error
      INTERNAL = 13;
    
      // The service is currently unavailable.  This is most likely a
      // transient condition, which can be corrected by retrying with
      // a backoff.
      //
      // See the guidelines above for deciding between `FAILED_PRECONDITION`,
      // `ABORTED`, and `UNAVAILABLE`.
      //
      // HTTP Mapping: 503 Service Unavailable
      UNAVAILABLE = 14;
    
      // Unrecoverable data loss or corruption.
      //
      // HTTP Mapping: 500 Internal Server Error
      DATA_LOSS = 15;
    }



    grpc-ecosystem/grpc-gateway: gRPC to JSON proxy generator following the gRPC HTTP spec
    https://github.com/grpc-ecosystem/grpc-gateway

  • 相关阅读:
    [python subprocess学习篇] 调用系统命令
    linux dd命令创建一定大小的文件
    [linux time命令学习篇] time 统计命令执行的时间
    新建应用母版页的网页index.aspx,about.aspx,login.aspx
    MOSS母板页制作 学习笔记(一)
    SharePoint 2010顶部链接导航栏的详细操作
    使用SharePoint 2010 母版页
    SharePoint 2010 母版页制作的简单介绍
    在 SharePoint 2010 中访问数据
    牛刀小试、用SharePoint 实现请假管理功能
  • 原文地址:https://www.cnblogs.com/rsapaper/p/9304192.html
Copyright © 2011-2022 走看看