Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add header annotations to OpenAPIv2 generator #2932

Closed
amitavaghosh1 opened this issue Oct 12, 2022 · 9 comments · Fixed by #3010
Closed

Add header annotations to OpenAPIv2 generator #2932

amitavaghosh1 opened this issue Oct 12, 2022 · 9 comments · Fixed by #3010

Comments

@amitavaghosh1
Copy link

I am generating openapi v2 documentation. using buf generate

service PageService {
  option (grpc.gateway.protoc_gen_swagger.options.openapiv2_tag) = {
    info: {
      title: "Create and view pages to group notes";
    };
  };

  rpc CreatePage (CreatePageRequest) returns (ApiResponse) {
    option(google.api.http) = {
      post: "/api/pages/{id}",
      body: "*"
    };
  }

  rpc GetPageDetails(GetPageRequest) returns (ApiResponse) {
    option(google.api.http) = {
      get: "/api/pages/{id}"
    };
  }
}

message CreatePageRequest {
  string id = 1;
  string description = 2;

  google.protobuf.Timestamp dated_at = 3;
}

message GetPageRequest {
  string id = 1;
  bool show_items = 2;
}

/* more code */

this is a part of how my proto file looks like. I was wondering if there is any way to use annotations to generate the swagger.json such that it shows up in headers like.

api_key:
  type: apiKey
  name: api_key
  in: header
@johanbrandhorst
Copy link
Collaborator

Yep!

option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
info: {
title: "A Bit of Everything";
version: "1.0";
contact: {
name: "gRPC-Gateway project";
url: "https://github.com/grpc-ecosystem/grpc-gateway";
email: "none@example.com";
};
license: {
name: "BSD 3-Clause License";
url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/master/LICENSE.txt";
};
extensions: {
key: "x-something-something";
value {
string_value: "yadda";
}
}
};
// Overwriting host entry breaks tests, so this is not done here.
external_docs: {
url: "https://github.com/grpc-ecosystem/grpc-gateway";
description: "More about gRPC-Gateway";
}
schemes: HTTP;
schemes: HTTPS;
schemes: WSS;
consumes: "application/json";
consumes: "application/x-foo-mime";
produces: "application/json";
produces: "application/x-foo-mime";
security_definitions: {
security: {
key: "BasicAuth";
value: {
type: TYPE_BASIC;
}
}
security: {
key: "ApiKeyAuth";
value: {
type: TYPE_API_KEY;
in: IN_HEADER;
name: "X-API-Key";
extensions: {
key: "x-amazon-apigateway-authtype";
value {
string_value: "oauth2";
}
}
extensions: {
key: "x-amazon-apigateway-authorizer";
value {
struct_value {
fields {
key: "type";
value {
string_value: "token";
}
}
fields {
key: "authorizerResultTtlInSeconds";
value {
number_value: 60;
}
}
}
}
}
}
}
security: {
key: "OAuth2";
value: {
type: TYPE_OAUTH2;
flow: FLOW_ACCESS_CODE;
authorization_url: "https://example.com/oauth/authorize";
token_url: "https://example.com/oauth/token";
scopes: {
scope: {
key: "read";
value: "Grants read access";
}
scope: {
key: "write";
value: "Grants write access";
}
scope: {
key: "admin";
value: "Grants read and write access to administrative information";
}
}
}
}
}
security: {
security_requirement: {
key: "BasicAuth";
value: {};
}
security_requirement: {
key: "ApiKeyAuth";
value: {};
}
}
security: {
security_requirement: {
key: "OAuth2";
value: {
scope: "read";
scope: "write";
}
}
security_requirement: {
key: "ApiKeyAuth";
value: {};
}
}
responses: {
key: "403";
value: {
description: "Returned when the user does not have permission to access the resource.";
}
}
responses: {
key: "404";
value: {
description: "Returned when the resource does not exist.";
schema: {
json_schema: {
type: STRING;
}
}
}
}
responses: {
key: "418";
value: {
description: "I'm a teapot.";
schema: {
json_schema: {
ref: ".grpc.gateway.examples.internal.proto.examplepb.NumericEnum";
}
}
}
}
responses: {
key: "500";
value: {
description: "Server error";
headers: {
key: "X-Correlation-Id"
value: {
description: "Unique event identifier for server requests"
type: "string"
format: "uuid"
default: "\"2438ac3c-37eb-4902-adef-ed16b4431030\""
pattern: "^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$"
}
};
schema: {
json_schema: {
ref: ".grpc.gateway.examples.internal.proto.examplepb.ErrorResponse";
}
}
}
}
extensions: {
key: "x-grpc-gateway-foo";
value {
string_value: "bar";
}
}
extensions: {
key: "x-grpc-gateway-baz-list";
value {
list_value: {
values: {
string_value: "one";
}
values: {
bool_value: true;
}
}
}
}
};
contains some examples of how to add security definitions and also response headers. Hope that helps!

@amitavaghosh1
Copy link
Author

amitavaghosh1 commented Oct 13, 2022

@johanbrandhorst

I meant http request headers like say X-Request-ID not security definitions. Per rpc Service definitions

I tried this:

rpc CreatePage (CreatePageRequest) returns (ApiResponse) {
    option(google.api.http) = {
      post: "/api/pages/{id}",
      body: "*"
    };

  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_header) = {
    description: "x-request-id";
    type: "string";
  };
}

But that isn't working

Also i made a simple setup script for a barebones setup

https://github.com/amitavaghosh1/setup/tree/main/golang/grpcproj

@johanbrandhorst
Copy link
Collaborator

It doesn't look like you can specify request headers, no.

@ikouchiha47
Copy link

@johanbrandhorst is there any way to add support for this? In the openapiv2.proto file, the message definition is there. Openapi supports request header.

So what to do now?

@johanbrandhorst
Copy link
Collaborator

We'd have to add the definitions for specifying headers into the annotations (here). I'm not actually sure where the header definitions would go, probably on an Operation? You'd have to look through the OpenApiv2 spec to see where it fits, the definitions should be somewhat 1:1 to the spec.

Once we have the annotation option in place we need to add parsing of the option into the openapiv2 generator, to produce the output in the final file.

@johanbrandhorst johanbrandhorst changed the title Is there a way to annotate headers in proto file Add header annotations to OpenAPIv2 generator Oct 14, 2022
@amitavaghosh1
Copy link
Author

amitavaghosh1 commented Oct 20, 2022

I think we should have a message Parameters and then in there we can have headers and path. Because the specs go like:

And that goes inside Operation

 "parameters": [
    {
      "name": "petId",
      "in": "path",
      "description": "ID of pet that needs to be updated",
      "required": true,
      "type": "string"
    },
    {
      "name": "name",
      "in": "formData",
      "description": "Updated name of the pet",
      "required": false,
      "type": "string"
    },
 {
      "name": "token",
      "in": "header",
      "description": "access token",
      "required": true,
      "type": "string"
    },
]

#2970 If you could have a look. I started working on this. @johanbrandhorst

I am not sure how to proceed from here. https://github.com/grpc-ecosystem/grpc-gateway/blob/master/protoc-gen-openapiv2/internal/genopenapi/types.go#L126 here I see some parameters object already specified. I am confused a bit.

@johanbrandhorst
Copy link
Collaborator

Hm, the problem with using parameters is that it lets users mess with the information generated from the RPC definitions themselves. I would really prefer things like parameters, URL path, etc to be impossible to break by adding annotations to the protobuf files. Maybe we could add parameters but only allow headers to be specified? Also not that it will always be in addition to what the RPC interface itself guarantees, which makes the specifying of headers itself brittle.

@amitavaghosh1
Copy link
Author

Okay. I will try and make those changes.

@krak3n
Copy link
Contributor

krak3n commented Nov 11, 2022

Implementation in #3010

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants