googleapis / gax-nodejs

Google API Extensions for Node.js
Apache License 2.0
117 stars 88 forks source link

error json format assumes that object should includes 'error' fields #1303

Open sckimynwa opened 2 years ago

sckimynwa commented 2 years ago

Overview

HI. I'm developing grpc-based web service with protobuf-generated SDKs.

when handling Error Message According to AIP Spec(mentioned below), Server gives the Error in json format. (which satisfies AIP Error Format. I think)

{
  "grpc-code":"SOME CODE",
  "message":"some message"
}

But, When Client tries to handle this error, this error shows up. image

According to source code (src/googleError.ts), the input json parameter assumes that it "should" have "error" field (which AIP Spec doesn't describe.)

I found that this format exists because Google's API Platforms compatibility reasons. but in order to support protobuf spec, Can you support protobuf Error Spec? (Google AIP Error Spec)

While proto3 messages have native JSON encoding, Google's API Platform uses a different error schema for Google's JSON HTTP APIs for backward compatibility reasons.

https://cloud.google.com/apis/design/errors#http_mapping

Google AIP Error Spec

// The `Status` type defines a logical error model that is suitable for
// different programming environments, including REST APIs and RPC APIs. It is
// used by [gRPC](https://github.com/grpc). Each `Status` message contains
// three pieces of data: error code, error message, and error details.
//
// You can find out more about this error model and how to work with it in the
// [API Design Guide](https://cloud.google.com/apis/design/errors).
message Status {
  // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
  int32 code = 1;

  // A developer-facing error message, which should be in English. Any
  // user-facing error message should be localized and sent in the
  // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
  string message = 2;

  // A list of messages that carry the error details.  There is a common set of
  // message types for APIs to use.
  repeated google.protobuf.Any details = 3;
}

Current Implementation (gax-nodejs)

static parseHttpError(json: any): GoogleError {
    if (Array.isArray(json)) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      json = json.find((obj: any) => {
        return 'error' in obj;
      });
    }
    const decoder = new GoogleErrorDecoder();
    const proto3Error = decoder.decodeHTTPError(json['error']);
    const error = Object.assign(
      new GoogleError(json['error']['message']),
      proto3Error
    );
    // Map Http Status Code to gRPC Status Code
    if (json['error']['code']) {
      error.code = rpcCodeFromHttpStatusCode(json['error']['code']);
    } else {
      // If error code is absent, proto3 message default value is 0. We should
      // keep error code as undefined.
      delete error.code;
    }
alexander-fenster commented 2 years ago

Thanks @sckimynwa! I will need some time to figure out what's going on here, I'll get back to you here in this issue.