Skip to content

Commit

Permalink
protoc-gen-openapi (#221)
Browse files Browse the repository at this point in the history
* First steps toward a protoc plugin for generating OpenAPI models.

Based on the Go code generation plugin (protoc-gen-go) and the
gnostic petstore-builder sample app.

* protoc-gen-openapi operation stubs

* updated, fixed build problems

* preliminary structural improvements to put everything in a single spec.

* handle more field and array types + patch requests

* work-in-progress, focusing on generating OpenAPI v3 from protoc-gen-openapi

* protoc-gen-openapi only generates v3, now includes parameters

* protoc-gen-openapi: get API name and description from protos.

* protoc-gen-openapi: only export schemas that are used

* protoc-gen-openapi: include message and field comments in openapi

* protoc-gen-openapi: mark output-only fields

* protoc-gen-openapi: general cleanup

* protoc-gen-openapi: add test

* protoc-gen-openapi: update to use the v2 protobuf-go plugin API

* protoc-gen-openapi: remove unneeded parameters from buildOperationV3

* protoc-gen-openapi: remove blank lines
  • Loading branch information
timburks committed Oct 23, 2020
1 parent 7fb1841 commit 42aec32
Show file tree
Hide file tree
Showing 23 changed files with 2,261 additions and 12 deletions.
20 changes: 20 additions & 0 deletions apps/protoc-gen-openapi/README.md
@@ -0,0 +1,20 @@
# protoc-gen-openapi

This directory contains a protoc plugin that generates an
OpenAPI description for a REST API that corresponds to a
Protocol Buffer service.

Installation:

go get github.com/googleapis/gnostic
go install github.com/googleapis/gnostic/apps/protoc-gen-openapi


Usage:

protoc sample.proto -I. --openapi_out=.

This runs the plugin for a file named `sample.proto` which
refers to additional .proto files in the same directory as
`sample.proto`. Output is written to the current directory.

31 changes: 31 additions & 0 deletions apps/protoc-gen-openapi/examples/google/api/annotations.proto
@@ -0,0 +1,31 @@
// Copyright (c) 2015, 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.api;

import "google/api/http.proto";
import "google/protobuf/descriptor.proto";

option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
option java_multiple_files = true;
option java_outer_classname = "AnnotationsProto";
option java_package = "com.google.api";
option objc_class_prefix = "GAPI";

extend google.protobuf.MethodOptions {
// See `HttpRule`.
HttpRule http = 72295728;
}
101 changes: 101 additions & 0 deletions apps/protoc-gen-openapi/examples/google/api/client.proto
@@ -0,0 +1,101 @@
// 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
//
// https://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.api;

import "google/protobuf/descriptor.proto";

option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
option java_multiple_files = true;
option java_outer_classname = "ClientProto";
option java_package = "com.google.api";
option objc_class_prefix = "GAPI";


extend google.protobuf.ServiceOptions {
// The hostname for this service.
// This should be specified with no prefix or protocol.
//
// Example:
//
// service Foo {
// option (google.api.default_host) = "foo.googleapi.com";
// ...
// }
string default_host = 1049;

// OAuth scopes needed for the client.
//
// Example:
//
// service Foo {
// option (google.api.oauth_scopes) = \
// "https://www.googleapis.com/auth/cloud-platform";
// ...
// }
//
// If there is more than one scope, use a comma-separated string:
//
// Example:
//
// service Foo {
// option (google.api.oauth_scopes) = \
// "https://www.googleapis.com/auth/cloud-platform,"
// "https://www.googleapis.com/auth/monitoring";
// ...
// }
string oauth_scopes = 1050;
}


extend google.protobuf.MethodOptions {
// A definition of a client library method signature.
//
// In client libraries, each proto RPC corresponds to one or more methods
// which the end user is able to call, and calls the underlying RPC.
// Normally, this method receives a single argument (a struct or instance
// corresponding to the RPC request object). Defining this field will
// add one or more overloads providing flattened or simpler method signatures
// in some languages.
//
// The fields on the method signature are provided as a comma-separated
// string.
//
// For example, the proto RPC and annotation:
//
// rpc CreateSubscription(CreateSubscriptionRequest)
// returns (Subscription) {
// option (google.api.method_signature) = "name,topic";
// }
//
// Would add the following Java overload (in addition to the method accepting
// the request object):
//
// public final Subscription createSubscription(String name, String topic)
//
// The following backwards-compatibility guidelines apply:
//
// * Adding this annotation to an unannotated method is backwards
// compatible.
// * Adding this annotation to a method which already has existing
// method signature annotations is backwards compatible if and only if
// the new method signature annotation is last in the sequence.
// * Modifying or removing an existing method signature annotation is
// a breaking change.
// * Re-ordering existing method signature annotations is a breaking
// change.
repeated string method_signature = 1051;
}
80 changes: 80 additions & 0 deletions apps/protoc-gen-openapi/examples/google/api/field_behavior.proto
@@ -0,0 +1,80 @@
// 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
//
// https://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.api;

import "google/protobuf/descriptor.proto";

option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
option java_multiple_files = true;
option java_outer_classname = "FieldBehaviorProto";
option java_package = "com.google.api";
option objc_class_prefix = "GAPI";


// An indicator of the behavior of a given field (for example, that a field
// is required in requests, or given as output but ignored as input).
// This **does not** change the behavior in protocol buffers itself; it only
// denotes the behavior and may affect how API tooling handles the field.
//
// Note: This enum **may** receive new values in the future.
enum FieldBehavior {
// Conventional default for enums. Do not use this.
FIELD_BEHAVIOR_UNSPECIFIED = 0;

// Specifically denotes a field as optional.
// While all fields in protocol buffers are optional, this may be specified
// for emphasis if appropriate.
OPTIONAL = 1;

// Denotes a field as required.
// This indicates that the field **must** be provided as part of the request,
// and failure to do so will cause an error (usually `INVALID_ARGUMENT`).
REQUIRED = 2;

// Denotes a field as output only.
// This indicates that the field is provided in responses, but including the
// field in a request does nothing (the server *must* ignore it and
// *must not* throw an error as a result of the field's presence).
OUTPUT_ONLY = 3;

// Denotes a field as input only.
// This indicates that the field is provided in requests, and the
// corresponding field is not included in output.
INPUT_ONLY = 4;

// Denotes a field as immutable.
// This indicates that the field may be set once in a request to create a
// resource, but may not be changed thereafter.
IMMUTABLE = 5;
}


extend google.protobuf.FieldOptions {
// A designation of a specific field behavior (required, output only, etc.)
// in protobuf messages.
//
// Examples:
//
// string name = 1 [(google.api.field_behavior) = REQUIRED];
// State state = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
// google.protobuf.Duration ttl = 1
// [(google.api.field_behavior) = INPUT_ONLY];
// google.protobuf.Timestamp expire_time = 1
// [(google.api.field_behavior) = OUTPUT_ONLY,
// (google.api.field_behavior) = IMMUTABLE];
repeated FieldBehavior field_behavior = 1052;
}

0 comments on commit 42aec32

Please sign in to comment.