diff --git a/Makefile b/Makefile index a369b04..e3b6b94 100644 --- a/Makefile +++ b/Makefile @@ -93,6 +93,9 @@ plugin: example: plugin cd "$(ROOT_DIR)"/net/grpc/gateway/examples/echo && make +standalone-proxy: package + cd "$(ROOT_DIR)"/net/grpc/gateway/examples/echo && make standalone-proxy + echo_server: cd "$(ROOT_DIR)"/net/grpc/gateway/examples/echo && make echo_server diff --git a/README.md b/README.md index b55c324..f16a67d 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,13 @@ Try gRPC-Web and run a quick Echo example from the browser! From the repo root directory: ```sh -$ docker-compose up +$ docker-compose up echo-server envoy commonjs-client-example ``` Open a browser tab, and inspect ``` -http://localhost/net/grpc/gateway/examples/echo/echotest.html +http://localhost:8081/echo_commonjs_test.html ``` ## How it works @@ -99,3 +99,24 @@ stream.on('data', function(response) { console.log(response.getMessage()); }); ``` + +## Proxy interoperability + +Multiple proxies supports the gRPC-Web protocol. Currently, the default proxy +is [Envoy](https://www.envoyproxy.io). + +``` +$ docker-compose up echo-server envoy commonjs-client-example +``` + +An alternative is to build Nginx that comes with this repository. + +``` +$ docker-compose up echo-server nginx commonjs-client-example +``` + +Finally, you can also try this [gRPC-Web Go Proxy](https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy). + +``` +$ docker-compose up echo-server grpcwebproxy binary-client-example +``` diff --git a/docker-compose.yml b/docker-compose.yml index 9777c9e..7ca9dfc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,6 +23,24 @@ services: - "8080:8080" links: - echo-server + grpcwebproxy: + build: + context: ./ + dockerfile: ./net/grpc/gateway/docker/grpcwebproxy/Dockerfile + image: grpc-web:grpcwebproxy + ports: + - "8080:8080" + links: + - echo-server + nginx: + build: + context: ./ + dockerfile: ./net/grpc/gateway/docker/nginx/Dockerfile + image: grpc-web:nginx + ports: + - "8080:8080" + links: + - echo-server static-assets: build: context: ./ @@ -41,3 +59,12 @@ services: image: grpc-web:commonjs-client-example ports: - "8081:8081" + binary-client-example: + build: + context: ./ + dockerfile: ./net/grpc/gateway/docker/binary_client_example/Dockerfile + depends_on: + - prereqs + image: grpc-web:binary-client-example + ports: + - "8081:8081" diff --git a/etc/localhost.crt b/etc/localhost.crt new file mode 100644 index 0000000..33bc89a --- /dev/null +++ b/etc/localhost.crt @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC9jCCAd4CCQCfXxHXagE8mjANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQGEwJV +UzELMAkGA1UECAwCQ0ExITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0 +ZDAeFw0xODA4MDMyMTE2NDdaFw0yMTA1MjMyMTE2NDdaMD0xCzAJBgNVBAYTAlVT +MQswCQYDVQQIDAJDQTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2/MlKj+OtIgJm/7DywOR +POypfvGHXqHTpg/ZbZgflx2vMwgoAhdun2e//AlssouStadnkevPEr+uFfxkEzH3 +80iYDtcZKXY8E6692hFrp7hKnA7gcBbb7ZQ1FwG/SfKLtLcderLcQb51P7IsQkfh +nB8hSosV9nHhdfVtsMW7L/caqB5lUHIbRsHhSw3+hzg0r0HuKxXd5HlyRXzf9cQX +4xc5B8Ldxo3QmXDOUHDw9quuxvUn5VWppWCGn2J+f9L/5iwgciApbiMBv/CkiVrt +iYwZY+TZY5u8lmL4FtLd2tj2vNXl5ESWcL1SRGSiaYmxX1B5rg4fSAAXmcNOzZHo +8wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCHko8eFag++9knWV8KlRRi+IdGeatU +TejdBVnCPFc7sJf1lkUQSb0mZMv0QEO51aXGVvU46pIjTAwtzcVgPc6ZHqcZY4r3 +xscrmECThbhsEQCHqDD55OB2a06bx+ylfbBnLh+F18W+/rI+HlRxSBGclyfVto1P +aCuYvYc0qKK90Ft1joZh1tXpho/D52B4CTa0Ax/5UqSVjTt0uPDhkCZJKnoENVgh +6hF8ehYTC6Kf6ZtbB6+GuaLXf6F96CROLifW219qxrKmGbMyJXolOxLatufnWwwv +Hw7z1FUzulJUkSRmgPJ9hFeyTjCS1BJ18glFjleLykYOtQi8kvnpFm6C +-----END CERTIFICATE----- diff --git a/etc/localhost.key b/etc/localhost.key new file mode 100644 index 0000000..930ea29 --- /dev/null +++ b/etc/localhost.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA2/MlKj+OtIgJm/7DywORPOypfvGHXqHTpg/ZbZgflx2vMwgo +Ahdun2e//AlssouStadnkevPEr+uFfxkEzH380iYDtcZKXY8E6692hFrp7hKnA7g +cBbb7ZQ1FwG/SfKLtLcderLcQb51P7IsQkfhnB8hSosV9nHhdfVtsMW7L/caqB5l +UHIbRsHhSw3+hzg0r0HuKxXd5HlyRXzf9cQX4xc5B8Ldxo3QmXDOUHDw9quuxvUn +5VWppWCGn2J+f9L/5iwgciApbiMBv/CkiVrtiYwZY+TZY5u8lmL4FtLd2tj2vNXl +5ESWcL1SRGSiaYmxX1B5rg4fSAAXmcNOzZHo8wIDAQABAoIBAFPnJL5BEIb9fezr ++nRvH/BFt0KdkC4hPUOTuDV+Wk6jHDozWk+x8JkOUsYqMjTJ2WVCPtgDRDK6vAXX +CbXo0dUUVC0VEJwoZjJ77iBJlO+d9ZgidKtNjQfMCZSFLhtfUrvVPoGXyT2rEb8C +kK+YDBAqL+DnvbENMBx3SyirxQQ+YetAUSxiZagtjKlax1bhXF/JCj816ezDqOzR +ZVx4MJiJg3oD+zKlwP+IaFlANIuW2W7+LbNzPpdXER4gafRzyjRy5ksO9NFO11Bu +2srJbAMZEr0MCEBjf5rD7CPuvhTTEcgk6CNPsIEt8zzMSZUMeS0xaIv0W1FKiw+R +BENntsECgYEA84fSMRApKaweeBrthPKR1ucnv3EHxn1l1mz45bp+2euHB6jUul9D +629mMv8J9PVdcPF5ck7YpCjslWm6oOhtKMemuwJm61cRF44Lz7jtLm3zNJMGhpbh +6Q0GoIVcyMrW79BODbEIU5SlWp0Usyjo/4CZEP5adho1JNTDHCyvEVUCgYEA5zY6 +tbfu+YYgICBnaRkGgdCRBxMurxdPrgbwvrKSMerYE9fufpgvZc5wwx02rJX0psuo +JNGLAkPJyimZCYhY/hxWwXQX8X4BhkKK2aFyBMaDIBA0h+unOwTxHrebQNprot3h +YVT8+tfZf8bGPl+dBs3Qf+WOESjRSyO9jr5BMScCgYBfI4mPF1Qtbot8unBeRvGI +tkeF999kwOp/CZV3EhOqiOP4rxFkOgFrwdp4Q8CdDRpTHFMov/rMrxw2BtcdM5Ap +pU3Ss06H1DzeKeUdYo5uXA/uUx3yiJF7HVagcVldLDkp+QP1P1sUY/bxXnqOv4W/ +A3tI80Vd7EEkwWXz5NUD/QKBgGXhYXFdQTI2RcWiQa7v1gwxqRYi/7krXnLioAaH +jR/tyZTE21RxHsGPe+Sd5M+brBgrOUYwBz7SPAKW3dZzfDNMrXXFAB/rVCSjAafw +Gdu81V61hVA3KJM7FDxiz0h+dltnxb4rwuWNY0uIfSZS31B2NF+G+VjaUY74irhx +YSyVAoGANrn70s5+cJDWcmDhaFNU/J/X2Q8GgTyBRd02FIvuv7BXgd9TZ7bUVTws +1nsQCCEVJqj4ksddVRq33NvsnjrgetGYe1LGl3uLakqaXd7iJXFCice3ZuFFrp9o +Iq2sUgG+9K8WFqNhANRKBVd32IpQzjIMAAJSbuG3EFZDLZJqxDs= +-----END RSA PRIVATE KEY----- diff --git a/javascript/net/grpc/web/grpc_generator.cc b/javascript/net/grpc/web/grpc_generator.cc index 0a1283b..2742b1b 100644 --- a/javascript/net/grpc/web/grpc_generator.cc +++ b/javascript/net/grpc/web/grpc_generator.cc @@ -165,7 +165,7 @@ void PrintFileHeader(Printer* printer, const std::map& vars) { } void PrintServiceConstructor(Printer* printer, - const std::map& vars) { + std::map& vars) { printer->Print( vars, "/**\n" @@ -181,6 +181,14 @@ void PrintServiceConstructor(Printer* printer, " /**\n" " * @private @const {!grpc.web.$mode$ClientBase} The client\n" " */\n" + " if (!options) options = {};\n"); + if (vars["mode"] == GetModeVar(Mode::GRPCWEB)) { + printer->Print( + vars, + " options['format'] = '$format$';\n\n"); + } + printer->Print( + vars, " this.client_ = new grpc.web.$mode$ClientBase(options);\n\n" " /**\n" " * @private @const {string} The hostname\n" @@ -357,8 +365,9 @@ class GrpcCodeGenerator : public CodeGenerator { vars["mode"] = GetModeVar(Mode::OP); } else if (mode == "base64") { vars["mode"] = GetModeVar(Mode::GATEWAY); - } else if (mode == "grpcweb") { + } else if (mode == "grpcweb" || mode == "grpcwebtext") { vars["mode"] = GetModeVar(Mode::GRPCWEB); + vars["format"] = (mode == "grpcweb") ? "binary" : "text"; } else if (mode == "jspb") { vars["mode"] = GetModeVar(Mode::OPJSPB); } else if (mode == "frameworks") { diff --git a/javascript/net/grpc/web/grpcwebclientbase.js b/javascript/net/grpc/web/grpcwebclientbase.js index 2c5ea44..ea23a77 100644 --- a/javascript/net/grpc/web/grpcwebclientbase.js +++ b/javascript/net/grpc/web/grpcwebclientbase.js @@ -43,6 +43,13 @@ const googCrypt = goog.require('goog.crypt.base64'); * @implements {AbstractClientBase} */ const GrpcWebClientBase = function(opt_options) { + /** + * @const + * @private {string} + */ + this.format_ = + goog.getObjectByName('format', opt_options) || "text"; + /** * @const * @private {boolean} @@ -58,8 +65,6 @@ const GrpcWebClientBase = function(opt_options) { GrpcWebClientBase.prototype.rpcCall = function( method, request, metadata, methodInfo, callback) { var xhr = this.newXhr_(); - var serialized = methodInfo.requestSerializeFn(request); - xhr.headers.addAll(metadata); var genericTransportInterface = { xhr: xhr, @@ -89,18 +94,28 @@ GrpcWebClientBase.prototype.rpcCall = function( } }); - xhr.headers.set('Content-Type', 'application/grpc-web-text'); + xhr.headers.addAll(metadata); + if (this.format_ == "text") { + xhr.headers.set('Content-Type', 'application/grpc-web-text'); + xhr.headers.set('Accept', 'application/grpc-web-text'); + } else { + xhr.headers.set('Content-Type', 'application/grpc-web+proto'); + } xhr.headers.set('X-User-Agent', 'grpc-web-javascript/0.1'); - xhr.headers.set('Accept', 'application/grpc-web-text'); - - var payload = this.encodeRequest_(serialized); - payload = googCrypt.encodeByteArray(payload); - + xhr.headers.set('X-Grpc-Web', '1'); if (this.suppressCorsPreflight_) { var headerObject = xhr.headers.toObject(); xhr.headers.clear(); method = GrpcWebClientBase.setCorsOverride_(method, headerObject); } + + var serialized = methodInfo.requestSerializeFn(request); + var payload = this.encodeRequest_(serialized); + if (this.format_ == "text") { + payload = googCrypt.encodeByteArray(payload); + } else if (this.format_ == "binary") { + xhr.setResponseType(XhrIo.ResponseType.ARRAY_BUFFER); + } xhr.send(method, 'POST', payload); return; }; @@ -112,8 +127,6 @@ GrpcWebClientBase.prototype.rpcCall = function( GrpcWebClientBase.prototype.serverStreaming = function( method, request, metadata, methodInfo) { var xhr = this.newXhr_(); - var serialized = methodInfo.requestSerializeFn(request); - xhr.headers.addAll(metadata); var genericTransportInterface = { xhr: xhr, @@ -121,18 +134,28 @@ GrpcWebClientBase.prototype.serverStreaming = function( var stream = new GrpcWebClientReadableStream(genericTransportInterface); stream.setResponseDeserializeFn(methodInfo.responseDeserializeFn); - xhr.headers.set('Content-Type', 'application/grpc-web-text'); + xhr.headers.addAll(metadata); + if (this.format_ == "text") { + xhr.headers.set('Content-Type', 'application/grpc-web-text'); + xhr.headers.set('Accept', 'application/grpc-web-text'); + } else { + xhr.headers.set('Content-Type', 'application/grpc-web+proto'); + } xhr.headers.set('X-User-Agent', 'grpc-web-javascript/0.1'); - xhr.headers.set('Accept', 'application/grpc-web-text'); - - var payload = this.encodeRequest_(serialized); - payload = googCrypt.encodeByteArray(payload); - + xhr.headers.set('X-Grpc-Web', '1'); if (this.suppressCorsPreflight_) { var headerObject = xhr.headers.toObject(); xhr.headers.clear(); method = GrpcWebClientBase.setCorsOverride_(method, headerObject); } + + var serialized = methodInfo.requestSerializeFn(request); + var payload = this.encodeRequest_(serialized); + if (this.format_ == "text") { + payload = googCrypt.encodeByteArray(payload); + } else if (this.format_ == "binary") { + xhr.setResponseType(XhrIo.ResponseType.ARRAY_BUFFER); + } xhr.send(method, 'POST', payload); return stream; diff --git a/javascript/net/grpc/web/grpcwebclientreadablestream.js b/javascript/net/grpc/web/grpcwebclientreadablestream.js index 68d8c06..c9f981b 100644 --- a/javascript/net/grpc/web/grpcwebclientreadablestream.js +++ b/javascript/net/grpc/web/grpcwebclientreadablestream.js @@ -40,6 +40,7 @@ const XhrIo = goog.require('goog.net.XhrIo'); const XmlHttp = goog.require('goog.net.XmlHttp'); const events = goog.require('goog.events'); const googCrypt = goog.require('goog.crypt.base64'); +const googString = goog.require('goog.string'); const {GenericTransportInterface} = goog.require('grpc.web.GenericTransportInterface'); const {Status} = goog.require('grpc.web.Status'); @@ -114,18 +115,26 @@ const GrpcWebClientReadableStream = function(genericTransportInterface) { var self = this; events.listen(this.xhr_, EventType.READY_STATE_CHANGE, function(e) { - var FrameType = GrpcWebStreamParser.FrameType; + var contentType = self.xhr_.getStreamingResponseHeader('Content-Type'); + if (!contentType) return; + contentType = contentType.toLowerCase(); - var responseText = self.xhr_.getResponseText(); - var newPos = responseText.length - responseText.length % 4; - var newData = responseText.substr(self.pos_, newPos - self.pos_); - if (newData.length == 0) return; - self.pos_ = newPos; - - var byteSource = googCrypt.decodeStringToUint8Array(newData); + if (googString.startsWith(contentType, 'application/grpc-web-text')) { + var responseText = self.xhr_.getResponseText(); + var newPos = responseText.length - responseText.length % 4; + var newData = responseText.substr(self.pos_, newPos - self.pos_); + if (newData.length == 0) return; + self.pos_ = newPos; + var byteSource = googCrypt.decodeStringToUint8Array(newData); + } else if (googString.startsWith(contentType, 'application/grpc')) { + var byteSource = new Uint8Array(self.xhr_.getResponse()); + } else { + return; + } var messages = self.parser_.parse([].slice.call(byteSource)); if (!messages) return; + var FrameType = GrpcWebStreamParser.FrameType; for (var i = 0; i < messages.length; i++) { if (FrameType.DATA in messages[i]) { var data = messages[i][FrameType.DATA]; diff --git a/net/grpc/gateway/docker/binary_client_example/Dockerfile b/net/grpc/gateway/docker/binary_client_example/Dockerfile new file mode 100644 index 0000000..d262224 --- /dev/null +++ b/net/grpc/gateway/docker/binary_client_example/Dockerfile @@ -0,0 +1,40 @@ +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM grpc-web:prereqs + +ARG EXAMPLE_DIR=/github/grpc-web/net/grpc/gateway/examples/echo + +RUN cd /github/grpc-web/packages/grpc-web && \ + rm -rf node_modules && \ + npm install && \ + npm run build && \ + npm link + +RUN protoc -I=$EXAMPLE_DIR echo.proto \ +--plugin=protoc-gen-grpc-web=\ +/github/grpc-web/javascript/net/grpc/web/protoc-gen-grpc-web \ +--js_out=import_style=commonjs:\ +$EXAMPLE_DIR/commonjs-example \ +--grpc-web_out=import_style=commonjs,mode=grpcweb,out=echo_grpc_pb.js:\ +$EXAMPLE_DIR/commonjs-example + +RUN cd $EXAMPLE_DIR/commonjs-example && \ + rm -rf node_modules && \ + npm install && \ + npm link grpc-web && \ + ./node_modules/.bin/browserify client.js > out.js + +EXPOSE 8081 +CMD ["nginx"] diff --git a/net/grpc/gateway/docker/commonjs_client_example/Dockerfile b/net/grpc/gateway/docker/commonjs_client_example/Dockerfile index b54ebba..e998524 100644 --- a/net/grpc/gateway/docker/commonjs_client_example/Dockerfile +++ b/net/grpc/gateway/docker/commonjs_client_example/Dockerfile @@ -16,17 +16,24 @@ FROM grpc-web:prereqs ARG EXAMPLE_DIR=/github/grpc-web/net/grpc/gateway/examples/echo +RUN cd /github/grpc-web/packages/grpc-web && \ + rm -rf node_modules && \ + npm install && \ + npm run build && \ + npm link + RUN protoc -I=$EXAMPLE_DIR echo.proto \ --plugin=protoc-gen-grpc-web=\ /github/grpc-web/javascript/net/grpc/web/protoc-gen-grpc-web \ --js_out=import_style=commonjs:\ $EXAMPLE_DIR/commonjs-example \ ---grpc-web_out=import_style=commonjs,mode=grpcweb,out=echo_grpc_pb.js:\ +--grpc-web_out=import_style=commonjs,mode=grpcwebtext,out=echo_grpc_pb.js:\ $EXAMPLE_DIR/commonjs-example RUN cd $EXAMPLE_DIR/commonjs-example && \ rm -rf node_modules && \ npm install && \ + npm link grpc-web && \ ./node_modules/.bin/browserify client.js > out.js EXPOSE 8081 diff --git a/net/grpc/gateway/docker/grpcwebproxy/Dockerfile b/net/grpc/gateway/docker/grpcwebproxy/Dockerfile new file mode 100644 index 0000000..3893d62 --- /dev/null +++ b/net/grpc/gateway/docker/grpcwebproxy/Dockerfile @@ -0,0 +1,20 @@ +FROM golang:alpine + +RUN apk add --no-cache git ca-certificates && \ + rm -rf /var/lib/apt/lists/* + +RUN go get -v -u github.com/golang/dep/cmd/dep +RUN go get -v github.com/improbable-eng/grpc-web/go/grpcwebproxy ; exit 0 +RUN cd src/github.com/improbable-eng/grpc-web && dep ensure +RUN go get -v -u github.com/improbable-eng/grpc-web/go/grpcwebproxy + +ADD ./etc/localhost.crt /etc +ADD ./etc/localhost.key /etc + +ENTRYPOINT [ "/bin/sh", "-c", "exec /go/bin/grpcwebproxy \ + --backend_addr=echo-server:9090 \ + --server_bind_address=0.0.0.0 \ + --server_http_debug_port=8080 \ + --run_http_server=true \ + --server_tls_cert_file=/etc/localhost.crt \ + --server_tls_key_file=/etc/localhost.key " ] diff --git a/net/grpc/gateway/docker/nginx/Dockerfile b/net/grpc/gateway/docker/nginx/Dockerfile new file mode 100644 index 0000000..be8e6da --- /dev/null +++ b/net/grpc/gateway/docker/nginx/Dockerfile @@ -0,0 +1,21 @@ +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM grpc-web:prereqs + +RUN cd /github/grpc-web && \ + make standalone-proxy + +EXPOSE 8080 +CMD ["/github/grpc-web/gConnector/nginx.sh"] diff --git a/net/grpc/gateway/docker/prereqs/Dockerfile b/net/grpc/gateway/docker/prereqs/Dockerfile index 0456eee..7188adb 100644 --- a/net/grpc/gateway/docker/prereqs/Dockerfile +++ b/net/grpc/gateway/docker/prereqs/Dockerfile @@ -25,6 +25,7 @@ RUN apt-get update && apt-get install -y \ default-jdk \ default-jre \ libtool \ + libpcre3-dev \ libssl-dev \ make \ nginx \ @@ -33,9 +34,11 @@ RUN apt-get update && apt-get install -y \ RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - && \ apt-get install -y nodejs -RUN git clone https://github.com/grpc/grpc-web /github/grpc-web +COPY . /github/grpc-web RUN cd /github/grpc-web && \ + rm -rf third_party && \ + git checkout third_party && \ ./scripts/init_submodules.sh RUN cd /github/grpc-web/third_party/grpc && \ diff --git a/net/grpc/gateway/examples/echo/Makefile b/net/grpc/gateway/examples/echo/Makefile index 335873c..c6b1d12 100644 --- a/net/grpc/gateway/examples/echo/Makefile +++ b/net/grpc/gateway/examples/echo/Makefile @@ -41,6 +41,11 @@ package: cp run_example.sh $(ROOT_DIR)/gConnector zip -r $(ROOT_DIR)/gConnector.zip $(ROOT_DIR)/gConnector/* +standalone-proxy: + mkdir -p $(ROOT_DIR)/gConnector/$(EXAMPLES_PATH) + cp nginx.conf $(ROOT_DIR)/gConnector/conf + zip -r $(ROOT_DIR)/gConnector.zip $(ROOT_DIR)/gConnector/* + echo_server: echo.pb.o echo.grpc.pb.o echo_server.o echo_service_impl.o $(CXX) $^ $(LDFLAGS) -o $@ @@ -86,7 +91,7 @@ proto-js: $(PROTOS_PATH)/protos/pair.proto $(PROTOC) -I=. --js_out=$(JS_IMPORT_STYLE):$(OUT_DIR) ./echo.proto $(PROTOC) -I=. --plugin=protoc-gen-grpc-web=$(GRPC_WEB_PLUGIN_PATH) \ - --grpc-web_out=out=$(OUT_DIR)/echo.grpc.pb.js,mode=grpcweb:. ./echo.proto + --grpc-web_out=out=$(OUT_DIR)/echo.grpc.pb.js,mode=grpcwebtext:. ./echo.proto install: mkdir -p $(HTML_DIR)/$(EXAMPLES_PATH) diff --git a/net/grpc/gateway/examples/echo/nginx.conf b/net/grpc/gateway/examples/echo/nginx.conf index 25efefc..a1ab72a 100644 --- a/net/grpc/gateway/examples/echo/nginx.conf +++ b/net/grpc/gateway/examples/echo/nginx.conf @@ -21,11 +21,11 @@ http { root /var/www/html; } location / { - grpc_pass localhost:9090; + grpc_pass echo-server:9090; if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Transfer-Encoding,Custom-Header-1,X-Accept-Content-Transfer-Encoding,X-Accept-Response-Streaming,X-User-Agent'; + add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Transfer-Encoding,Custom-Header-1,X-Accept-Content-Transfer-Encoding,X-Accept-Response-Streaming,X-User-Agent,X-Grpc-Web'; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; @@ -34,7 +34,7 @@ http { if ($request_method = 'POST') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; - add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Transfer-Encoding,Custom-Header-1,X-Accept-Content-Transfer-Encoding,X-Accept-Response-Streaming,X-User-Agent'; + add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Transfer-Encoding,Custom-Header-1,X-Accept-Content-Transfer-Encoding,X-Accept-Response-Streaming,X-User-Agent,X-Grpc-Web'; add_header 'Access-Control-Expose-Headers' 'Content-Transfer-Encoding'; } } diff --git a/net/grpc/gateway/examples/echo/tutorial.md b/net/grpc/gateway/examples/echo/tutorial.md index 7b426fc..8c7500a 100644 --- a/net/grpc/gateway/examples/echo/tutorial.md +++ b/net/grpc/gateway/examples/echo/tutorial.md @@ -99,13 +99,13 @@ To generate the client stub JS file, now run this command: ```sh $ protoc -I=. --plugin=protoc-gen-grpc-web= \ - --grpc-web_out=out=echo.grpc.pb.js,mode=grpcweb:. ./echo.proto + --grpc-web_out=out=echo.grpc.pb.js,mode=grpcwebtext:. ./echo.proto ``` The format for the `--grpc-web_out` param is ```sh ---grpc-web_out=out=,mode=grpcweb: +--grpc-web_out=out=,mode=grpcwebtext: ``` Our command generates the client stub in the file `echo.grpc.pb.js`. diff --git a/packages/grpc-web/README.md b/packages/grpc-web/README.md index ee13806..dbf2d4d 100644 --- a/packages/grpc-web/README.md +++ b/packages/grpc-web/README.md @@ -38,7 +38,7 @@ This example is using the `echo.proto` file from the [Echo Example](https://gith 2. Generate your client with `protoc` and the `protoc-gen-grpc-web` plugin. Make sure you set the import_style for both `js_out` and `grpc-web_out` to **commonjs**. It is also important that both your js and grpc-web output to the same directory. ```shell - protoc echo.proto --js_out=import_style=commonjs:generated --grpc-web_out=import_style=commonjs,mode=grpcweb,out=echo_grpc_pb.js:generated + protoc echo.proto --js_out=import_style=commonjs:generated --grpc-web_out=import_style=commonjs,mode=grpcwebtext,out=echo_grpc_pb.js:generated ``` 3. Start using your generated client!