From 8084f4ea26cccf9bd2d96d2a81eaea490aaf603b Mon Sep 17 00:00:00 2001 From: Juan Alvarez Date: Thu, 3 Jun 2021 11:48:53 -0500 Subject: [PATCH] chore(tonic-web): include crate in top-level workspace (#648) This PR adds the tonic-web crate to tonic's workspace members. Unit and integration tests should now run as part of CI runs. --- Cargo.toml | 2 + tonic-web/.gitignore | 6 - tonic-web/Cargo.toml | 27 ++- tonic-web/interop/.dockerignore | 2 - tonic-web/interop/Cargo.toml | 13 -- tonic-web/interop/Dockerfile | 28 --- tonic-web/interop/README.md | 27 --- tonic-web/interop/client/interop_client.js | 204 ------------------ tonic-web/interop/client/package.json | 19 -- tonic-web/interop/client/test.proto | 68 ------ tonic-web/interop/client/test.sh | 8 - tonic-web/interop/src/main.rs | 17 -- tonic-web/{tonic-web => }/src/call.rs | 0 tonic-web/{tonic-web => }/src/config.rs | 0 tonic-web/{tonic-web => }/src/cors.rs | 0 tonic-web/{tonic-web => }/src/lib.rs | 0 tonic-web/{tonic-web => }/src/service.rs | 4 +- tonic-web/tests/integration/Cargo.toml | 4 +- tonic-web/tests/integration/src/lib.rs | 2 +- tonic-web/tests/integration/tests/grpc_web.rs | 1 - tonic-web/tonic-web/Cargo.toml | 21 -- 21 files changed, 28 insertions(+), 425 deletions(-) delete mode 100644 tonic-web/.gitignore delete mode 100644 tonic-web/interop/.dockerignore delete mode 100644 tonic-web/interop/Cargo.toml delete mode 100644 tonic-web/interop/Dockerfile delete mode 100644 tonic-web/interop/README.md delete mode 100644 tonic-web/interop/client/interop_client.js delete mode 100644 tonic-web/interop/client/package.json delete mode 100644 tonic-web/interop/client/test.proto delete mode 100755 tonic-web/interop/client/test.sh delete mode 100644 tonic-web/interop/src/main.rs rename tonic-web/{tonic-web => }/src/call.rs (100%) rename tonic-web/{tonic-web => }/src/config.rs (100%) rename tonic-web/{tonic-web => }/src/cors.rs (100%) rename tonic-web/{tonic-web => }/src/lib.rs (100%) rename tonic-web/{tonic-web => }/src/service.rs (99%) delete mode 100644 tonic-web/tonic-web/Cargo.toml diff --git a/Cargo.toml b/Cargo.toml index 3d1cbb1..05b7f6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "tonic-health", "tonic-types", "tonic-reflection", + "tonic-web", # Non-published crates "examples", @@ -21,5 +22,6 @@ members = [ "tests/integration_tests", "tests/stream_conflict", "tests/root-crate-path", + "tonic-web/tests/integration" ] diff --git a/tonic-web/.gitignore b/tonic-web/.gitignore deleted file mode 100644 index 79d35a0..0000000 --- a/tonic-web/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules -/target -binary -text -run.sh -package-lock.json \ No newline at end of file diff --git a/tonic-web/Cargo.toml b/tonic-web/Cargo.toml index 33fe463..e912c97 100644 --- a/tonic-web/Cargo.toml +++ b/tonic-web/Cargo.toml @@ -1,6 +1,21 @@ -[workspace] -members = [ - "tonic-web", - "interop", - "tests/integration" -] \ No newline at end of file +[package] +name = "tonic-web" +version = "0.1.0" +authors = ["Juan Alvarez "] +edition = "2018" + +[dependencies] +tonic = { path = "../tonic", default-features = false, features = ["transport"] } +http = "0.2" +base64 = "0.13" +futures-core = "0.3" +bytes = "1.0" +hyper = "0.14" +http-body = "0.4" +tower-service = "0.3" +tracing = "0.1" +pin-project = "1" + +[dev-dependencies] +tokio = { version = "1", features = ["macros", "rt"] } +tonic = { path = "../tonic", default-features = false, features = ["transport", "tls"] } diff --git a/tonic-web/interop/.dockerignore b/tonic-web/interop/.dockerignore deleted file mode 100644 index e62ad6c..0000000 --- a/tonic-web/interop/.dockerignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!client/* \ No newline at end of file diff --git a/tonic-web/interop/Cargo.toml b/tonic-web/interop/Cargo.toml deleted file mode 100644 index 746b97c..0000000 --- a/tonic-web/interop/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "web-interop" -version = "0.1.0" -authors = ["Juan Alvarez "] -publish = false -edition = "2018" - -[dependencies] -interop = { path = "../../interop" } -tonic = { path = "../../tonic" } -tonic-web = { path = "../tonic-web" } -tokio = { version = "1.0.1", features = ["rt-multi-thread", "macros"] } - diff --git a/tonic-web/interop/Dockerfile b/tonic-web/interop/Dockerfile deleted file mode 100644 index 640bf44..0000000 --- a/tonic-web/interop/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM node:12-stretch - -RUN apt-get install -y unzip - -WORKDIR /tmp - -RUN curl -sSL https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/\ -protoc-3.14.0-linux-x86_64.zip -o protoc.zip && \ - unzip -qq protoc.zip && \ - cp ./bin/protoc /usr/local/bin/protoc - -RUN curl -sSL https://github.com/grpc/grpc-web/releases/download/1.2.1/\ -protoc-gen-grpc-web-1.2.1-linux-x86_64 -o /usr/local/bin/protoc-gen-grpc-web && \ - chmod +x /usr/local/bin/protoc-gen-grpc-web - -WORKDIR / - -COPY ./client ./ - -RUN echo "\nloglevel=error\n" >> $HOME/.npmrc && npm install && mkdir -p binary text - -RUN protoc -I=. ./test.proto\ - --js_out=import_style=commonjs:./text\ - --grpc-web_out=import_style=commonjs,mode=grpcwebtext:./text - -RUN protoc -I=. ./test.proto\ - --js_out=import_style=commonjs:./binary\ - --grpc-web_out=import_style=commonjs,mode=grpcweb:./binary diff --git a/tonic-web/interop/README.md b/tonic-web/interop/README.md deleted file mode 100644 index a225af4..0000000 --- a/tonic-web/interop/README.md +++ /dev/null @@ -1,27 +0,0 @@ -## Running interop tests - -Start the server: - -```bash -cd tonic-web/interop -cargo run -``` - -Build the client docker image: - -```bash - cd tonic-web/interop - docker build -t grpcweb-client . -``` - -Run tests on linux: - -```bash -docker run --network=host --rm grpcweb-client /test.sh -``` - -Run tests on docker desktop: - -```bash -docker run --rm grpcweb-client /test.sh host.docker.internal -``` diff --git a/tonic-web/interop/client/interop_client.js b/tonic-web/interop/client/interop_client.js deleted file mode 100644 index c41bcc1..0000000 --- a/tonic-web/interop/client/interop_client.js +++ /dev/null @@ -1,204 +0,0 @@ -/** - * - * 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. - * - */ - -// Adapted from https://github.com/grpc/grpc-web/tree/master/test/interop - -global.XMLHttpRequest = require("xhr2"); - -const parseArgs = require('minimist'); -const argv = parseArgs(process.argv, { - string: ['mode', 'host'] -}); - -const SERVER_HOST = `http://${argv.host || "localhost"}:9999`; - -if (argv.mode === 'binary') { - console.log('Testing tonic-web mode (binary)...'); -} else { - console.log('Testing tonic-web mode (text)...'); -} -console.log('Tonic server:', SERVER_HOST); - -const PROTO_PATH = argv.mode === 'binary' ? './binary' : './text'; - -const { - Empty, - SimpleRequest, - StreamingOutputCallRequest, - EchoStatus, - Payload, - ResponseParameters -} = require(`${PROTO_PATH}/test_pb.js`); - -const {TestServiceClient} = require(`${PROTO_PATH}/test_grpc_web_pb.js`); - -const assert = require('assert'); -const grpc = {}; -grpc.web = require('grpc-web'); - -function multiDone(done, count) { - return function () { - count -= 1; - if (count <= 0) { - done(); - } - }; -} - -function doEmptyUnary(done) { - const testService = new TestServiceClient(SERVER_HOST, null, null); - testService.emptyCall(new Empty(), null, (err, response) => { - assert.ifError(err); - assert(response instanceof Empty); - done(); - }); -} - -function doLargeUnary(done) { - const testService = new TestServiceClient(SERVER_HOST, null, null); - const req = new SimpleRequest(); - const size = 314159; - - const payload = new Payload(); - payload.setBody('0'.repeat(271828)); - - req.setPayload(payload); - req.setResponseSize(size); - - testService.unaryCall(req, null, (err, response) => { - assert.ifError(err); - assert.equal(response.getPayload().getBody().length, size); - done(); - }); -} - -function doServerStreaming(done) { - const testService = new TestServiceClient(SERVER_HOST, null, null); - const sizes = [31415, 9, 2653, 58979]; - - const responseParams = sizes.map((size, idx) => { - const param = new ResponseParameters(); - param.setSize(size); - param.setIntervalUs(idx * 10); - return param; - }); - - const req = new StreamingOutputCallRequest(); - req.setResponseParametersList(responseParams); - - const stream = testService.streamingOutputCall(req); - - done = multiDone(done, sizes.length); - let numCallbacks = 0; - stream.on('data', (response) => { - assert.equal(response.getPayload().getBody().length, sizes[numCallbacks]); - numCallbacks++; - done(); - }); -} - -function doCustomMetadata(done) { - const testService = new TestServiceClient(SERVER_HOST, null, null); - done = multiDone(done, 3); - - const req = new SimpleRequest(); - const size = 314159; - const ECHO_INITIAL_KEY = 'x-grpc-test-echo-initial'; - const ECHO_INITIAL_VALUE = 'test_initial_metadata_value'; - const ECHO_TRAILING_KEY = 'x-grpc-test-echo-trailing-bin'; - const ECHO_TRAILING_VALUE = 0xababab; - - const payload = new Payload(); - payload.setBody('0'.repeat(271828)); - - req.setPayload(payload); - req.setResponseSize(size); - - const call = testService.unaryCall(req, { - [ECHO_INITIAL_KEY]: ECHO_INITIAL_VALUE, - [ECHO_TRAILING_KEY]: ECHO_TRAILING_VALUE - }, (err, response) => { - assert.ifError(err); - assert.equal(response.getPayload().getBody().length, size); - done(); - }); - - call.on('metadata', (metadata) => { - assert(ECHO_INITIAL_KEY in metadata); - assert.equal(metadata[ECHO_INITIAL_KEY], ECHO_INITIAL_VALUE); - done(); - }); - - call.on('status', (status) => { - assert('metadata' in status); - assert(ECHO_TRAILING_KEY in status.metadata); - assert.equal(status.metadata[ECHO_TRAILING_KEY], ECHO_TRAILING_VALUE); - done(); - }); -} - -function doStatusCodeAndMessage(done) { - const testService = new TestServiceClient(SERVER_HOST, null, null); - const req = new SimpleRequest(); - - const TEST_STATUS_MESSAGE = 'test status message'; - const echoStatus = new EchoStatus(); - echoStatus.setCode(2); - echoStatus.setMessage(TEST_STATUS_MESSAGE); - - req.setResponseStatus(echoStatus); - - testService.unaryCall(req, {}, (err, response) => { - assert(err); - assert('code' in err); - assert('message' in err); - assert.equal(err.code, 2); - assert.equal(err.message, TEST_STATUS_MESSAGE); - done(); - }); -} - -function doUnimplementedMethod(done) { - const testService = new TestServiceClient(SERVER_HOST, null, null); - testService.unimplementedCall(new Empty(), {}, (err, response) => { - assert(err); - assert('code' in err); - assert.equal(err.code, 12); - done(); - }); -} - -const testCases = { - 'empty_unary': {testFunc: doEmptyUnary}, - 'large_unary': {testFunc: doLargeUnary}, - 'server_streaming': { - testFunc: doServerStreaming, - skipBinaryMode: true - }, - 'custom_metadata': {testFunc: doCustomMetadata}, - 'status_code_and_message': {testFunc: doStatusCodeAndMessage}, - 'unimplemented_method': {testFunc: doUnimplementedMethod} -}; - - -describe('tonic-web interop tests', function () { - Object.keys(testCases).forEach((testCase) => { - if (argv.mode === 'binary' && testCases[testCase].skipBinaryMode) return; - it('should pass ' + testCase, testCases[testCase].testFunc); - }); -}); diff --git a/tonic-web/interop/client/package.json b/tonic-web/interop/client/package.json deleted file mode 100644 index 515a15d..0000000 --- a/tonic-web/interop/client/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "grpc-web-interop-test", - "version": "0.1.0", - "description": "gRPC-Web Interop Test Client", - "license": "Apache-2.0", - "private": true, - "scripts": { - "test": "mocha -b --timeout 500 ./interop_client.js" - }, - "dependencies": { - "google-protobuf": "~3.14.0", - "grpc-web": "~1.2.1" - }, - "devDependencies": { - "minimist": "~1.2.5", - "mocha": "~7.1.1", - "xhr2": "~0.2.0" - } -} diff --git a/tonic-web/interop/client/test.proto b/tonic-web/interop/client/test.proto deleted file mode 100644 index 7df6a85..0000000 --- a/tonic-web/interop/client/test.proto +++ /dev/null @@ -1,68 +0,0 @@ - -// Copyright 2015-2016 gRPC authors. -// -// 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 -// -// http://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. - -// Adapted from https://github.com/grpc/grpc-web/tree/master/src/proto/grpc/testing - -syntax = "proto3"; - -package grpc.testing; - -service TestService { - rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty); - rpc UnaryCall(SimpleRequest) returns (SimpleResponse); - rpc StreamingOutputCall(StreamingOutputCallRequest) - returns (stream StreamingOutputCallResponse); - rpc UnimplementedCall(grpc.testing.Empty) returns (grpc.testing.Empty); -} - -message Empty {} - -message BoolValue { - bool value = 1; -} - -message Payload { - bytes body = 2; -} - -message EchoStatus { - int32 code = 1; - string message = 2; -} - -message SimpleRequest { - int32 response_size = 2; - Payload payload = 3; - EchoStatus response_status = 7; -} - -message SimpleResponse { - Payload payload = 1; -} - -message ResponseParameters { - int32 size = 1; - int32 interval_us = 2; -} - -message StreamingOutputCallRequest { - repeated ResponseParameters response_parameters = 2; - Payload payload = 3; - EchoStatus response_status = 7; -} - -message StreamingOutputCallResponse { - Payload payload = 1; -} diff --git a/tonic-web/interop/client/test.sh b/tonic-web/interop/client/test.sh deleted file mode 100755 index 72e7cae..0000000 --- a/tonic-web/interop/client/test.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -set -e - -HOST=${1:-"localhost"} - -npm test -- --host="$HOST" -npm test -- --mode=binary --host="$HOST" \ No newline at end of file diff --git a/tonic-web/interop/src/main.rs b/tonic-web/interop/src/main.rs deleted file mode 100644 index de5279c..0000000 --- a/tonic-web/interop/src/main.rs +++ /dev/null @@ -1,17 +0,0 @@ -use interop::server::{EchoHeadersSvc, TestService, TestServiceServer}; -use tonic::transport::Server; - -#[tokio::main] -async fn main() -> Result<(), Box> { - let addr = ([127, 0, 0, 1], 9999).into(); - let test_svc = TestServiceServer::new(TestService::default()); - let with_echo = EchoHeadersSvc::new(test_svc); - - Server::builder() - .accept_http1(true) - .add_service(tonic_web::enable(with_echo)) - .serve(addr) - .await?; - - Ok(()) -} diff --git a/tonic-web/tonic-web/src/call.rs b/tonic-web/src/call.rs similarity index 100% rename from tonic-web/tonic-web/src/call.rs rename to tonic-web/src/call.rs diff --git a/tonic-web/tonic-web/src/config.rs b/tonic-web/src/config.rs similarity index 100% rename from tonic-web/tonic-web/src/config.rs rename to tonic-web/src/config.rs diff --git a/tonic-web/tonic-web/src/cors.rs b/tonic-web/src/cors.rs similarity index 100% rename from tonic-web/tonic-web/src/cors.rs rename to tonic-web/src/cors.rs diff --git a/tonic-web/tonic-web/src/lib.rs b/tonic-web/src/lib.rs similarity index 100% rename from tonic-web/tonic-web/src/lib.rs rename to tonic-web/src/lib.rs diff --git a/tonic-web/tonic-web/src/service.rs b/tonic-web/src/service.rs similarity index 99% rename from tonic-web/tonic-web/src/service.rs rename to tonic-web/src/service.rs index 4b87bae..296a355 100644 --- a/tonic-web/tonic-web/src/service.rs +++ b/tonic-web/src/service.rs @@ -2,7 +2,7 @@ use std::task::{Context, Poll}; use http::{header, HeaderMap, HeaderValue, Method, Request, Response, StatusCode, Version}; use hyper::Body; -use tonic::body::{BoxBody, empty_body}; +use tonic::body::{empty_body, BoxBody}; use tonic::transport::NamedService; use tower_service::Service; use tracing::{debug, trace}; @@ -255,7 +255,7 @@ mod tests { } fn call(&mut self, _: Request) -> Self::Future { - Box::pin(async { Ok(Response::new(BoxBody::empty())) }) + Box::pin(async { Ok(Response::new(empty_body())) }) } } diff --git a/tonic-web/tests/integration/Cargo.toml b/tonic-web/tests/integration/Cargo.toml index dd6348f..165ac86 100644 --- a/tonic-web/tests/integration/Cargo.toml +++ b/tonic-web/tests/integration/Cargo.toml @@ -7,9 +7,9 @@ edition = "2018" [dependencies] tonic = { path = "../../../tonic" } -tonic-web = { path = "../../tonic-web" } +tonic-web = { path = "../../../tonic-web" } prost = "0.7" -tokio = { version = "1.0.1", features = ["macros", "rt", "net"] } +tokio = { version = "1", features = ["macros", "rt", "net"] } base64 = "0.13" bytes = "1.0" tokio-stream = { version = "0.1", features = ["net"] } diff --git a/tonic-web/tests/integration/src/lib.rs b/tonic-web/tests/integration/src/lib.rs index a712dc1..b4cad9a 100644 --- a/tonic-web/tests/integration/src/lib.rs +++ b/tonic-web/tests/integration/src/lib.rs @@ -1,6 +1,6 @@ use std::pin::Pin; -use tokio_stream::{self as stream, StreamExt, Stream}; +use tokio_stream::{self as stream, Stream, StreamExt}; use tonic::{Request, Response, Status, Streaming}; use pb::{test_server::Test, Input, Output}; diff --git a/tonic-web/tests/integration/tests/grpc_web.rs b/tonic-web/tests/integration/tests/grpc_web.rs index a833ef4..61b6866 100644 --- a/tonic-web/tests/integration/tests/grpc_web.rs +++ b/tonic-web/tests/integration/tests/grpc_web.rs @@ -68,7 +68,6 @@ async fn origin_not_allowed() { assert_eq!(res.status(), StatusCode::FORBIDDEN); } - async fn spawn(allowed_origin: &str) -> String { let addr = SocketAddr::from(([127, 0, 0, 1], 0)); let listener = TcpListener::bind(addr).await.expect("listener"); diff --git a/tonic-web/tonic-web/Cargo.toml b/tonic-web/tonic-web/Cargo.toml deleted file mode 100644 index 72b7eff..0000000 --- a/tonic-web/tonic-web/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "tonic-web" -version = "0.1.0" -authors = ["Juan Alvarez "] -edition = "2018" - -[dependencies] -tonic = { path = "../../tonic", default-features = false, features = ["transport"] } -http = "0.2" -base64 = "0.13" -futures-core = "0.3" -bytes = "1.0" -hyper = "0.14" -http-body = "0.4" -tower-service = "0.3" -tracing = "0.1" -pin-project = "1" - -[dev-dependencies] -tokio = { version = "1.0.1", features = ["macros", "rt"] } -tonic = { path = "../../tonic", default-features = false, features = ["transport", "tls"] }