Marwan Sulaiman
The New York Times
Go NYC July 18th, 2019
{
"swagger": "2.0",
"info": {
"title": "Search API",
"version": "1.0",
"contact": {
"name": "Search Team",
"email": "searchteam@product.com"
}
},
"host": "search.product.com",
"schemes": [
"http",
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/search": {
"get": {
"summary": "search allows you to search by a keyword",
"operationId": "Search",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/SearchResult"
}
},
"400": {
"description": "missing query"
}
},
"parameters": [
{
"name": "q",
"in": "query",
"required": true,
"type": "string"
}
],
"tags": [
"Service"
]
}
}
},
"definitions": {
"SearchResult": {
"type": "object",
"properties": {
"Sites": {
"type": "array",
"items": {
"type": "string"
}
},
"Images": {
"type": "array",
"items": {
"type": "string"
}
},
"Videos": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
service Index {
rpc Search(SearchRequest) returns (SearchResponse);
}
message SearchRequest {
string query = 1;
}
message SearchResponse {
repeated string URLS = 1;
repeated string images = 2;
repeated string videos = 3;
}
~ go get github.com/golang/protobuf/protoc-gen-go
~ protoc --go_out=. service.proto
type SearchRequest struct {
Query string `json:"query"`
}
type SearchResponse struct {
URLS []string `json:"URLS"`
Images []string `json:"images"`
Videos []string `json:"videos"`
}
~ go get github.com/twitchtv/twirp/protoc-gen-twirp
~ protoc --go_out=. --twirp_out=. service.proto
type Index interface {
Search(context.Context, *SearchRequest) (*SearchResponse, error)
}
func NewIndexServer(Index) http.Handler {}
func NewIndexJSONClient(addr string) Index {}
func NewIndexProtobufClient(addr string) Index {}
~ go get github.com/elliots/protoc-gen-twirp_swagger
~ protoc --twirp_swagger_out=. service.proto
{
"swagger": "2.0",
"info": {
"title": "service.proto",
"version": "version not set"
},
"schemes": [
"http",
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/twirp/company.indexteam.Index/Search": {
"post": {
"operationId": "Search",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/indexteamSearchResponse"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/indexteamSearchRequest"
}
}
],
"tags": [
"Index"
]
}
}
},
"definitions": {
"indexteamSearchRequest": {
"type": "object",
"properties": {
"query": {
"type": "string"
}
}
},
"indexteamSearchResponse": {
"type": "object",
"properties": {
"URLS": {
"type": "array",
"items": {
"type": "string"
}
},
"images": {
"type": "array",
"items": {
"type": "string"
}
},
"videos": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
~ curl -H "Content-Type: application/json" -d '{"query": "Go"}' \
'localhost:8080/twirp/company.indexteam.Index/Search'
package main
import (
"companyindex"
"context"
"fmt"
"net/http"
)
func main() {
idx := companyindex.NewIndexProtobufClient(
"http://localhost:8080",
http.DefaultClient,
)
resp, err := idx.Search(context.Background(), &companyindex.SearchRequest{
Query: "Go",
})
if err != nil {
panic(err)
}
fmt.Println(resp)
}
~ go get marwan.io/protoc-gen-twirpql
~ protoc --twirpql_out=. service.proto
func Handler(service Index) http.Handler {}
func Playground(title, endpoint string) http.Handler {}