Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: envoyproxy/envoy-mobile
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 204eb8f485a5a53612bff62e2181a97b96498976
Choose a base ref
..
head repository: envoyproxy/envoy-mobile
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0663784b4aed92d0af1037109802bd0178463a4e
Choose a head ref
Showing with 2,127 additions and 2,384 deletions.
  1. +8 −8 .github/workflows/android.yml
  2. +3 −3 .github/workflows/core.yml
  3. +2 −2 .github/workflows/ios.yml
  4. +2 −1 WORKSPACE
  5. +1 −0 bazel/aar_with_jni.bzl
  6. +126 −64 docs/root/api/grpc.rst
  7. +162 −99 docs/root/api/http.rst
  8. +15 −18 docs/root/api/starting_envoy.rst
  9. +25 −0 docs/root/start/building/building.rst
  10. +26 −0 envoy_build_config/BUILD
  11. +1 −1 library/common/extensions/registry.cc → envoy_build_config/extension_registry.cc
  12. 0 library/common/extensions/registry.h → envoy_build_config/extension_registry.h
  13. +33 −47 examples/java/hello_world/MainActivity.java
  14. +26 −35 examples/kotlin/hello_world/MainActivity.kt
  15. +1 −2 examples/objective-c/hello_world/Result.h
  16. +21 −27 examples/objective-c/hello_world/ViewController.m
  17. +1 −3 examples/swift/hello_world/ResponseModels.swift
  18. +38 −19 examples/swift/hello_world/ViewController.swift
  19. +1 −1 library/common/BUILD
  20. +6 −1 library/common/api/external.cc
  21. +1 −0 library/common/config_template.cc
  22. +1 −1 library/common/engine.h
  23. +0 −27 library/common/extensions/BUILD
  24. +3 −1 library/java/src/io/envoyproxy/envoymobile/engine/EnvoyEngineImpl.java
  25. +11 −3 library/java/src/io/envoyproxy/envoymobile/engine/EnvoyHTTPStream.java
  26. +2 −2 ...tlin/src/io/envoyproxy/envoymobile/{AndroidEnvoyClientBuilder.kt → AndroidStreamClientBuilder.kt}
  27. +8 −10 library/kotlin/src/io/envoyproxy/envoymobile/BUILD
  28. +0 −65 library/kotlin/src/io/envoyproxy/envoymobile/Envoy.kt
  29. +35 −0 library/kotlin/src/io/envoyproxy/envoymobile/EnvoyClient.kt
  30. +0 −26 library/kotlin/src/io/envoyproxy/envoymobile/EnvoyStreamEmitter.kt
  31. +0 −33 library/kotlin/src/io/envoyproxy/envoymobile/HTTPClient.kt
  32. +30 −5 library/kotlin/src/io/envoyproxy/envoymobile/HeadersBuilder.kt
  33. +0 −32 library/kotlin/src/io/envoyproxy/envoymobile/Request.kt
  34. +0 −117 library/kotlin/src/io/envoyproxy/envoymobile/RequestBuilder.kt
  35. +6 −5 library/kotlin/src/io/envoyproxy/envoymobile/RequestHeaders.kt
  36. +25 −2 library/kotlin/src/io/envoyproxy/envoymobile/RequestHeadersBuilder.kt
  37. +0 −23 library/kotlin/src/io/envoyproxy/envoymobile/RequestMapper.kt
  38. +11 −0 library/kotlin/src/io/envoyproxy/envoymobile/RequestTrailers.kt
  39. +20 −0 library/kotlin/src/io/envoyproxy/envoymobile/RequestTrailersBuilder.kt
  40. +0 −129 library/kotlin/src/io/envoyproxy/envoymobile/ResponseHandler.kt
  41. +11 −0 library/kotlin/src/io/envoyproxy/envoymobile/ResponseHeaders.kt
  42. +21 −1 library/kotlin/src/io/envoyproxy/envoymobile/ResponseHeadersBuilder.kt
  43. +11 −0 library/kotlin/src/io/envoyproxy/envoymobile/ResponseTrailers.kt
  44. +20 −0 library/kotlin/src/io/envoyproxy/envoymobile/ResponseTrailersBuilder.kt
  45. +1 −2 library/kotlin/src/io/envoyproxy/envoymobile/RetryPolicy.kt
  46. +61 −0 library/kotlin/src/io/envoyproxy/envoymobile/Stream.kt
  47. +52 −0 library/kotlin/src/io/envoyproxy/envoymobile/StreamCallbacks.kt
  48. +13 −0 library/kotlin/src/io/envoyproxy/envoymobile/StreamClient.kt
  49. +17 −14 library/kotlin/src/io/envoyproxy/envoymobile/{EnvoyClientBuilder.kt → StreamClientBuilder.kt}
  50. +0 −40 library/kotlin/src/io/envoyproxy/envoymobile/StreamEmitter.kt
  51. +109 −0 library/kotlin/src/io/envoyproxy/envoymobile/StreamPrototype.kt
  52. +8 −13 library/kotlin/src/io/envoyproxy/envoymobile/grpc/GRPCClient.kt
  53. +0 −83 library/kotlin/src/io/envoyproxy/envoymobile/grpc/GRPCRequestBuilder.kt
  54. +24 −0 library/kotlin/src/io/envoyproxy/envoymobile/grpc/GRPCRequestHeaders.kt
  55. +76 −0 library/kotlin/src/io/envoyproxy/envoymobile/grpc/GRPCRequestHeadersBuilder.kt
  56. +59 −0 library/kotlin/src/io/envoyproxy/envoymobile/grpc/GRPCStream.kt
  57. +0 −42 library/kotlin/src/io/envoyproxy/envoymobile/grpc/GRPCStreamEmitter.kt
  58. +77 −57 library/kotlin/src/io/envoyproxy/envoymobile/grpc/{GRPCResponseHandler.kt → GRPCStreamPrototype.kt}
  59. +17 −0 library/kotlin/src/io/envoyproxy/envoymobile/mocks/MockEnvoyEngine.kt
  60. +22 −0 library/kotlin/src/io/envoyproxy/envoymobile/mocks/MockEnvoyHTTPStream.kt
  61. +95 −0 library/kotlin/src/io/envoyproxy/envoymobile/mocks/MockStream.kt
  62. +14 −0 library/kotlin/src/io/envoyproxy/envoymobile/mocks/MockStreamClient.kt
  63. +17 −0 library/kotlin/src/io/envoyproxy/envoymobile/mocks/MockStreamPrototype.kt
  64. +14 −54 library/kotlin/test/io/envoyproxy/envoymobile/BUILD
  65. +0 −212 library/kotlin/test/io/envoyproxy/envoymobile/EnvoyClientTest.kt
  66. +0 −63 library/kotlin/test/io/envoyproxy/envoymobile/GRPCRequestBuilderTest.kt
  67. +69 −0 library/kotlin/test/io/envoyproxy/envoymobile/GRPCRequestHeadersBuilderTest.kt
  68. +0 −296 library/kotlin/test/io/envoyproxy/envoymobile/GRPCResponseHandlerTest.kt
  69. +0 −101 library/kotlin/test/io/envoyproxy/envoymobile/GRPCStreamEmitterTest.kt
  70. +263 −0 library/kotlin/test/io/envoyproxy/envoymobile/GRPCStreamTest.kt
  71. +45 −0 library/kotlin/test/io/envoyproxy/envoymobile/HeadersBuilderTest.kt
  72. +0 −148 library/kotlin/test/io/envoyproxy/envoymobile/RequestBuilderTest.kt
  73. +246 −0 library/kotlin/test/io/envoyproxy/envoymobile/RequestHeadersBuilderTest.kt
  74. +0 −282 library/kotlin/test/io/envoyproxy/envoymobile/RequestMapperTest.kt
  75. +0 −52 library/kotlin/test/io/envoyproxy/envoymobile/RequestTest.kt
  76. +0 −50 library/kotlin/test/io/envoyproxy/envoymobile/ResponseHandlerTest.kt
  77. +4 −4 library/kotlin/test/io/envoyproxy/envoymobile/RetryPolicyMapperTest.kt
  78. +24 −25 ...ry/kotlin/test/io/envoyproxy/envoymobile/{EnvoyClientBuilderTest.kt → StreamClientBuilderTest.kt}
  79. +2 −0 library/objective-c/EnvoyEngine.h
  80. +20 −0 library/objective-c/EnvoyEngineImpl.m
  81. +1 −1 library/swift/src/EnvoyClient.swift
  82. +1 −1 library/swift/src/Headers.swift
  83. +3 −3 library/swift/src/HeadersBuilder.swift
  84. +3 −3 library/swift/src/StreamClientBuilder.swift
  85. +4 −0 library/swift/src/filters/RequestFilter.swift
  86. +4 −4 library/swift/src/grpc/GRPCRequestHeadersBuilder.swift
  87. +1 −1 library/swift/src/grpc/GRPCStream.swift
  88. +14 −0 library/swift/src/grpc/GRPCStreamPrototype.swift
  89. +1 −1 library/swift/src/mocks/MockStream.swift
  90. +7 −0 library/swift/src/mocks/MockStreamClient.swift
  91. +4 −0 library/swift/src/mocks/MockStreamPrototype.swift
  92. +4 −3 library/swift/test/GRPCRequestHeadersBuilderTests.swift
  93. +7 −6 library/swift/test/GRPCStreamTests.swift
  94. +10 −10 library/swift/test/StreamClientBuilderTests.swift
16 changes: 8 additions & 8 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ jobs:
linuxdist:
name: linux_dist
runs-on: ubuntu-18.04
timeout-minutes: 45
timeout-minutes: 90
steps:
- uses: actions/checkout@v1
with:
@@ -36,7 +36,7 @@ jobs:
macdist:
name: mac_dist
runs-on: macOS-latest
timeout-minutes: 45
timeout-minutes: 90
steps:
- uses: actions/checkout@v1
with:
@@ -58,7 +58,7 @@ jobs:
name: mac_java_helloworld
needs: macdist
runs-on: macOS-latest
timeout-minutes: 45
timeout-minutes: 90
steps:
- uses: actions/checkout@v1
with:
@@ -85,13 +85,13 @@ jobs:
adb install -r --no-incremental bazel-bin/examples/java/hello_world/hello_envoy.apk
adb shell am start -n io.envoyproxy.envoymobile.helloenvoy/.MainActivity
name: 'Start java app'
- run: 'adb logcat -e "successful response" -m 1'
- run: 'adb logcat -e "received headers with status 200" -m 1'
name: 'Check liveliness'
mackotlin:
name: mac_kotlin_helloworld
needs: macdist
runs-on: macOS-latest
timeout-minutes: 45
timeout-minutes: 90
steps:
- uses: actions/checkout@v1
with:
@@ -118,12 +118,12 @@ jobs:
adb install -r --no-incremental bazel-bin/examples/kotlin/hello_world/hello_envoy_kt.apk
adb shell am start -n io.envoyproxy.envoymobile.helloenvoykotlin/.MainActivity
name: 'Start kotlin app'
- run: 'adb logcat -e "successful response" -m 1'
- run: 'adb logcat -e "received headers with status 200" -m 1'
name: 'Check liveliness'
kotlintests:
name: kotlin_tests
runs-on: ubuntu-18.04
timeout-minutes: 45
timeout-minutes: 90
steps:
- uses: actions/checkout@v1
with:
@@ -135,7 +135,7 @@ jobs:
javatests:
name: java_tests
runs-on: ubuntu-18.04
timeout-minutes: 45
timeout-minutes: 90
steps:
- uses: actions/checkout@v1
with:
6 changes: 3 additions & 3 deletions .github/workflows/core.yml
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ jobs:
unittests:
name: unit_tests
runs-on: macOS-latest
timeout-minutes: 60
timeout-minutes: 90
steps:
- uses: actions/checkout@v1
with:
@@ -22,7 +22,7 @@ jobs:
tsan:
name: tsan
runs-on: ubuntu-18.04
timeout-minutes: 60
timeout-minutes: 90
steps:
- uses: actions/checkout@v1
with:
@@ -38,7 +38,7 @@ jobs:
asan:
name: asan
runs-on: ubuntu-18.04
timeout-minutes: 60
timeout-minutes: 90
steps:
- uses: actions/checkout@v1
with:
4 changes: 2 additions & 2 deletions .github/workflows/ios.yml
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ jobs:
run: 'cat /tmp/envoy.log'
# Check for the sentinel value that shows the app is alive and well.
- name: 'Check liveliness'
run: 'cat /tmp/envoy.log | grep "Response status (1): 200"'
run: 'cat /tmp/envoy.log | grep "received headers with status 200"'
macobjc:
name: mac_objc_helloworld
needs: macdist
@@ -89,7 +89,7 @@ jobs:
run: 'cat /tmp/envoy.log'
# Check for the sentinel value that shows the app is alive and well.
- name: 'Check liveliness'
run: 'cat /tmp/envoy.log | grep "Response status (1): 200"'
run: 'cat /tmp/envoy.log | grep "received headers with status 200"'
swifttests:
name: swift_tests
runs-on: macOS-latest
3 changes: 2 additions & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ envoy_mobile_dependencies()
load("@envoy_mobile//bazel:envoy_mobile_toolchains.bzl", "envoy_mobile_toolchains")
envoy_mobile_toolchains()

android_sdk_repository(name = "androidsdk")
# Fixing to API 29 since proguard seems to be failing for 30+
android_sdk_repository(name = "androidsdk", api_level = 29)

android_ndk_repository(name = "androidndk")
1 change: 1 addition & 0 deletions bazel/aar_with_jni.bzl
Original file line number Diff line number Diff line change
@@ -270,6 +270,7 @@ def _create_sources_javadocs(name, android_library):
java -jar $(location @kotlin_dokka//jar) \
$$sources_dir \
-format javadoc \
-noStdlibLink -noJdkLink \
-output $$tmp_dir > /dev/null
cd $$tmp_dir
zip -r $$original_directory/$@ . > /dev/null
190 changes: 126 additions & 64 deletions docs/root/api/grpc.rst
Original file line number Diff line number Diff line change
@@ -16,132 +16,194 @@ Envoy Mobile implements the gRPC protocol, accepting and returning serialized pr
In the future, Envoy Mobile will provide much more comprehensive integration with gRPC and protobuf,
utilizing annotations for enhanced functionality.

-----------
Quick start
-----------

Below are some quick examples for getting started with gRPC streams. See the individual class references
in the later sections of this page for in-depth information on how each type is used.

Start and interact with a gRPC stream in **Kotlin**::

val headers = GRPCRequestHeadersBuilder(scheme = "https", authority = "envoyproxy.io", path = "/pb.api.v1.Foo/GetBar")
.build()

val streamClient = AndroidStreamClientBuilder(application).build()
GRPCClient(streamClient)
.newGRPCStreamPrototype()
.setOnResponseHeaders { headers, endStream ->
Log.d("MainActivity", "Headers received: $headers, end stream: $endStream")
}
.setOnResponseMessage { messageData in
Log.d("MainActivity", "Received gRPC message")
}
.setOnResponseTrailers { trailers in
Log.d("MainActivity", "Trailers received: $trailers")
}
.setOnError { ... }
.setOnCancel { ... }
.start(Executors.newSingleThreadExecutor())
.sendHeaders(headers, false)
.sendMessage(...)
...
.close()

Start and interact with a gRPC stream in **Swift**::

let headers = GRPCRequestHeadersBuilder(scheme: "https", authority: "envoyproxy.io", path: "/pb.api.v1.Foo/GetBar")
.build()

let streamClient = try StreamClientBuilder().build()
GRPCClient(streamClient: streamClient)
.newGRPCStreamPrototype()
.setOnResponseHeaders { headers, endStream in
print("Headers received: \(headers), end stream: \(endStream)")
}
.setOnResponseMessage { messageData in
print("Received gRPC message")
}
.setOnResponseTrailers { trailers in
print("Trailers received: \(trailers)")
}
.setOnError { ... }
.setOnCancel { ... }
.start(queue: .main)
.sendHeaders(headers, endStream: false)
.sendMessage(...)
...
.close()

--------------
``GRPCClient``
--------------

The ``GRPCClient`` type provides the ability to start gRPC streams, and is backed by Envoy Mobile's
``HTTPClient`` type that is instantiated using the ``EnvoyClientBuilder``.
``StreamClient`` interface (typically instantiated using a ``StreamClientBuilder``).

To create a ``GRPCClient``, simply :ref:`create an HTTP client <api_starting_envoy>` and pass it to the initializer:
To create a ``GRPCClient``, simply :ref:`create a stream client <api_starting_envoy>` and pass it to the initializer:

``grpcClient = GRPCClient(httpClient)``
``grpcClient = GRPCClient(streamClient)``

This client can then be used with the types outlined below for starting gRPC streams.

----------------------
``GRPCRequestBuilder``
``GRPCRequestHeaders``
----------------------

Envoy Mobile provides a ``GRPCRequestBuilder`` which acts very similarly to the ``RequestBuilder``
type. Upon calling ``build()``, it returns a ``Request`` (the same type used for standard HTTP
requests/streams) which is preconfigured for gRPC.
Envoy Mobile provides a ``GRPCRequestHeadersBuilder`` which acts very similarly to the ``RequestHeadersBuilder``
type. Upon calling ``build()``, it returns a ``GRPCRequestHeaders`` instance - a subclass of ``RequestHeaders``
configured specifically for gRPC streams.

To start a gRPC stream, create a ``Request`` using the ``GRPCRequestBuilder``.
To start a gRPC stream, first create an instance of ``GRPCRequestHeaders`` using the ``GRPCRequestHeadersBuilder``.

**Kotlin**::

val request = GRPCRequestBuilder("/pb.api.v1.Foo/GetBar", "api.envoyproxy.io", true)
.addHeader("x-custom-header", "foobar")
val headers = GRPCRequestHeadersBuilder("https", "envoyproxy.io", "/pb.api.v1.Foo/GetBar")
.add("x-foo", "123")
...
.build()

**Swift**::

let request = GRPCRequestBuilder(path: "/pb.api.v1.Foo/GetBar", authority: "api.envoyproxy.io", useHTTPS: true)
.addHeader(name: "x-custom-header", value: "foobar")
let headers = GRPCRequestHeadersBuilder(scheme: "https", authority: "envoyproxy.io", path: "/pb.api.v1.Foo/GetBar")
.add(name: "x-foo", value: "123")
...
.build()

-----------------------
``GRPCResponseHandler``
``GRPCStreamPrototype``
-----------------------

Very similarly to the HTTP ``ResponseHandler``, the ``GRPCResponseHandler`` allows for receiving
updates to the gRPC stream and contains a set of callbacks that are called whenever an update
occurs on the stream.

This handler processes inbound gRPC responses, buffers data as necessary while chunks of
protobuf messages are received, then finally passes fully formed protobuf data to the callbacks
provided.
A ``GRPCStreamPrototype`` is used to configure gRPC streams prior to starting them by assigning callbacks
to be invoked when response data is received on the stream.

Typically, consumers should listen to ``onMessage`` and use a protobuf library to deserialize
the complete protobuf message data.

To create a ``GRPCStreamPrototype``, use an instance of ``GRPCClient``.

**Kotlin**::

val handler = GRPCResponseHandler(Executor { })
.onHeaders { headers, grpcStatus, _ ->
Log.d("MainActivity", "Received gRPC status: " + statusCode + " and headers: " + headers)
Unit
val prototype = grpcClient
.newGRPCStreamPrototype()
.setOnResponseHeaders { headers, endStream ->
Log.d("MainActivity", "Headers received: $headers, end stream: $endStream")
}
.onMessage { messageData ->
// Deserialize message data here
.setOnResponseMessage { messageData ->
Log.d("MainActivity", "Received gRPC message")
}
.onTrailers { trailers ->
Log.d("MainActivity", "Trailers received: " + trailers)
Unit
.setOnResponseTrailers { trailers ->
Log.d("MainActivity", "Trailers received: $trailers")
}
.onError { error ->
Log.d("MainActivity", "Error received: " + error.message)
Unit
}
...
.setOnError { ... }
.setOnCancel { ... }

**Swift**::

let handler = GRPCResponseHandler()
.onHeaders { headers, grpcStatus, _ in
print("Received gRPC status: \(grpcStatus) and headers: \(headers)")
let prototype = grpcClient
.newGRPCStreamPrototype()
.setOnResponseHeaders { headers, endStream in
print("Headers received: \(headers), end stream: \(endStream)")
}
.onMessage { messageData in
// Deserialize message data here
.setOnResponseMessage { messageData in
print("Received gRPC message")
}
.onTrailers { trailers in
.setOnResponseTrailers { trailers in
print("Trailers received: \(trailers)")
}
.onError { error in
print("Error received: \(error.message)")
}
...

.setOnError { ... }
.setOnCancel { ... }

---------------------
``GRPCStreamEmitter``
---------------------
--------------
``GRPCStream``
--------------

Finally, a gRPC stream may be opened using a ``GRPCClient`` instance.
gRPC streams are started by calling ``start()`` on a ``GRPCStreamPrototype``.

Doing so returns a ``GRPCStreamEmitter`` which allows the sender to interact with the stream.
Doing so returns a ``GRPCStream`` which allows the sender to interact with the stream.

The ``sendMessage`` function should be invoked with the serialized data from a protobuf message.
The emitter will then transform the provided data into the gRPC wire format and send it over the
stream.

**Kotlin**::

val envoy = AndroidEnvoyClientBuilder(...).build()
val grpcClient = GRPCClient(envoy)
val streamClient = AndroidStreamClientBuilder()
...
.build()
val grpcClient = GRPCClient(streamClient)

val request = GRPCRequestBuilder(...).build()
val responseHandler = GRPCResponseHandler(...)
val grpcEmitter = grpcClient.start(request, responseHandler)
.sendMessage(...)
val requestHeaders = GRPCRequestHeadersBuilder()
...
.build()
val prototype = grpcClient
.newGRPCStreamPrototype()
...
val stream = prototype
.start(Executors.newSingleThreadExecutor())
.sendHeaders(...)
.sendMessage(...)

...
grpcEmitter.close(...)
stream.close(...)

**Swift**::

let envoy = try EnvoyClientBuilder(...).build()
let grpcClient = GRPCClient(httpClient: envoy)
let streamClient = StreamClientBuilder()
...
.build()
let grpcClient = GRPCClient(streamClient: streamClient)

let request = GRPCRequestBuilder(...).build()
let responseHandler = GRPCResponseHandler(...)
let grpcEmitter = grpcClient.start(request, handler: responseHandler)
.sendMessage(...)
let requestHeaders = GRPCRequestHeadersBuilder()
...
.build()
let prototype = grpcClient
.newGRPCStreamPrototype()
...
let stream = prototype
.start(queue: .main)
.sendHeaders(...)
.sendMessage(...)

...
grpcEmitter.close(...)
stream.close(...)
Loading