Skip to content

Files

Latest commit

 

History

History

api

API Guidelines

General

For more general reading on proto best practices see https://medium.com/@akhaku/protobuf-definition-best-practices-87f281576f31

Enums

All enum values should have a zero value of UNSPECIFIED. This signifies that the value was never filled in. If a real value was used for the zero value, then that value may be erroneously presented in an object despite not being filled in.

UNKNOWN is also a useful value to be used when the value needed is not present in the enum for some reason, for example when translating between two systems where a string will become an enumerated value.

enum Foo {
  UNSPECIFIED = 0;  // Value was not filled in.
  UNKNOWN = 1;      // Value could not be represented by existing enum values.
  MY_VALUE = 2;
  MY_OTHER_VALUE = 3;
}

Rules

Below are conventions followed in the Clutch APIs that are unfortunately not automatically linted yet.

The rules are meant to take as much guesswork out of naming things as possible by making the filename, package name, and services match. HTTP annotations are literal RPC, instead of trying to map RESTful concepts back onto the API.

All HTTP annotations should use the POST method

Examples of incorrect definition for this rule:

rpc GetBook(GetBookRequest) returns (GetBookResponse) {
  option (google.api.http) = {
    get : "/v1/bookstore/catalog/getBook"
  };
}
  • ❌ HTTP annotation uses GET instead of POST.

Examples of correct definition for this rule:

rpc GetBook(GetBookRequest) returns (GetBookResponse) {
  option (google.api.http) = {
    post : "/v1/bookstore/catalog/getBook"
    body : "*"
  };
}

Version should always be the trailing component of package

Examples of incorrect definition for this rule:

package clutch.aws.v1.ec2;
  • ❌ Last component of package is ec2, not v1.
package clutch.v1.healthcheck;
  • ❌ Last component of package is healthcheck, not v1.

Examples of correct definition for this rule:

package clutch.aws.ec2.v1;
package clutch.healthcheck.v1;

Package name and folder structure should match

Examples of incorrect definition for this rule:

  • Filename clutch/api/aws/v1/ec2.proto
package clutch.aws.ec2.v1;
  • ec2 is missing from folder structure.

Examples of correct definition for this rule:

  • Filename clutch/api/aws/ec2/v1/ec2.proto
package clutch.aws.ec2.v1;

Service name should match last non-version component of package name

Examples of incorrect definition for this rule:

  • Filename clutch/api/bookstore/v1/bookstore.proto
package clutch.bookstore.v1;

service BookAPI {
  ...
}
  • ❌ Last package component is bookstore, but service name is BookAPI.

  • Filename clutch/api/bookstore/catalog/v1/catalog.proto

package clutch.bookstore.catalog.v1;

service LookupAPI {
  ...
}
  • ❌ Last package component is catalog, but service name is LookupAPI.

Examples of correct definition for this rule:

  • Filename clutch/api/bookstore/v1/bookstore.proto
package clutch.bookstore.v1;

service BookstoreAPI {
  ...
}
  • Filename clutch/api/bookstore/catalog/v1/catalog.proto
package clutch.bookstore.catalog.v1;

service CatalogAPI {
  ...
}

HTTP annotation path should match package name, annotation should be same as RPC method

Examples of incorrect definition for this rule:

package clutch.bookstore.catalog.v1;

service CatalogAPI {
  rpc CreateEntry(CreateEntryRequest) returns (CreateEntryResponse) {
    option (google.api.http) = {
      post : "/v1/catalog/entry"
      body : "*"
    };
  }
}
  • ❌ Leading path is /v1/catalog, not /v1/bookstore/catalog in accordance with package name.
  • ❌ RPC method is CreateEntry but HTTP mapping is /v1/catalog/entry.

Examples of correct definition for this rule:

package clutch.bookstore.catalog.v1;

service CatalogAPI {
  rpc CreateEntry(CreateEntryRequest) returns (CreateEntryResponse) {
    option (google.api.http) = {
      post : "/v1/bookstore/catalog/createEntry"
      body : "*"
    };
  }
}