- Status: accepted
- Deciders: Fabien Boucher
- Date: 2021-04-22
- Issue: #346
- The current API implementations is spread across multiple modules (such as webapp, config, db and query) without a formal definition of the inputs/outputs. This induces inconsistencies and we foresee technical difficulties to maintain and evole the service.
- We would like to use an interface description language to define the API between the various component (such as between the webapi and webclients, worker and database).
- How do we define and maintain the interfaces?
- OpenAPI Swagger
- Protobuf
- Thrift
Chosen option: "Protobuf", because it comes out best (see below).
- We need to start defining interfaces outside of their implementations.
- We need to use a simpler HTTP api (e.g. the path for the action function name and the body for its input), instead of encoding the inputs with a mix of path, querystring and body components.
For example, use
POST /get_projects BODY { "index": "name" }instead ofGET /projects?index=name.
- The team needs to learn a new language.
- Follow-up decisions required for the actual implementation.
Zuul example: https://opendev.org/zuul/zuul/raw/branch/master/web/public/openapi.yaml (generated webclient: https://zuul.opendev.org/openapi ).
- Good, because it defines common HTTP APIs.
- Bad, because it is hard to maintain.
Google APIs example: https://github.com/googleapis/googleapis. ETCD APIs model kv.proto and rpc.proto.
Proof of concept for the upcoming filter sugestion api of Monocle:
// monocle.proto
// Copyright: (c) 2021 Monocle authors
// SPDX-License-Identifier: AGPL-3.0-only
syntax = "proto3";
import "google/api/annotations.proto";
option go_package = "monocle/config";
message ProjectDefinition {
string name = 1;
string repository_regex = 2;
string branch_regex = 3;
string file_regex = 4;
}
message GetProjectsRequest {
string index = 1;
}
message GetProjectsResponse {
repeated ProjectDefinition projects = 1;
}
service Monocle {
rpc GetProjects(GetProjectsRequest) returns (GetProjectsResponse) {
option (google.api.http) = {
post: "/api/1/get_projects"
body: "*"
};
}
}# Generate openapi from protobuf definition
protoc search.proto -I/home/tdecacqu/src/github.com/googleapis/googleapis/ -I. --openapi_out=.# monocle-openapi.yaml
openapi: 3.0.3
info:
title: Monocle
version: 0.0.1
paths:
/api/1/get_projects:
post:
operationId: Monocle_GetProjects
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/GetProjectsRequest'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/GetProjectsResponse'
components:
schemas:
GetProjectsRequest:
properties:
index:
type: string
GetProjectsResponse:
properties:
projects:
type: array
items:
$ref: '#/components/schemas/ProjectDefinition'
ProjectDefinition:
properties:
name:
type: string
repository_regex:
type: string
branch_regex:
type: string
file_regex:
type: string- Good, because it is a stable standard.
- Good, because it enables high quality code generation for client and server.
- Bad, because it requires custom tooling to work with.
- Good, it has many languages implementations.
- Good, it can describes function error with exception.
- Bad, the JSON serialization is not human readable.