Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update docs for v2 #1388

Merged
merged 2 commits into from
May 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
301 changes: 121 additions & 180 deletions docs/_docs/customizingyourgateway.md

Large diffs are not rendered by default.

30 changes: 23 additions & 7 deletions docs/_docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,29 @@ category: documentation
# Examples

Examples are available under `examples/internal` directory.
* `proto/examplepb/echo_service.proto`, `proto/examplepb/a_bit_of_everything.proto`, `proto/examplepb/unannotated_echo_service.proto`: service definition
* `proto/examplepb/echo_service.pb.go`, `proto/examplepb/a_bit_of_everything.pb.go`, `proto/examplepb/unannotated_echo_service.pb.go`: [generated] stub of the service
* `proto/examplepb/echo_service.pb.gw.go`, `proto/examplepb/a_bit_of_everything.pb.gw.go`, `proto/examplepb/uannotated_echo_service.pb.gw.go`: [generated] reverse proxy for the service
* `proto/examplepb/unannotated_echo_service.yaml`: gRPC API Configuration for ```unannotated_echo_service.proto```
* `server/main.go`: service implementation
* `main.go`: entrypoint of the generated reverse proxy
* [`proto/examplepb/echo_service.proto`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/proto/examplepb/echo_service.proto),
[`proto/examplepb/a_bit_of_everything.proto`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/proto/examplepb/a_bit_of_everything.proto),
[`proto/examplepb/unannotated_echo_service.proto`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/proto/examplepb/unannotated_echo_service.proto):
protobuf service definitions.
* [`proto/examplepb/echo_service.pb.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/proto/examplepb/echo_service.pb.go),
[`proto/examplepb/a_bit_of_everything.pb.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/proto/examplepb/a_bit_of_everything.pb.go),
[`proto/examplepb/unannotated_echo_service.pb.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/proto/examplepb/unannotated_echo_service.pb.go):
generated Go service stubs and types.
* [`proto/examplepb/echo_service.pb.gw.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/proto/examplepb/echo_service.pb.gw.go),
[`proto/examplepb/a_bit_of_everything.pb.gw.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/proto/examplepb/a_bit_of_everything.pb.gw.go),
[`proto/examplepb/uannotated_echo_service.pb.gw.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/proto/examplepb/uannotated_echo_service.pb.gw.go):
generated gRPC-gateway clients.
* [`proto/examplepb/unannotated_echo_service.yaml`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/proto/examplepb/uannotated_echo_service.yaml):
gRPC API Configuration for `unannotated_echo_service.proto`.
* [`server/main.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/server/main.go):
service implementation.
* [`main.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/examples/internal/gateway/main.go):
entrypoint of the generated reverse proxy.

To use the same port for custom HTTP handlers (e.g. serving `swagger.json`), gRPC-gateway, and a gRPC server, see [this code example by CoreOS](https://github.com/philips/grpc-gateway-example/blob/master/cmd/serve.go) (and its accompanying [blog post](https://coreos.com/blog/grpc-protobufs-swagger.html))
To use the same port for custom HTTP handlers (e.g. serving `swagger.json`),
gRPC-gateway, and a gRPC server, see
[this code example by CoreOS](https://github.com/philips/grpc-gateway-example/blob/master/cmd/serve.go)
(and its accompanying
[blog post](https://coreos.com/blog/grpc-protobufs-swagger.html))


33 changes: 24 additions & 9 deletions docs/_docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,42 @@ title: FAQ
# FAQ

## How can I write the annotations which grpc-gateway requires?
Grpc-gateway follows the spec of [`google.api.HttpRule`](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto).
So first check out the documentation if it is feasible in the spec.
The gRPC-Gateway follows the spec of
[`google.api.HttpRule`](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto),
so first check out the documentation if it is feasible in the spec.

See also [a past discussion](https://groups.google.com/d/msg/grpc-io/Xqx80hG0D44/VNCDHjeE6pUJ) in grpc-io mailing list.
See also [a past discussion](https://groups.google.com/d/msg/grpc-io/Xqx80hG0D44/VNCDHjeE6pUJ)
in the grpc-io mailing list.

## I want to support a certain style of HTTP request but the code generated by grpc-gateway does not. How can I support this style?
See the question above at first.

Grpc-gateway is intended to cover 80% of use cases without forcing you to write comprehensive but complicated annotations. So grpc-gateway itself does not always cover all the use cases you have by design. In other words, grpc-gateway automates typical boring boilerplate mapping between gRPC and HTTP/1 communication, but it does not do arbitrarily complex custom mappings for you.
The gRPC-Gateway is intended to cover 80% of use cases without forcing you to write comprehensive but
complicated annotations. So the gateway itself does not always cover all the use cases you
have by design. In other words, the gateway automates typical boring boilerplate mapping
between gRPC and HTTP/1 communication, but it does not do arbitrarily complex custom mappings for you.

On the other hand, you can still add whatever you want as a middleware which wraps [`runtime.ServeMux`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#ServeMux). Since `runtime.ServeMux` is just a standard [`http.Handler`](http://golang.org/pkg/http#Handler), you can easily write a custom wrapper of `runtime.ServeMux`, leveraged with existing third-party libraries in Go.
e.g. https://github.com/grpc-ecosystem/grpc-gateway/blob/master/examples/internal/main.go
On the other hand, you can still add whatever you want as a middleware which wraps
[`runtime.ServeMux`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#ServeMux).
Since `runtime.ServeMux` is just a standard [`http.Handler`](http://golang.org/pkg/http#Handler),
you can easily write a custom wrapper of `runtime.ServeMux`, leveraged with existing third-party
libraries in Go.
e.g. https://github.com/grpc-ecosystem/grpc-gateway/blob/master/examples/internal/gateway/main.go

## My gRPC server is written in (Scala|C++|Ruby|Haskell|....). Is there a (Scala|C++|Ruby|Haskell|....) version of grpc-gateway?

AFAIK, no. But it should not be a big issue because the reverse-proxy which grpc-gateway generates usually works as an independent process and communicates with your gRPC server over TCP or a unix-domain socket.
AFAIK, no. But it should not be a big issue because the reverse-proxy which grpc-gateway generates
usually works as an independent process and communicates with your gRPC server over TCP or a unix-domain socket.

## Why are the models in the swagger specification prefixed with the last part of the proto package name?

The reason to generate the prefixes is that we don't have a guaranteed unique namespace. If two packages produce different Foo messages then we will have trouble.
The reason to generate the prefixes is that we don't have a guaranteed unique namespace.
If two packages produce different Foo messages then we will have trouble.

## Why not strip the prefix?

When a message is added which happens to conflict with another message (e.g. by importing a message with the same name from a different package) it will break code that is very far away from the code that changed. This is in an effort to adhere to the [principle of least astonishment](https://en.wikipedia.org/wiki/Principle_of_least_astonishment).
When a message is added which happens to conflict with another message
(e.g. by importing a message with the same name from a different package)
it will break code that is very far away from the code that changed.
This is in an effort to adhere to the
[principle of least astonishment](https://en.wikipedia.org/wiki/Principle_of_least_astonishment).
20 changes: 11 additions & 9 deletions docs/_docs/grpcapiconfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ The following is equivalent to the basic [usage example](usage.html) but without

1. Define your service in gRPC as usual

your_service.proto:
```protobuf
your_service.proto:
```protobuf
syntax = "proto3";
package your.service.v1;
option go_package = "github.com/yourorg/yourprotos/gen/go/your/service/v1";
Expand All @@ -28,9 +28,10 @@ The following is equivalent to the basic [usage example](usage.html) but without
service YourService {
rpc Echo(StringMessage) returns (StringMessage) {}
}
```
```

2. Instead of annotating the .proto file in this step leave it untouched and create a `your_service.yaml` with the following content:
2. Instead of annotating the .proto file in this step leave it untouched
and create a `your_service.yaml` with the following content:
```yaml
type: google.api.Service
config_version: 3
Expand All @@ -53,12 +54,13 @@ The following is equivalent to the basic [usage example](usage.html) but without

4. Implement your service in gRPC as usual

5. Generate the reverse-proxy. Here we have to pass the path to the `your_service.yaml` in addition to the .proto file:
5. Generate the reverse-proxy. Here we have to pass the path to
the `your_service.yaml` in addition to the .proto file:

```sh
protoc -I. --grpc-gateway_out=logtostderr=true,paths=source_relative,grpc_api_configuration=path/to/your_service.yaml:./gen/go \
your/service/v1/your_service.proto
```
```sh
protoc -I. --grpc-gateway_out=logtostderr=true,paths=source_relative,grpc_api_configuration=path/to/your_service.yaml:./gen/go \
your/service/v1/your_service.proto
```

This will generate a reverse proxy `gen/go/your/service/v1/your_service.pb.gw.go` that is identical to the one produced for the annotated proto.

Expand Down
22 changes: 6 additions & 16 deletions docs/_docs/httpbody.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,35 @@
category: documentation
---

# HttpBody message Feature
# HttpBody messages
The [HTTP Body](https://github.com/googleapis/googleapis/blob/master/google/api/httpbody.proto) messages allows a response message to be specified with custom data content and a custom content type header. The values included in the HTTPBody response will be used verbatim in the returned message from the gateway. Make sure you format your response carefully!

## Example Usage
1. Create a mux and configure it to use the `HTTPBodyMarshaler`.
1. Define your service in gRPC with an httpbody response message

```golang
mux := runtime.NewServeMux()
runtime.SetHTTPBodyMarshaler(mux)
```
2. Define your service in gRPC with an httpbody response message

```golang
```protobuf
import "google/api/httpbody.proto";
import "google/api/annotations.proto";
import "google/protobuf/empty.proto";

service HttpBodyExampleService {

rpc HelloWorld(google.protobuf.Empty) returns (google.api.HttpBody) {
rpc HelloWorld(google.protobuf.Empty) returns (google.api.HttpBody) {
option (google.api.http) = {
get: "/helloworld"
};
}

rpc Download(google.protobuf.Empty) returns (stream google.api.HttpBody) {
option (google.api.http) = {
get: "/download"
};
}

}
```
3. Generate gRPC and reverse-proxy stubs and implement your service.

## Example service implementation

```golang
```go
func (*HttpBodyExampleService) Helloworld(ctx context.Context, in *empty.Empty) (*httpbody.HttpBody, error) {
return &httpbody.HttpBody{
ContentType: "text/html",
Expand All @@ -64,5 +55,4 @@ func (HttpBodyExampleService) Download(_ *empty.Empty, stream HttpBodyExampleSer

return nil
}

```
```
102 changes: 64 additions & 38 deletions docs/_docs/patch.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,60 +5,86 @@ category: documentation
# Patch Feature
The HTTP PATCH method allows a resource to be partially updated.

The idea, If a binding is mapped to patch and the request message has exactly one FieldMask message in it, additional code is rendered for the gateway handler that will populate the FieldMask based on the request body.
If a binding is mapped to patch and the request message has exactly one
FieldMask message in it, additional code is rendered for the gateway
handler that will populate the FieldMask based on the request body.

There are two scenarios:
- The FieldMask is hidden from the REST request as per the [Google API design guide](https://cloud.google.com/apis/design/standard_methods#update) (as in the first additional binding in the [UpdateV2](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/examples/internal/proto/examplepb/a_bit_of_everything.proto#L366) example). In this case, the FieldMask is updated from the request body and set in the gRPC request message.
- The FieldMask is exposed to the REST request (as in the second additional binding in the [UpdateV2](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/examples/internal/proto/examplepb/a_bit_of_everything.proto#L370) example). For this case, the field mask is left untouched by the gateway.
- The FieldMask is hidden from the REST request as per the
[Google API design guide](https://cloud.google.com/apis/design/standard_methods#update)
(as in the first additional binding in the
[UpdateV2](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/examples/internal/proto/examplepb/a_bit_of_everything.proto#L366)
example).
In this case, the FieldMask is updated from the request body and
set in the gRPC request message.
- The FieldMask is exposed to the REST request (as in the second
additional binding in the
[UpdateV2](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/examples/internal/proto/examplepb/a_bit_of_everything.proto#L370)
example).
For this case, the field mask is left untouched by the gateway.

## Example Usage
1. Create PATCH request.

The PATCH request needs to include the message and the update mask.
```golang
// UpdateV2Request request for update includes the message and the update mask
message UpdateV2Request {
ABitOfEverything abe = 1;
google.protobuf.FieldMask update_mask = 2;
}
```
The PATCH request needs to include the message and the update mask.
```protobuf
// UpdateV2Request request for update includes the message and the update mask
message UpdateV2Request {
ABitOfEverything abe = 1;
google.protobuf.FieldMask update_mask = 2;
}
```
2. Define your service in gRPC

If you want to use PATCH with fieldmask hidden from REST request only include the request message in the body.
If you want to use PATCH with fieldmask hidden from REST request only include the request message in the body.

```golang
rpc UpdateV2(UpdateV2Request) returns (google.protobuf.Empty) {
option (google.api.http) = {
put: "/v2/example/a_bit_of_everything/{abe.uuid}"
body: "abe"
additional_bindings {
patch: "/v2/example/a_bit_of_everything/{abe.uuid}"
```protobuf
rpc UpdateV2(UpdateV2Request) returns (google.protobuf.Empty) {
option (google.api.http) = {
put: "/v2/example/a_bit_of_everything/{abe.uuid}"
body: "abe"
}
};
}
```
additional_bindings {
patch: "/v2/example/a_bit_of_everything/{abe.uuid}"
body: "abe"
}
};
}
```

If you want to use PATCH with fieldmask exposed to the REST request then include the entire request message.
If you want to use PATCH with fieldmask exposed to the REST request then include the entire request message.

```golang
rpc UpdateV2(UpdateV2Request) returns (google.protobuf.Empty) {
option (google.api.http) = {
patch: "/v2a/example/a_bit_of_everything/{abe.uuid}"
body: "*"
};
}
```
```protobuf
rpc UpdateV2(UpdateV2Request) returns (google.protobuf.Empty) {
option (google.api.http) = {
patch: "/v2a/example/a_bit_of_everything/{abe.uuid}"
body: "*"
};
}
```

3. Generate gRPC and reverse-proxy stubs and implement your service.

## Curl examples

In the example below we will partially update our ABitOfEverything resource by passing only the field we want to change. Since we are using the endpoint with field mask hidden we only need to pass the field we want to change ("string_value") and it will keep everything else in our resource the same.
```
curl --data '{"string_value": "strprefix/foo"}' -X PATCH http://address:port/v2/example/a_bit_of_everything/1
In the example below we will partially update our ABitOfEverything
resource by passing only the field we want to change. Since we are
using the endpoint with field mask hidden we only need to pass the
field we want to change ("string_value") and it will keep everything
else in our resource the same.
```shell
$ curl \
--data '{"string_value": "strprefix/foo"}' \
-X PATCH \
http://address:port/v2/example/a_bit_of_everything/1
```

If we know what fields we want to update then we can use PATCH with field mask approach. For this we need to pass the resource and the update_mask. Below only the "single_nested" will get updated because that is what we specify in the field_mask.
```
curl --data '{"abe":{"single_nested":{"amount":457},"string_value":"some value that won't get updated because not in the field mask"},"update_mask":{"paths":["single_nested"]}}' -X PATCH http://address:port/v2a/example/a_bit_of_everything/1
If we know what fields we want to update then we can use PATCH with
field mask approach. For this we need to pass the resource and the
update_mask. Below only the "single_nested" will get updated because
that is what we specify in the field_mask.
```shell
$ curl \
--data '{"abe":{"single_nested":{"amount":457},"string_value":"some value that won't get updated because not in the field mask"},"update_mask":{"paths":["single_nested"]}}' \
-X PATCH \
http://address:port/v2a/example/a_bit_of_everything/1
```
1 change: 1 addition & 0 deletions docs/_docs/season_of_docs.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
category: documentation
name: 2020 Season of Docs
---

# 2020 Season of Docs
Expand Down
Loading