Конечная точка HTTP grpc-шлюза. POST-запрос возвращает json: не может распаковать объект в значение Go типа string
Я использую Protocol Buffers, gRPC и Go для создания CRUD API. Я использовал grpc-gateway для предоставления конечных точек HTTP для моего сервера gRPC. Мои реализации gRPC как клиента, так и сервера работают нормально. Когда я отправляю запрос POST (для метода Create), используя cURL, ответ {"error":"json: cannot unmarshal object into Go value of type string","message":"json: cannot unmarshal object into Go value of type string","code":3}
,
Я работаю на Windows 10 и Go 1.11. Все grpc-шлюзы, протоколы и соответствующие зависимости обновлены в соответствии с инструкциями на https://github.com/grpc-ecosystem/grpc-gateway. Я зашел так далеко, что попытался отладить (не) функции маршалинга среды выполнения grpc-gateway, но безрезультатно. HTTP-прокси получает строку JSON просто отлично.
Настройка body:
Атрибут опции RPC к типу сообщения не помогает. пример body: text_post
Удаление... Запрос... Ответные абстракции и установка входных и выходных параметров на прямой TextPost
тоже не помогло.
Я подозреваю, что это может быть вложенный атрибут сообщения (т.е. CreateTextPostRequest.text_post является TextPost). Я также попытался удалить все строковые параметры, так как они являются необязательными по умолчанию в буферах протокола 3. Наконец, я попытался экранировать строку JSON для нескольких проблем GitHub.
Мои определения буфера протокола.
syntax = "proto3";
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
message Location {
double latitude = 1;
double longitude = 2;
}
message TextPost {
string content_id = 1;
string owner_id = 2;
string title = 3;
string text_body = 4;
repeated string tags = 5;
google.protobuf.Timestamp created_at = 6;
Location location_posted = 7;
// Photo post_icon = 8;
}
message CreateTextPostRequest {
TextPost text_post = 1;
}
message CreateTextPostResponse {
TextPost text_post = 1;
}
service ContentService {
rpc CreateTextPost (CreateTextPostRequest) returns (CreateTextPostResponse) {
option (google.api.http) = {
post: "/v1/content/text"
body: "*"
};
}
}
И вызов curl (использование заголовков content-type/accept также не помогло):
curl -X POST -d '{"text_post": {"owner_id": "TestingSimon", "title": "This is a title.", "text_body": "This is a story.", "tags": ["story", "poem", "haiku"], "created_at": {"seconds": 1550204918, "nanos": 902975700}, "location_posted": {"latitude": 33.5779, "longitude": 101.8552 }}}' \
http://localhost:8080/v1/content/text
устанавливать правила на всякий случай
content:
protoc -I${GOPATH}/src \
-I${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--proto_path=api/protos/contentpb \
--go_out=plugins=grpc:./api/protos/contentpb \
api/protos/contentpb/content.proto
contentproxy:
protoc -I${GOPATH}/src \
-I${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--proto_path=api/protos/contentpb \
--grpc-gateway_out=logtostderr=true:./api/protos/contentpb \
api/protos/contentpb/content.proto
Точка входа HTTP определена точно так, как указано в шаге 6 README, найденном здесь: https://github.com/grpc-ecosystem/grpc-gateway
Ожидаемый результат: Marshaled TextPostResponse
Фактический результат: {"error":"json: cannot unmarshal object into Go value of type string","message":"json: cannot unmarshal object into Go value of type string","code":3}
Редактировать: я изолировал проблему, так как grpc-gateway не смог разархивировать запрос JSON в google.protobuf.Timestamp
который является *timestamp.Timestamp от github.com/golang/protobuf/ptypes/timestamp
,
Успешный запрос:
curl -H "Accept: application/jsonpb" \
-H "Content-Type: application/json" \
-X POST -d '{"text_post": {"owner_id": "UserSimon", "title": "This is a title.", "text_body": "This is a story.", "tags": ["story", "poem", "haiku"], "location_posted": {"latitude": 33.5779, "longitude": 101.8552 }}}' \
http://localhost:8080/v1/content/text
Отклик:
{"text_post":{"content_id":"9aa72c19-857a-4f80-9bd4-73a5df90c72c","owner_id":"UserSimon","title":"This is a title.","text_body":"This is a story.","tags":["story","poem","haiku"],"location_posted":{"latitude":33.5779,"longitude":101.8552}}}
Я полагаю, я мог бы опустить метку времени, которая отправлялась как "created_at": {"seconds": 1550204918, "nanos": 902975700}
в запросе?