Protoc Gen WEB Handler
protoc-gen-web-handler
- плагин к protoc,позволяющий генерировать обертку RESTful к фреймворкам Echo, Gin из proto-файла.
Генерация осуществляется на базе аннотации google.api.http и её реализации в проекте grpc-gateway.
Установка
go get gitlab.com/ovsinc/protoc-gen-web-handler
Приложение protoc-gen-web-handler
будет установлено в директорию $(go env GOPATH)/bin
. Можно изменить путь установки, если определить требуемое значение в переменной окружения GOBIN
.
Генерация кода
Приложение нельзя запускать самостоятельно, только в связке с protoc.
Для работы "protoc-gen-web-handler" должно быть доступено через переменную окружения $PATH.
Пример запуска:
protoc \
-I=. \
-I=$(go env GOPATH)/src/github.com/envoyproxy/protoc-gen-validate \
-I=$(go env GOPATH)/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--go_out=plugins=grpc:. \
--web-handler_out=:. \
simple.proto
Доступны настройки:
- err_binding_code [int] - http code ответа при обнаружении ошибки при echo.Context#Bind запроса. По-умолчанию - 400.
- err_validation_code [int] - http code ответа при обнаружении ошибки валидации запроса. По-умолчанию - 422.
- use_validation [bool] - добавить в полученных код Валидацию запроса. По-умолчанию - true.
- use_binding [bool] - добавить в полученный код биндинга запроса на структуру запроса. Oтключение биндинга автоматически отключает валидацию. По-умолчанию - true.
- paths [string] - указать как будут структурироваться генерированные файлы. По-умолчанию - "". Доступные значения: "import"(""), "source_relative".
- framework [string] - указать используемый веб фреймворк. По-умолчанию - "echo". Доступные значения: "echo", "gin".
- pb_package [string] - указать pb-пакет, генерируемому с помощью protoc-gen-go. По-умолчанию - "" (все сгенерированные файлы находятся в одном каталоге - импорт не требуется). Указание значений "" или "." отключает использование pb как внешего пакета. По-умолчанию - "".
- import_path [string] - указать полный путь пакета, если в go_package он не указан. По-умолчанию - "".
- import_prefix [string] - указать префикс пакета, если в go_package не указан полный путь пакета. По-умолчанию - "".
- no_test [bool] - отключить генерацию тестов. По-умолчанию - false.
- emit_unpopulated - добавлять или нет в результирующий JSON пустые значения. По-умолчанию - false.
В генераторе protoc-gen-web-handler
поддерживается валидаторы protoc-gen-validate или protoc-gen-govalidators.
В случае, если валидация не требуется, то генерацию кода, реализующего функцию валидации можно отключить с помощью ключа use_validation
.
Итого полный набор возможных параметров может выглядеть так:
--web-handler_out=framework=echo,
err_binding_code=400,err_validation_code=422,
use_validation=true,use_binding=true,paths=source_relative,
pb_package=gitlab.com/ovsinc/myproc/domain/pb,emit_unpopulated=false,
import_path=myproc/interfaces/web,import_prefix=gitlab.com/ovsinc:.
Использования на примере
Допустим, есть файла simple.proto
:
syntax = "proto3";
option go_package = "examplepb";
import "google/api/annotations.proto";
import "validate/validate.proto";
message Hello {
string msg = 1 [(validate.rules).string.len = 2, json_name = "msg"];
}
service HelloService {
rpc HelloRPC(Hello) returns (Hello) {
option (google.api.http) = {
post: "/hello"
body: "*"
};
}
}
Лучше не использовать параметризованные URL. Однако, если использовать такой URL необходимо, вимательно отнеситесь к его параметризованным частям. URL, содержащий, часть {param}
будет преобразован в :param
. Однако, спецификация google.api.http
поддерживает возможность использования вложенных типов в URL. Например, конструкция {param.new}
будет преобразована в :param.new
и как будет обрабатыватся URL с такой конструкцией зависит от использованного веб-фреймворка.
Для данного proto-файла будет сгенерированно два go-артефакта код-обёртка и тестовый.
Тестовай артефакт служит для проверки правильности генерации, на возможность компилляции. Производится юнит-тестирование с пустыми значениями. Отключить его генерацию можно с помощью установки флага no_test
в true
.
Иногда требуется вынести код-обертки (полученного protoc-gen-web-handler
) от кода pb-объектов (полученного с помощью protoc-gen-go
). Для решения данного вопроса нужно использовать опцию pb_package
с указанием полного пути к pb-пакету. Например, --web-handler_out=pb_package=gitlab.com/ovsinc/myproc/domain/pb:.
.
Для использования полученного кода, нужно реализовать набор методов сервиса типа <method name> (<Context>, *<request type>) (*<response type>, int, error)
. Набор методов определен в интерфейсе. Применительно к случаю simple.proto
интерфейс сервиса будет включать только один метод:
type HelloServicePayloadFuncI interface {
HelloServiceHelloRPCPayloadFunc(echo.Context, *Hello) (*Hello, int, error)
}
Для отладки в сгенерированном коде присутсвует тестовый набор методов, возвращающих ошибку http.StatusNotImplemented
.
Например, использование для фреймворка Echo может выглядеть так:
package main
import (
"net/http"
"github.com/labstack/echo"
)
func main() {
e := echo.New()
g := e.Group("/api/")
RegisterHelloServiceRoutes(g, UnimplementedHelloServicePayloadFuncs)
e.Logger.Fatal(e.Start(":1323"))
}