From 4d1e7efb919d2590bdc6280e82f52453a7970ae6 Mon Sep 17 00:00:00 2001 From: Mikko Karjalainen Date: Tue, 23 Oct 2018 17:39:46 +0100 Subject: [PATCH 01/15] Update devdocs to styx 1.0: plugins-scenarios.md. --- docs/developer-guide/plugins-scenarios.md | 190 +++++++++------------- 1 file changed, 76 insertions(+), 114 deletions(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index f38fc372dd..28ab3292fe 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -7,7 +7,7 @@ Transforming a request object synchronously is trivial. By "synchronously" we mean in the same thread, in non-blocking fashion. -Just call `request.newBuilder()` to create a new `HttpRequest.Builder` object. +Just call `request.newBuilder` to create a new `HttpRequest.Builder` object. It has already been initialised with the copy of the original `request`. Modify the builder as desired, construct a new version, and pass it to the `chain.proceed()`, as the example demonstrates: @@ -22,7 +22,7 @@ import static com.hotels.styx.api.HttpHeaderNames.USER_AGENT; public class SyncRequestPlugin implements Plugin { @Override - public StyxObservable intercept(HttpRequest request, Chain chain) { + public Eventual intercept(LiveHttpRequest request, Chain chain) { return chain.proceed( request.newBuilder() .header(USER_AGENT, "Styx/1.0 just testing plugins") @@ -35,7 +35,7 @@ public class SyncRequestPlugin implements Plugin { ### Synchronously transforming response This example demonstrates how to synchronously transform a HTTP response. We will -use a `StyxObservable.map` method to add an "X-Foo" header to the response. +use a `Eventual.map` method to add an "X-Foo" header to the response. ```java import com.hotels.styx.api.HttpInterceptor; @@ -46,7 +46,7 @@ import com.hotels.styx.api.plugins.spi.Plugin; public class SyncResponsePlugin implements Plugin { @Override - public StyxObservable intercept(HttpRequest request, HttpInterceptor.Chain chain) { + public Eventual intercept(LiveHttpRequest request, HttpInterceptor.Chain chain) { return chain.proceed(request) .map(response -> response.newBuilder() .header("X-Foo", "bar") @@ -75,7 +75,7 @@ import java.util.concurrent.CompletableFuture; public class AsyncRequestInterceptor implements Plugin { @Override - public StyxObservable intercept(HttpRequest request, HttpInterceptor.Chain chain) { + public Eventual intercept(LiveHttpRequest request, HttpInterceptor.Chain chain) { return asyncUrlReplacement(request.url()) // (1) .map(newUrl -> request.newBuilder() // (4) @@ -84,8 +84,8 @@ public class AsyncRequestInterceptor implements Plugin { .flatMap(chain::proceed); // (5) } - private static StyxObservable asyncUrlReplacement(Url url) { - return StyxObservable.from(pathReplacementService(url.path())) // (3) + private static Eventual asyncUrlReplacement(Url url) { + return Eventual.from(pathReplacementService(url.path())) // (3) .map(newPath -> new Url.Builder(url) .path(newPath) .build()); @@ -98,15 +98,15 @@ public class AsyncRequestInterceptor implements Plugin { } ``` -Step 1. We call the `asyncUrlReplacement`, which returns a `StyxObservable`. +Step 1. We call the `asyncUrlReplacement`, which returns an `Eventual`. The `asyncUrlReplacement` wraps a call to the remote service and converts -the outcome into a `StyxObservable`, which is the basis for our response observable. +the outcome into a `Eventual`, which is the basis for our response observable. Step 2. A call to `pathReplacementService` makes a non-blocking call to the remote key/value store. Well, at least we pretend to call the key value store, but in this example we'll just return a completed future of a constant value. -Step 3. `CompletableFuture` is converted to `StyxObservable`, so that other asynchronous +Step 3. `CompletableFuture` is converted to an `Eventual`, so that other asynchronous operations like `chain.proceed` can be bound to it later on. Step 4. The eventual outcome from the `asyncUrlReplacement` yields a new, modified URL instance. @@ -114,7 +114,7 @@ We'll transform the `request` by substituting the URL path with the new one. This is a quick synchronous operation so we'll do it in a `map` operator. Step 5. Finally, we will bind the outcome from `chain.proceed` into the response observable. -Remember that `chain.proceed` returns an `Observable` it is therefore +Remember that `chain.proceed` returns an `Eventual` it is therefore interface compatible and can be `flatMap`'d to the response observable. The resulting response observable chain is returned from the `intercept`. @@ -140,11 +140,10 @@ public class AsyncResponseInterceptor implements Plugin { private static final String X_MY_HEADER = "X-My-Header"; @Override - public StyxObservable intercept(HttpRequest request, HttpInterceptor.Chain chain) { + public Eventual intercept(LiveHttpRequest request, HttpInterceptor.Chain chain) { return chain.proceed(request) // (1) .flatMap(response -> // (3) - StyxObservable - .from(thirdPartyHeaderService(response.header(X_MY_HEADER).orElse("default"))) // (1) + Eventual.from(thirdPartyHeaderService(response.header(X_MY_HEADER).orElse("default"))) // (2) .map(value -> // (4) response.newBuilder() .header(X_MY_HEADER, value) @@ -159,10 +158,10 @@ public class AsyncResponseInterceptor implements Plugin { } ``` -Step 1. We start by calling `chain.proceed(request)` to obtain a response observable. +Step 1. We start by calling `chain.proceed(request)` to obtain a response `Eventual`. -Step 2. A `callTo3rdParty` returns a CompletableFuture. We use `StyxObservable.from` to convert it -into a `StyxObservable` so that it can be bound to the response observable. +Step 2. A `callTo3rdParty` returns a `CompletableFuture`. It is converted to an `Eventual` with +`Eventual.from` and bound to response `Eventual`. Step 3. The `flatMap` operator binds `callToThirdParty` into the response observable. @@ -172,11 +171,11 @@ into the response headers. ## HTTP Content Transformations -Styx exposes HTTP messages to interceptors as streaming `HttpRequest` and `HttpResponse` messages. +Styx exposes HTTP messages to interceptors as streaming `LiveHttpRequest` and `LiveHttpResponse` messages. In this form, the interceptors can process the content in a streaming fashion. That is, they they can look into, and modify the content as it streams through. -Alternatively, streaming messages can be aggregated into a `FullHttpRequest` or `FullHttpResponse` +Alternatively, live messages can be aggregated to `HttpRequest` or `HttpResponse` messages. The full HTTP message body is then available for the interceptor to use. Note that content aggregation is always an asynchronous operation. This is because the streaming HTTP message is exposing the content, in byte buffers, as it arrives from the network, and Styx must wait until @@ -195,7 +194,7 @@ public class RequestAggregationPlugin implements Plugin { private static final int MAX_CONTENT_LENGTH = 100000; @Override - public StyxObservable intercept(HttpRequest request, Chain chain) { + public Eventual intercept(LiveHttpRequest request, Chain chain) { return request.toFullRequest(MAX_CONTENT_LENGTH) .map(fullRequest -> fullRequest.newBuilder() .body(new byte[0], true) @@ -206,7 +205,7 @@ public class RequestAggregationPlugin implements Plugin { ``` `maxContentBytes` is a safety valve that prevents Styx from accumulating too much content -and possibly running out of memory. Styx only accumulates up to `maxContentBytes` of content. +and running out of memory. Styx only accumulates up to `maxContentBytes` of content. `toFullRequest` fails when the content stream exceeds this amount, and Styx emits a `ContentOverflowException`, @@ -216,15 +215,14 @@ and possibly running out of memory. Styx only accumulates up to `maxContentBytes Streaming HTTP body content can be transformed both synchronously and asynchronously. However there are some pitfalls you need to know: - - Reference counting. Styx exposes the content stream as an observable of reference counted - Netty `ByteBuf` objects. Ensure the reference counts are correctly decremented when - buffers are transformed. - - - Continuity (or discontinuity) of Styx content observable. Each content tranformation with - `map` or `flatMap` is a composition of some source observable. So is each content transformation + - Reference counting. Styx exposes the content stream as a `ByteStream` of reference counted + `Buffer` objects. + + - Continuity (or discontinuity) of Styx content `ByteStream`. Each content transformation with + `map` or `flatMap` is a composition of another `ByteStream`. So is each content transformation linked to some source observable, an ultimate source being the Styx server core. It is the consumer's responsibility to ensure this link never gets broken. That is, you - are not allowed to just substitute the content observable with another one, unless it composes + are not allowed to just replace the content stream with another one, unless it composes to the previous content source. @@ -233,115 +231,79 @@ However there are some pitfalls you need to know: In this rather contrived example we will transform HTTP response content to upper case letters. -Streaming `HttpRequest` content is a byte buffer stream. The stream can be accessed -with a `request.body()` method and its data type is `StyxObservable`. - -Because `toUpperCase` is non-blocking transformation we can compose it to the original -byte stream using a `map` operator. - -The mapping function decodes the original byte buffer `buf` to an UTF-8 encoded -Java `String`, and copies its upper case representation into a newly created byte buffer. -The old byte buffer `buf` is discarded. - -Because `buf` is a Netty reference counted `ByteBuf`, we must take care to decrement its -reference count by calling `buf.release()`. - ```java public class MyPlugin extends Plugin { @Override - public StyxObservable intercept(HttpRequest request, Chain chain) { - StyxObservable toUpperCase = request.body() - .map(buf -> { - buf.release(); - return copiedBuffer(buf.toString(UTF_8).toUpperCase(), UTF_8); - }); - + public Eventual intercept(LiveHttpRequest request, Chain chain) { return chain.proceed( request.newBuilder() - .body(toUpperCase) + .body(byteStream -> // 1 + byteStream.map(buf -> { // 2 + String upperCase = new String(buf.content(), UTF_8).toUpperCase(); // 3 + return new Buffer(upperCase, UTF_8); + })) .build() ); } } ``` -### Asynchronously transforming streaming request content - -Asynchronous content stream transformation is very similar to the synchronous transformation. -The only difference is that asynchronous transformation must be composed with a `flatMap` -instead of `map`. Otherwise the same discussion apply. As always it is important to take care -of the reference counting. +A call to `request.newBuilder` opens up a new request builder that allows request to be transformed. -```java -public class AsyncRequestContentTransformation implements Plugin { - - @Override - public StyxObservable intercept(HttpRequest request, Chain chain) { - StyxObservable contentMapping = request.body() - .flatMap(buf -> { - String content = buf.toString(UTF_8); - buf.release(); - return sendToRemoteServer(content) - .map(value -> copiedBuffer(value, UTF_8)); - }); +The body transformation involves two lambda methods: - return chain.proceed( - request.newBuilder() - .body(contentMapping) - .build() - ); - } - - StyxObservable sendToRemoteServer(String buf) { - return StyxObservable.of("modified 3rd party content"); - } -} -``` + 1. A `.body(Function)` accepts a lambda that modifies the request + byte stream. Here we provide a lambda that accepts a `ByteStream` and returns another + by applying a synchronous `map` operator on the stream. + + 2. The `ByteStream` is modified by applying a `map` operator that synchronously modifies + each `Buffer` that streams through. The `map` involves another lambda that accepts a + `Buffer` and returns a modified buffer. + + 3. In this example the buffer is converted to an upper case. + ### Synchronously transforming streaming response content +This example demonstrates how an HTTP response content can be transformed synchronously. + ```java public class AsyncResponseContentStreamTransformation implements Plugin { @Override - public StyxObservable intercept(HttpRequest request, Chain chain) { + public Eventual intercept(LiveHttpRequest request, Chain chain) { return chain.proceed(request) - .map(response -> { - StyxObservable contentMapping = response.body() - .map(buf -> { - buf.release(); - return copiedBuffer(buf.toString(UTF_8).toUpperCase(), UTF_8); - }); - return response.newBuilder() - .body(contentMapping) - .build(); - }); + .map(response -> // 1 + response.newBuilder() + .body(byteStream -> // 2 + byteStream.map(buf -> { // 3 + String upperCase = new String(buf.content(), UTF_8).toUpperCase(); // 4 + return new Buffer(upperCase, UTF_8); + })) + .build()); } } ``` -### Asynchronously transforming streaming response content +This is quite similar to the request transformation but it involves an additional lambda +expression to capture the HTTP response from `Eventual` envelope: -```java -public class AsyncResponseContentStreamTransformation implements Plugin { - @Override - public StyxObservable intercept(HttpRequest request, Chain chain) { - return chain.proceed(request) - .map(response -> { - StyxObservable contentMapping = response.body() - .flatMap(buf -> { - String content = buf.toString(UTF_8); - buf.release(); - return sendToRemoteServer(content) - .map(value -> copiedBuffer(value, UTF_8)); - }); - return response.newBuilder() - .body(contentMapping) - .build(); - }); - } + 1. `chain.proceed` returns an `Eventual` HTTP response. We apply a `Eventual.map` operator + to tap into this response. The `map` operator accepts a lambda expression that handles the + response when it eventually is available. + +After that, we will transform the response just like we did in the previous example for + response content transformations. - StyxObservable sendToRemoteServer(String buf) { - return StyxObservable.of("modified 3rd party content"); - } -} -``` \ No newline at end of file + + +### Asynchronously transforming streaming request content + +Not supported at the moment. Please raise a feature request and the Styx team can implement this. + + + + + +### Asynchronously transforming streaming response content + +Not supported at the moment. Please raise a feature request and the Styx team can implement this. From 8c34125f1291d583fdeaf8c74bc29ef5afb5cb72 Mon Sep 17 00:00:00 2001 From: Mikko Karjalainen Date: Wed, 24 Oct 2018 17:30:14 +0100 Subject: [PATCH 02/15] Update as per code review findings. --- docs/developer-guide/plugins-scenarios.md | 34 ++++++++++++----------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index 28ab3292fe..d0894af291 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -100,7 +100,7 @@ public class AsyncRequestInterceptor implements Plugin { Step 1. We call the `asyncUrlReplacement`, which returns an `Eventual`. The `asyncUrlReplacement` wraps a call to the remote service and converts -the outcome into a `Eventual`, which is the basis for our response observable. +the outcome into a `Eventual`. Step 2. A call to `pathReplacementService` makes a non-blocking call to the remote key/value store. Well, at least we pretend to call the key value store, but in this example we'll just return a @@ -113,10 +113,10 @@ Step 4. The eventual outcome from the `asyncUrlReplacement` yields a new, modifi We'll transform the `request` by substituting the URL path with the new one. This is a quick synchronous operation so we'll do it in a `map` operator. -Step 5. Finally, we will bind the outcome from `chain.proceed` into the response observable. -Remember that `chain.proceed` returns an `Eventual` it is therefore -interface compatible and can be `flatMap`'d to the response observable. The resulting -response observable chain is returned from the `intercept`. +Step 5. Finally, we will bind the outcome from `chain.proceed` into the response eventual. +Remember that `chain.proceed` returns an `Eventual`. It is therefore +interface compatible and can be `flatMap`'d to the response eventual. The resulting +response eventual chain is returned from the `intercept`. ### Asynchronously transform response object @@ -163,7 +163,7 @@ Step 1. We start by calling `chain.proceed(request)` to obtain a response `Event Step 2. A `callTo3rdParty` returns a `CompletableFuture`. It is converted to an `Eventual` with `Eventual.from` and bound to response `Eventual`. -Step 3. The `flatMap` operator binds `callToThirdParty` into the response observable. +Step 3. The `flatMap` operator binds `callToThirdParty` into the response `Eventual`. Step 4. We will transform the HTTP response by inserting an outcome of `callToThirdParty`, or `value`, into the response headers. @@ -215,12 +215,12 @@ and running out of memory. Styx only accumulates up to `maxContentBytes` of cont Streaming HTTP body content can be transformed both synchronously and asynchronously. However there are some pitfalls you need to know: - - Reference counting. Styx exposes the content stream as a `ByteStream` of reference counted + - **Reference counting.** Styx exposes the content stream as a `ByteStream` of reference counted `Buffer` objects. - - Continuity (or discontinuity) of Styx content `ByteStream`. Each content transformation with + - **Continuity (or discontinuity) of Styx content `ByteStream`:** each content transformation with `map` or `flatMap` is a composition of another `ByteStream`. So is each content transformation - linked to some source observable, an ultimate source being the Styx server core. + linked to some source `ByteStream`, an ultimate source being the Styx server core. It is the consumer's responsibility to ensure this link never gets broken. That is, you are not allowed to just replace the content stream with another one, unless it composes to the previous content source. @@ -248,7 +248,8 @@ public class MyPlugin extends Plugin { } ``` -A call to `request.newBuilder` opens up a new request builder that allows request to be transformed. +A call to `request.newBuilder` opens up a new request builder that allows the request +to be transformed to. The body transformation involves two lambda methods: @@ -260,7 +261,8 @@ The body transformation involves two lambda methods: each `Buffer` that streams through. The `map` involves another lambda that accepts a `Buffer` and returns a modified buffer. - 3. In this example the buffer is converted to an upper case. + 3. In this example, the content of the buffer buffer is interpreted as `String` and + converted to an upper case. ### Synchronously transforming streaming response content @@ -285,14 +287,14 @@ public class AsyncResponseContentStreamTransformation implements Plugin { ``` This is quite similar to the request transformation but it involves an additional lambda -expression to capture the HTTP response from `Eventual` envelope: +expression to capture the HTTP response from its `Eventual` envelope: - 1. `chain.proceed` returns an `Eventual` HTTP response. We apply a `Eventual.map` operator + 1. `chain.proceed` returns an `Eventual` HTTP response. We apply an `Eventual.map` operator to tap into this response. The `map` operator accepts a lambda expression that handles the - response when it eventually is available. + response when it is available. -After that, we will transform the response just like we did in the previous example for - response content transformations. +After that, we will transform the response just like we did in the previous example for +response content transformations. From 90f8b71064ffbe3e85f2e3666a12b45857a3a901 Mon Sep 17 00:00:00 2001 From: Mikko Karjalainen Date: Thu, 25 Oct 2018 09:19:18 +0100 Subject: [PATCH 03/15] Fix as per code review findings. --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index d0894af291..a589b479f1 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -161,7 +161,7 @@ public class AsyncResponseInterceptor implements Plugin { Step 1. We start by calling `chain.proceed(request)` to obtain a response `Eventual`. Step 2. A `callTo3rdParty` returns a `CompletableFuture`. It is converted to an `Eventual` with -`Eventual.from` and bound to response `Eventual`. +`Eventual.from` and bound to the response `Eventual`. Step 3. The `flatMap` operator binds `callToThirdParty` into the response `Eventual`. From f4993fd7c842bdac36da4eda2b463acda9ecec78 Mon Sep 17 00:00:00 2001 From: Mikko Karjalainen Date: Thu, 25 Oct 2018 10:47:05 +0100 Subject: [PATCH 04/15] Update as per code review comments. --- docs/developer-guide/plugins-scenarios.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index a589b479f1..5cc03a86f4 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -113,7 +113,7 @@ Step 4. The eventual outcome from the `asyncUrlReplacement` yields a new, modifi We'll transform the `request` by substituting the URL path with the new one. This is a quick synchronous operation so we'll do it in a `map` operator. -Step 5. Finally, we will bind the outcome from `chain.proceed` into the response eventual. +Step 5. Finally, we will bind the outcome from `chain.proceed` into the response `Eventual`. Remember that `chain.proceed` returns an `Eventual`. It is therefore interface compatible and can be `flatMap`'d to the response eventual. The resulting response eventual chain is returned from the `intercept`. @@ -215,7 +215,7 @@ and running out of memory. Styx only accumulates up to `maxContentBytes` of cont Streaming HTTP body content can be transformed both synchronously and asynchronously. However there are some pitfalls you need to know: - - **Reference counting.** Styx exposes the content stream as a `ByteStream` of reference counted + - **Reference counting:** Styx exposes the content stream as a `ByteStream` of reference counted `Buffer` objects. - **Continuity (or discontinuity) of Styx content `ByteStream`:** each content transformation with From cc9fb4443280a22efb9344854fc0cb4813b532e0 Mon Sep 17 00:00:00 2001 From: Mikko Karjalainen Date: Thu, 25 Oct 2018 10:57:45 +0100 Subject: [PATCH 05/15] Modify as per code review comments. --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index 5cc03a86f4..c335b78d4a 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -262,7 +262,7 @@ The body transformation involves two lambda methods: `Buffer` and returns a modified buffer. 3. In this example, the content of the buffer buffer is interpreted as `String` and - converted to an upper case. + converted to upper case. ### Synchronously transforming streaming response content From 9a46d4130bdcb618eb4a2b8f269a993b3cc9e3a0 Mon Sep 17 00:00:00 2001 From: kvosper Date: Thu, 25 Oct 2018 17:24:52 +0100 Subject: [PATCH 06/15] Update docs/developer-guide/plugins-scenarios.md Co-Authored-By: mikkokar --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index c335b78d4a..75b6970b14 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -114,7 +114,7 @@ We'll transform the `request` by substituting the URL path with the new one. This is a quick synchronous operation so we'll do it in a `map` operator. Step 5. Finally, we will bind the outcome from `chain.proceed` into the response `Eventual`. -Remember that `chain.proceed` returns an `Eventual`. It is therefore +Remember that `chain.proceed` returns an `Eventual`. It is, therefore, interface compatible and can be `flatMap`'d to the response eventual. The resulting response eventual chain is returned from the `intercept`. From fed2a541bfb68944a4a1631aeb36cee809817fdc Mon Sep 17 00:00:00 2001 From: kvosper Date: Thu, 25 Oct 2018 17:25:03 +0100 Subject: [PATCH 07/15] Update docs/developer-guide/plugins-scenarios.md Co-Authored-By: mikkokar --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index 75b6970b14..c0aede31f7 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -115,7 +115,7 @@ This is a quick synchronous operation so we'll do it in a `map` operator. Step 5. Finally, we will bind the outcome from `chain.proceed` into the response `Eventual`. Remember that `chain.proceed` returns an `Eventual`. It is, therefore, -interface compatible and can be `flatMap`'d to the response eventual. The resulting +interface compatible and can be `flatMap`'d to the response `Eventual`. The resulting response eventual chain is returned from the `intercept`. From 4841b4bb33adc98289702417065a36a002c5e2cd Mon Sep 17 00:00:00 2001 From: kvosper Date: Thu, 25 Oct 2018 17:25:09 +0100 Subject: [PATCH 08/15] Update docs/developer-guide/plugins-scenarios.md Co-Authored-By: mikkokar --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index c0aede31f7..ccd5a08521 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -116,7 +116,7 @@ This is a quick synchronous operation so we'll do it in a `map` operator. Step 5. Finally, we will bind the outcome from `chain.proceed` into the response `Eventual`. Remember that `chain.proceed` returns an `Eventual`. It is, therefore, interface compatible and can be `flatMap`'d to the response `Eventual`. The resulting -response eventual chain is returned from the `intercept`. +response `Eventual` chain is returned from the `intercept`. ### Asynchronously transform response object From ce91fe0d39afb7ed4c0044d28ac7473ac6f1d6db Mon Sep 17 00:00:00 2001 From: kvosper Date: Thu, 25 Oct 2018 17:25:23 +0100 Subject: [PATCH 09/15] Update docs/developer-guide/plugins-scenarios.md Co-Authored-By: mikkokar --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index ccd5a08521..59e23f608b 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -253,7 +253,7 @@ to be transformed to. The body transformation involves two lambda methods: - 1. A `.body(Function)` accepts a lambda that modifies the request + 1. `.body(Function)` accepts a lambda that modifies the request byte stream. Here we provide a lambda that accepts a `ByteStream` and returns another by applying a synchronous `map` operator on the stream. From 1741f0b3663f21d14e86cb65bb159d9fcccc23f0 Mon Sep 17 00:00:00 2001 From: kvosper Date: Thu, 25 Oct 2018 17:25:31 +0100 Subject: [PATCH 10/15] Update docs/developer-guide/plugins-scenarios.md Co-Authored-By: mikkokar --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index 59e23f608b..deeeeac47c 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -261,7 +261,7 @@ The body transformation involves two lambda methods: each `Buffer` that streams through. The `map` involves another lambda that accepts a `Buffer` and returns a modified buffer. - 3. In this example, the content of the buffer buffer is interpreted as `String` and + 3. In this example, the content of the buffer is interpreted as `String` and converted to upper case. From 8968bef81851f656fa533933d3c208371a81f097 Mon Sep 17 00:00:00 2001 From: kvosper Date: Thu, 25 Oct 2018 17:25:37 +0100 Subject: [PATCH 11/15] Update docs/developer-guide/plugins-scenarios.md Co-Authored-By: mikkokar --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index deeeeac47c..9f373c6033 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -267,7 +267,7 @@ The body transformation involves two lambda methods: ### Synchronously transforming streaming response content -This example demonstrates how an HTTP response content can be transformed synchronously. +This example demonstrates how HTTP response content can be transformed synchronously. ```java public class AsyncResponseContentStreamTransformation implements Plugin { From b02ae4d12f20f7950b334a685f36b18c1af4fb86 Mon Sep 17 00:00:00 2001 From: kvosper Date: Thu, 25 Oct 2018 17:25:43 +0100 Subject: [PATCH 12/15] Update docs/developer-guide/plugins-scenarios.md Co-Authored-By: mikkokar --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index 9f373c6033..bccd0020a2 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -286,7 +286,7 @@ public class AsyncResponseContentStreamTransformation implements Plugin { } ``` -This is quite similar to the request transformation but it involves an additional lambda +This is quite similar to the request transformation, but it involves an additional lambda expression to capture the HTTP response from its `Eventual` envelope: 1. `chain.proceed` returns an `Eventual` HTTP response. We apply an `Eventual.map` operator From 9922e74050e93c63247bf07234e7ba8802634843 Mon Sep 17 00:00:00 2001 From: kvosper Date: Mon, 29 Oct 2018 15:43:36 +0000 Subject: [PATCH 13/15] Update docs/developer-guide/plugins-scenarios.md Co-Authored-By: mikkokar --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index bccd0020a2..a5f41ebc40 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -35,7 +35,7 @@ public class SyncRequestPlugin implements Plugin { ### Synchronously transforming response This example demonstrates how to synchronously transform a HTTP response. We will -use a `Eventual.map` method to add an "X-Foo" header to the response. +call `Eventual.map` to add an "X-Foo" header to the response. ```java import com.hotels.styx.api.HttpInterceptor; From 053b1d1b2c458c6a2f5f3cc1a3af7734ffb4aa3d Mon Sep 17 00:00:00 2001 From: kvosper Date: Mon, 29 Oct 2018 15:43:46 +0000 Subject: [PATCH 14/15] Update docs/developer-guide/plugins-scenarios.md Co-Authored-By: mikkokar --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index a5f41ebc40..8d60081c14 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -100,7 +100,7 @@ public class AsyncRequestInterceptor implements Plugin { Step 1. We call the `asyncUrlReplacement`, which returns an `Eventual`. The `asyncUrlReplacement` wraps a call to the remote service and converts -the outcome into a `Eventual`. +the outcome into an `Eventual`. Step 2. A call to `pathReplacementService` makes a non-blocking call to the remote key/value store. Well, at least we pretend to call the key value store, but in this example we'll just return a From 6192745652272659c5dc3da504516db84707e0a8 Mon Sep 17 00:00:00 2001 From: kvosper Date: Mon, 29 Oct 2018 15:44:06 +0000 Subject: [PATCH 15/15] Update docs/developer-guide/plugins-scenarios.md Co-Authored-By: mikkokar --- docs/developer-guide/plugins-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer-guide/plugins-scenarios.md b/docs/developer-guide/plugins-scenarios.md index 8d60081c14..21f3c00ec2 100644 --- a/docs/developer-guide/plugins-scenarios.md +++ b/docs/developer-guide/plugins-scenarios.md @@ -249,7 +249,7 @@ public class MyPlugin extends Plugin { ``` A call to `request.newBuilder` opens up a new request builder that allows the request -to be transformed to. +to be transformed. The body transformation involves two lambda methods: