From b86cfcfda92f02ce3d2dd5cbaa09a8d473978809 Mon Sep 17 00:00:00 2001 From: Sadeq Dousti <3616518+msdousti@users.noreply.github.com> Date: Tue, 14 Nov 2023 11:03:52 +0100 Subject: [PATCH] Remove unwanted reformatting --- README.md | 460 +++++++++++++++++++++++------------------------------- 1 file changed, 196 insertions(+), 264 deletions(-) diff --git a/README.md b/README.md index 88cdbc9ae..0bb611a2e 100644 --- a/README.md +++ b/README.md @@ -11,17 +11,13 @@ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/zalando/logbook/main/LICENSE) [![Project Map](https://sourcespy.com/shield.svg)](https://sourcespy.com/github/zalandologbook/) -> **Logbook** noun, /lɑɡ bʊk/: A book in which measurements from the ship's log are recorded, along with other salient -> details of the voyage. +> **Logbook** noun, /lɑɡ bʊk/: A book in which measurements from the ship's log are recorded, along with other salient details of the voyage. -**Logbook** is an extensible Java library to enable complete request and response logging for different client- and -server-side technologies. It satisfies a special need by a) allowing web application -developers to log any HTTP traffic that an application receives or sends b) in a way that makes it easy to persist and -analyze it later. This can be useful for traditional log analysis, meeting audit +**Logbook** is an extensible Java library to enable complete request and response logging for different client- and server-side technologies. It satisfies a special need by a) allowing web application +developers to log any HTTP traffic that an application receives or sends b) in a way that makes it easy to persist and analyze it later. This can be useful for traditional log analysis, meeting audit requirements or investigating individual historic traffic issues. -Logbook is ready to use out of the box for most common setups. Even for uncommon applications and technologies, it -should be simple to implement the necessary interfaces to connect a +Logbook is ready to use out of the box for most common setups. Even for uncommon applications and technologies, it should be simple to implement the necessary interfaces to connect a library/framework/etc. to it. ## Features @@ -54,7 +50,6 @@ library/framework/etc. to it. Add the following dependency to your project: ```xml - org.zalando logbook-core @@ -67,7 +62,6 @@ Add the following dependency to your project: For Spring 5 / Spring Boot 2 backwards compatibility please add the following import: ```xml - org.zalando logbook-servlet @@ -81,17 +75,16 @@ Additional modules/artifacts of Logbook always share the same version number. Alternatively, you can import our *bill of materials*... ```xml - - - - org.zalando - logbook-bom - ${logbook.version} - pom - import - - + + + org.zalando + logbook-bom + ${logbook.version} + pom + import + + ``` @@ -99,69 +92,66 @@ Alternatively, you can import our *bill of materials*... ... which allows you to omit versions: ```xml - org.zalando logbook-core -org.zalando -logbook-httpclient + org.zalando + logbook-httpclient -org.zalando -logbook-jaxrs + org.zalando + logbook-jaxrs -org.zalando -logbook-json + org.zalando + logbook-json -org.zalando -logbook-netty + org.zalando + logbook-netty -org.zalando -logbook-okhttp + org.zalando + logbook-okhttp -org.zalando -logbook-okhttp2 + org.zalando + logbook-okhttp2 -org.zalando -logbook-servlet + org.zalando + logbook-servlet -org.zalando -logbook-spring-boot-starter + org.zalando + logbook-spring-boot-starter -org.zalando -logbook-ktor-common + org.zalando + logbook-ktor-common -org.zalando -logbook-ktor-client + org.zalando + logbook-ktor-client -org.zalando -logbook-ktor-server + org.zalando + logbook-ktor-server -org.zalando -logbook-ktor + org.zalando + logbook-ktor -org.zalando -logbook-logstash + org.zalando + logbook-logstash ``` - -The logbook logger must be configured to trace level in order to log the requests and responses. With Spring Boot 2 ( -using Logback) this can be accomplished by adding the following line to your `application.properties` +The logbook logger must be configured to trace level in order to log the requests and responses. With Spring Boot 2 (using Logback) this can be accomplished by adding the following line to your `application.properties` ``` logging.level.org.zalando.logbook: TRACE @@ -173,25 +163,24 @@ All integrations require an instance of `Logbook` which holds all configuration You can either create one using all the defaults: ```java -Logbook logbook=Logbook.create(); +Logbook logbook = Logbook.create(); ``` - or create a customized version using the `LogbookBuilder`: ```java -Logbook logbook=Logbook.builder() - .condition(new CustomCondition()) - .queryFilter(new CustomQueryFilter()) - .pathFilter(new CustomPathFilter()) - .headerFilter(new CustomHeaderFilter()) - .bodyFilter(new CustomBodyFilter()) - .requestFilter(new CustomRequestFilter()) - .responseFilter(new CustomResponseFilter()) - .sink(new DefaultSink( - new CustomHttpLogFormatter(), - new CustomHttpLogWriter() - )) - .build(); +Logbook logbook = Logbook.builder() + .condition(new CustomCondition()) + .queryFilter(new CustomQueryFilter()) + .pathFilter(new CustomPathFilter()) + .headerFilter(new CustomHeaderFilter()) + .bodyFilter(new CustomBodyFilter()) + .requestFilter(new CustomRequestFilter()) + .responseFilter(new CustomResponseFilter()) + .sink(new DefaultSink( + new CustomHttpLogFormatter(), + new CustomHttpLogWriter() + )) + .build(); ``` ### Strategy @@ -207,8 +196,7 @@ Some of those restrictions could be mitigated with custom [`HttpLogWriter`](#wri implementations, but they were never ideal. Starting with version 2.0 Logbook now comes with a [Strategy pattern](https://en.wikipedia.org/wiki/Strategy_pattern) -at its core. Make sure you read the documentation of -the [`Strategy`](logbook-api/src/main/java/org/zalando/logbook/Strategy.java) +at its core. Make sure you read the documentation of the [`Strategy`](logbook-api/src/main/java/org/zalando/logbook/Strategy.java) interface to understand the implications. Logbook comes with some built-in strategies: @@ -218,7 +206,6 @@ Logbook comes with some built-in strategies: - [`WithoutBodyStrategy`](logbook-core/src/main/java/org/zalando/logbook/core/WithoutBodyStrategy.java) ### Attribute Extractor - Starting with version 3.4.0, Logbook is equipped with a feature called *Attribute Extractor*. Attributes are basically a list of key/value pairs that can be extracted from request and/or response, and logged with them. The idea was sprouted from [issue 381](https://github.com/zalando/logbook/issues/381), where a feature was requested to extract the subject @@ -226,9 +213,9 @@ claim from JWT tokens in the authorization header. The `AttributeExtractor` interface has two `extract` methods: One that can extract attributes from the request only, and one that has both request and response at its avail. The both return an instance of the `HttpAttributes` class, which is -basically a fancy `Map`. Notice that since the map values are of type `Object`, they should have a -proper `toString()` method in order for them to appear in the logs in a meaningful way. Alternatively, log formatters -can work around this by implementing their own serialization logic. For instance, the built-in log formatter +basically a fancy `Map`. Notice that since the map values are of type `Object`, they should have a +proper `toString()` method in order for them to appear in the logs in a meaningful way. Alternatively, log formatters +can work around this by implementing their own serialization logic. For instance, the built-in log formatter `JsonHttpLogFormatter` uses `ObjectMapper` to serialize the values. Here is an example: @@ -236,24 +223,23 @@ Here is an example: ```java final class OriginExtractor implements AttributeExtractor { - @Override - public HttpAttributes extract(final HttpRequest request) { - return HttpAttributes.of("origin", request.getOrigin()); - } - + @Override + public HttpAttributes extract(final HttpRequest request) { + return HttpAttributes.of("origin", request.getOrigin()); + } + } ``` Logbook must then be created by registering this attribute extractor: ```java -final Logbook logbook=Logbook.builder() +final Logbook logbook = Logbook.builder() .attributeExtractor(new OriginExtractor()) .build(); ``` This will result in request logs to include something like: - ```text "attributes":{"origin":"LOCAL"} ``` @@ -265,13 +251,13 @@ The latter extracts all claims matching a list of claim names from the request J If you require to incorporate multiple `AttributeExtractor`s, you can use the class `CompositeAttributeExtractor`: ```java -final List extractors=List.of( - extractor1, - extractor2, - extractor3 - ); +final List extractors = List.of( + extractor1, + extractor2, + extractor3 +); -final Logbook logbook=Logbook.builder() +final Logbook logbook = Logbook.builder() .attributeExtractor(new CompositeAttributeExtractor(extractors)) .build(); ``` @@ -285,31 +271,27 @@ Logbook works in several different phases: 3. [Formatting](#formatting) and 4. [Writing](#writing) -Each phase is represented by one or more interfaces that can be used for customization. Every phase has a sensible -default. +Each phase is represented by one or more interfaces that can be used for customization. Every phase has a sensible default. #### Conditional -Logging HTTP messages and including their bodies is a rather expensive task, so it makes a lot of sense to disable -logging for certain requests. A common use case would be to ignore *health check* +Logging HTTP messages and including their bodies is a rather expensive task, so it makes a lot of sense to disable logging for certain requests. A common use case would be to ignore *health check* requests from a load balancer, or any request to management endpoints typically issued by developers. -Defining a condition is as easy as writing a special `Predicate` that decides whether a request (and its corresponding -response) should be logged or not. Alternatively you can use and combine +Defining a condition is as easy as writing a special `Predicate` that decides whether a request (and its corresponding response) should be logged or not. Alternatively you can use and combine predefined predicates: ```java -Logbook logbook=Logbook.builder() - .condition(exclude( +Logbook logbook = Logbook.builder() + .condition(exclude( requestTo("/health"), requestTo("/admin/**"), contentType("application/octet-stream"), - header("X-Secret",newHashSet("1","true")::contains))) - .build(); + header("X-Secret", newHashSet("1", "true")::contains))) + .build(); ``` -Exclusion patterns, e.g. `/admin/**`, are loosely -following [Ant's style of path patterns](https://ant.apache.org/manual/dirtasks.html#patterns) +Exclusion patterns, e.g. `/admin/**`, are loosely following [Ant's style of path patterns](https://ant.apache.org/manual/dirtasks.html#patterns) without taking the the query string of the URL into consideration. #### Filtering @@ -329,10 +311,8 @@ Logbook supports different types of filters: | `RequestFilter` | `HttpRequest` | request | Replace binary, multipart and stream bodies. | | `ResponseFilter` | `HttpResponse` | response | Replace binary, multipart and stream bodies. | -`QueryFilter`, `PathFilter`, `HeaderFilter` and `BodyFilter` are relatively high-level and should cover all needs in ~ -90% of all -cases. For more complicated setups one should fallback to the low-level variants, i.e. `RequestFilter` -and `ResponseFilter` +`QueryFilter`, `PathFilter`, `HeaderFilter` and `BodyFilter` are relatively high-level and should cover all needs in ~90% of all +cases. For more complicated setups one should fallback to the low-level variants, i.e. `RequestFilter` and `ResponseFilter` respectively (in conjunction with `ForwardingHttpRequest`/`ForwardingHttpResponse`). You can configure filters like this: @@ -343,13 +323,13 @@ import static org.zalando.logbook.core.HeaderFilters.eachHeader; import static org.zalando.logbook.core.QueryFilters.accessToken; import static org.zalando.logbook.core.QueryFilters.replaceQuery; -Logbook logbook=Logbook.builder() - .requestFilter(RequestFilters.replaceBody(message->contentType("audio/*").test(message)?"mmh mmh mmh mmh":null)) - .responseFilter(ResponseFilters.replaceBody(message->contentType("*/*-stream").test(message)?"It just keeps going and going...":null)) +Logbook logbook = Logbook.builder() + .requestFilter(RequestFilters.replaceBody(message -> contentType("audio/*").test(message) ? "mmh mmh mmh mmh" : null)) + .responseFilter(ResponseFilters.replaceBody(message -> contentType("*/*-stream").test(message) ? "It just keeps going and going..." : null)) .queryFilter(accessToken()) - .queryFilter(replaceQuery("password","")) + .queryFilter(replaceQuery("password", "")) .headerFilter(authorization()) - .headerFilter(eachHeader("X-Secret"::equalsIgnoreCase,"")) + .headerFilter(eachHeader("X-Secret"::equalsIgnoreCase, "")) .build(); ``` @@ -364,12 +344,12 @@ Here are some examples: import static org.zalando.logbook.json.JsonPathBodyFilters.jsonPath; import static java.util.regex.Pattern.compile; -Logbook logbook=Logbook.builder() +Logbook logbook = Logbook.builder() .bodyFilter(jsonPath("$.password").delete()) .bodyFilter(jsonPath("$.active").replace("unknown")) .bodyFilter(jsonPath("$.address").replace("X")) - .bodyFilter(jsonPath("$.name").replace(compile("^(\\w).+"),"$1.")) - .bodyFilter(jsonPath("$.friends.*.name").replace(compile("^(\\w).+"),"$1.")) + .bodyFilter(jsonPath("$.name").replace(compile("^(\\w).+"), "$1.")) + .bodyFilter(jsonPath("$.friends.*.name").replace(compile("^(\\w).+"), "$1.")) .bodyFilter(jsonPath("$.grades.*").replace(1.0)) .build(); ``` @@ -404,7 +384,6 @@ Take a look at the following example, before and after filtering was applied: } } ``` -
@@ -434,34 +413,29 @@ Take a look at the following example, before and after filtering was applied: } } ``` -
#### Correlation -Logbook uses a *correlation id* to correlate requests and responses. This allows match-related requests and responses -that would usually be located in different places in the log file. +Logbook uses a *correlation id* to correlate requests and responses. This allows match-related requests and responses that would usually be located in different places in the log file. -If the default implementation of the correlation id is insufficient for your use case, you may provide a custom -implementation: +If the default implementation of the correlation id is insufficient for your use case, you may provide a custom implementation: ```java -Logbook logbook=Logbook.builder() - .correlationId(new CustomCorrelationId()) - .build(); +Logbook logbook = Logbook.builder() + .correlationId(new CustomCorrelationId()) + .build(); ``` #### Formatting -*Formatting* defines how requests and responses will be transformed to strings basically. Formatters do **not** specify -where requests and responses are logged to — writers do that work. +*Formatting* defines how requests and responses will be transformed to strings basically. Formatters do **not** specify where requests and responses are logged to — writers do that work. Logbook comes with two different default formatters: *HTTP* and *JSON*. ##### HTTP -*HTTP* is the default formatting style, provided by the `DefaultHttpLogFormatter`. It is primarily designed to be used -for local development and debugging, not for production use. This is because it’s +*HTTP* is the default formatting style, provided by the `DefaultHttpLogFormatter`. It is primarily designed to be used for local development and debugging, not for production use. This is because it’s not as readily machine-readable as JSON. ###### Request @@ -489,16 +463,14 @@ Content-Type: application/json ##### JSON -*JSON* is an alternative formatting style, provided by the `JsonHttpLogFormatter`. Unlike HTTP, it is primarily designed -for production use — parsers and log consumers can easily consume it. +*JSON* is an alternative formatting style, provided by the `JsonHttpLogFormatter`. Unlike HTTP, it is primarily designed for production use — parsers and log consumers can easily consume it. Requires the following dependency: ```xml - - org.zalando - logbook-json + org.zalando + logbook-json ``` @@ -518,12 +490,8 @@ Requires the following dependency: "scheme": "http", "port": null, "headers": { - "Accept": [ - "application/json" - ], - "Content-Type": [ - "text/plain" - ] + "Accept": ["application/json"], + "Content-Type": ["text/plain"] }, "body": "Hello world!" } @@ -540,9 +508,7 @@ Requires the following dependency: "protocol": "HTTP/1.1", "status": 200, "headers": { - "Content-Type": [ - "text/plain" - ] + "Content-Type": ["text/plain"] }, "body": "Hello world!" } @@ -560,9 +526,7 @@ a JSON response body will **not** be escaped and represented as a string: "protocol": "HTTP/1.1", "status": 200, "headers": { - "Content-Type": [ - "application/json" - ] + "Content-Type": ["application/json"] }, "body": { "greeting": "Hello, world!" @@ -572,8 +536,7 @@ a JSON response body will **not** be escaped and represented as a string: ##### Common Log Format -The Common Log Format ([CLF](https://httpd.apache.org/docs/trunk/logs.html#common)) is a standardized text file format -used by web servers when generating server log files. The format is supported via +The Common Log Format ([CLF](https://httpd.apache.org/docs/trunk/logs.html#common)) is a standardized text file format used by web servers when generating server log files. The format is supported via the `CommonsLogFormatSink`: ```text @@ -582,8 +545,7 @@ the `CommonsLogFormatSink`: ##### Extended Log Format -The Extended Log Format ([ELF](https://en.wikipedia.org/wiki/Extended_Log_Format)) is a standardised text file format, -like Common Log Format (CLF), that is used by web servers when generating log +The Extended Log Format ([ELF](https://en.wikipedia.org/wiki/Extended_Log_Format)) is a standardised text file format, like Common Log Format (CLF), that is used by web servers when generating log files, but ELF files provide more information and flexibility. The format is supported via the `ExtendedLogFormatSink`. Also see [W3C](https://www.w3.org/TR/WD-logfile.html) document. @@ -605,11 +567,9 @@ Users may override default fields with their custom fields through the construct new ExtendedLogFormatSink(new DefaultHttpLogWriter(),"date time cs(Custom-Request-Header) sc(Custom-Response-Header)") ``` -For Http header fields: `cs(Any-Header)` and `sc(Any-Header)`, users could specify any headers they want to extract from -the request. +For Http header fields: `cs(Any-Header)` and `sc(Any-Header)`, users could specify any headers they want to extract from the request. -Other supported fields are listed in the value of `ExtendedLogFormatSink.Field`, which can be put in the custom field -expression. +Other supported fields are listed in the value of `ExtendedLogFormatSink.Field`, which can be put in the custom field expression. ##### cURL @@ -659,38 +619,36 @@ By default, requests and responses are logged with an *slf4j* logger that uses t category and the log level `trace`. This can be customized: ```java -Logbook logbook=Logbook.builder() - .sink(new DefaultSink( - new DefaultHttpLogFormatter(), - new DefaultHttpLogWriter() - )) - .build(); +Logbook logbook = Logbook.builder() + .sink(new DefaultSink( + new DefaultHttpLogFormatter(), + new DefaultHttpLogWriter() + )) + .build(); ``` ##### Stream -An alternative implementation is to log requests and responses to a `PrintStream`, e.g. `System.out` or `System.err`. -This is usually a bad choice for running in production, but can sometimes be +An alternative implementation is to log requests and responses to a `PrintStream`, e.g. `System.out` or `System.err`. This is usually a bad choice for running in production, but can sometimes be useful for short-term local development and/or investigation. ```java -Logbook logbook=Logbook.builder() - .sink(new DefaultSink( - new DefaultHttpLogFormatter(), - new StreamHttpLogWriter(System.err) - )) - .build(); +Logbook logbook = Logbook.builder() + .sink(new DefaultSink( + new DefaultHttpLogFormatter(), + new StreamHttpLogWriter(System.err) + )) + .build(); ``` ##### Chunking -The `ChunkingSink` will split long messages into smaller chunks and will write them individually while delegating to -another sink: +The `ChunkingSink` will split long messages into smaller chunks and will write them individually while delegating to another sink: ```java -Logbook logbook=Logbook.builder() - .sink(new ChunkingSink(sink,1000)) - .build(); +Logbook logbook = Logbook.builder() + .sink(new ChunkingSink(sink, 1000)) + .build(); ``` @@ -704,28 +662,26 @@ Multiple sinks can be combined into one using the `CompositeSink`. ### Servlet -You’ll have to register the `LogbookFilter` as a `Filter` in your filter chain — either in your `web.xml` file (please -note that the xml approach will use all the defaults and is not configurable): +You’ll have to register the `LogbookFilter` as a `Filter` in your filter chain — either in your `web.xml` file (please note that the xml approach will use all the defaults and is not configurable): ```xml - LogbookFilter org.zalando.logbook.servlet.LogbookFilter -LogbookFilter -/* -REQUEST -ASYNC + LogbookFilter + /* + REQUEST + ASYNC ``` or programmatically, via the `ServletContext`: ```java -context.addFilter("LogbookFilter",new LogbookFilter(logbook)) - .addMappingForUrlPatterns(EnumSet.of(REQUEST,ASYNC),true,"/*"); +context.addFilter("LogbookFilter", new LogbookFilter(logbook)) + .addMappingForUrlPatterns(EnumSet.of(REQUEST, ASYNC), true, "/*"); ``` **Beware**: The `ERROR` dispatch is not supported. You're strongly advised to produce error responses within the @@ -749,88 +705,77 @@ using the `logbook.servlet.form-request` system property: #### Security -Secure applications usually need a slightly different setup. You should generally avoid logging unauthorized requests, -especially the body, because it quickly allows attackers to flood your logfile — -and, consequently, your precious disk space. Assuming that your application handles authorization inside another filter, -you have two choices: +Secure applications usually need a slightly different setup. You should generally avoid logging unauthorized requests, especially the body, because it quickly allows attackers to flood your logfile — +and, consequently, your precious disk space. Assuming that your application handles authorization inside another filter, you have two choices: - Don't log unauthorized requests - Log unauthorized requests without the request body -You can easily achieve the former setup by placing the `LogbookFilter` after your security filter. The latter is a -little bit more sophisticated. You’ll need two `LogbookFilter` instances — one before +You can easily achieve the former setup by placing the `LogbookFilter` after your security filter. The latter is a little bit more sophisticated. You’ll need two `LogbookFilter` instances — one before your security filter, and one after it: ```java -context.addFilter("SecureLogbookFilter",new SecureLogbookFilter(logbook)) - .addMappingForUrlPatterns(EnumSet.of(REQUEST,ASYNC),true,"/*"); - context.addFilter("securityFilter",new SecurityFilter()) - .addMappingForUrlPatterns(EnumSet.of(REQUEST),true,"/*"); - context.addFilter("LogbookFilter",new LogbookFilter(logbook)) - .addMappingForUrlPatterns(EnumSet.of(REQUEST,ASYNC),true,"/*"); +context.addFilter("SecureLogbookFilter", new SecureLogbookFilter(logbook)) + .addMappingForUrlPatterns(EnumSet.of(REQUEST, ASYNC), true, "/*"); +context.addFilter("securityFilter", new SecurityFilter()) + .addMappingForUrlPatterns(EnumSet.of(REQUEST), true, "/*"); +context.addFilter("LogbookFilter", new LogbookFilter(logbook)) + .addMappingForUrlPatterns(EnumSet.of(REQUEST, ASYNC), true, "/*"); ``` -The first logbook filter will log unauthorized requests **only**. The second filter will log authorized requests, as -always. +The first logbook filter will log unauthorized requests **only**. The second filter will log authorized requests, as always. ### HTTP Client -The `logbook-httpclient` module contains both an `HttpRequestInterceptor` and an `HttpResponseInterceptor` to use with -the `HttpClient`: +The `logbook-httpclient` module contains both an `HttpRequestInterceptor` and an `HttpResponseInterceptor` to use with the `HttpClient`: ```java -CloseableHttpClient client=HttpClientBuilder.create() +CloseableHttpClient client = HttpClientBuilder.create() .addInterceptorFirst(new LogbookHttpRequestInterceptor(logbook)) .addInterceptorFirst(new LogbookHttpResponseInterceptor()) .build(); ``` -Since the `LogbookHttpResponseInterceptor` is incompatible with the `HttpAsyncClient` there is another way to log -responses: +Since the `LogbookHttpResponseInterceptor` is incompatible with the `HttpAsyncClient` there is another way to log responses: ```java -CloseableHttpAsyncClient client=HttpAsyncClientBuilder.create() +CloseableHttpAsyncClient client = HttpAsyncClientBuilder.create() .addInterceptorFirst(new LogbookHttpRequestInterceptor(logbook)) .build(); - + // and then wrap your response consumer - client.execute(producer,new LogbookHttpAsyncResponseConsumer<>(consumer),callback) +client.execute(producer, new LogbookHttpAsyncResponseConsumer<>(consumer), callback) ``` ### HTTP Client 5 The `logbook-httpclient5` module contains an `ExecHandler` to use with the `HttpClient`: - ```java -CloseableHttpClient client=HttpClientBuilder.create() - .addExecInterceptorFirst("Logbook",new LogbookHttpExecHandler(logbook)) +CloseableHttpClient client = HttpClientBuilder.create() + .addExecInterceptorFirst("Logbook", new LogbookHttpExecHandler(logbook)) .build(); ``` +The Handler should be added first, such that a compression is performed after logging and decompression is performed before logging. -The Handler should be added first, such that a compression is performed after logging and decompression is performed -before logging. - -To avoid a breaking change, there is also an `HttpRequestInterceptor` and an `HttpResponseInterceptor` to use with -the `HttpClient`, which works fine as long as compression (or other ExecHandlers) is +To avoid a breaking change, there is also an `HttpRequestInterceptor` and an `HttpResponseInterceptor` to use with the `HttpClient`, which works fine as long as compression (or other ExecHandlers) is not used: ```java -CloseableHttpClient client=HttpClientBuilder.create() +CloseableHttpClient client = HttpClientBuilder.create() .addRequestInterceptorFirst(new LogbookHttpRequestInterceptor(logbook)) .addResponseInterceptorFirst(new LogbookHttpResponseInterceptor()) .build(); ``` -Since the `LogbookHttpResponseInterceptor` is incompatible with the `HttpAsyncClient` there is another way to log -responses: +Since the `LogbookHttpResponseInterceptor` is incompatible with the `HttpAsyncClient` there is another way to log responses: ```java -CloseableHttpAsyncClient client=HttpAsyncClientBuilder.create() +CloseableHttpAsyncClient client = HttpAsyncClientBuilder.create() .addRequestInterceptorFirst(new LogbookHttpRequestInterceptor(logbook)) .build(); - + // and then wrap your response consumer - client.execute(producer,new LogbookHttpAsyncResponseConsumer<>(consumer),callback) +client.execute(producer, new LogbookHttpAsyncResponseConsumer<>(consumer), callback) ``` ### JAX-RS 2.x and 3.x (aka Jakarta RESTful Web Services) @@ -893,21 +838,21 @@ The `logbook-netty` module contains: A `LogbookClientHandler` to be used with an `HttpClient`: ```java -HttpClient httpClient= +HttpClient httpClient = HttpClient.create() - .doOnConnected( - (connection->connection.addHandlerLast(new LogbookClientHandler(logbook))) - ); + .doOnConnected( + (connection -> connection.addHandlerLast(new LogbookClientHandler(logbook))) + ); ``` A `LogbookServerHandler` for use used with an `HttpServer`: ```java -HttpServer httpServer= +HttpServer httpServer = HttpServer.create() - .doOnConnection( - connection->connection.addHandlerLast(new LogbookServerHandler(logbook)) - ); + .doOnConnection( + connection -> connection.addHandlerLast(new LogbookServerHandler(logbook)) + ); ``` #### Spring WebFlux @@ -922,20 +867,17 @@ Users of Spring WebFlux can pick any of the following options: #### Micronaut -Users of Micronaut can follow -the [official docs](https://docs.micronaut.io/snapshot/guide/index.html#nettyClientPipeline) on how to integrate Logbook -with Micronaut. +Users of Micronaut can follow the [official docs](https://docs.micronaut.io/snapshot/guide/index.html#nettyClientPipeline) on how to integrate Logbook with Micronaut. -:warning: Even though Quarkus and Vert.x use Netty under the hood, unfortunately neither of them allows accessing or -customizing it (yet). +:warning: Even though Quarkus and Vert.x use Netty under the hood, unfortunately neither of them allows accessing or customizing it (yet). ### OkHttp v2.x The `logbook-okhttp2` module contains an `Interceptor` to use with version 2.x of the `OkHttpClient`: ```java -OkHttpClient client=new OkHttpClient(); - client.networkInterceptors().add(new LogbookInterceptor(logbook)); +OkHttpClient client = new OkHttpClient(); +client.networkInterceptors().add(new LogbookInterceptor(logbook)); ``` If you're expecting gzip-compressed responses you need to register our `GzipInterceptor` in addition. @@ -943,9 +885,9 @@ The transparent gzip support built into OkHttp will run after any network interc logbook to log compressed binary responses. ```java -OkHttpClient client=new OkHttpClient(); - client.networkInterceptors().add(new LogbookInterceptor(logbook)); - client.networkInterceptors().add(new GzipInterceptor()); +OkHttpClient client = new OkHttpClient(); +client.networkInterceptors().add(new LogbookInterceptor(logbook)); +client.networkInterceptors().add(new GzipInterceptor()); ``` ### OkHttp v3.x @@ -953,7 +895,7 @@ OkHttpClient client=new OkHttpClient(); The `logbook-okhttp` module contains an `Interceptor` to use with version 3.x of the `OkHttpClient`: ```java -OkHttpClient client=new OkHttpClient.Builder() +OkHttpClient client = new OkHttpClient.Builder() .addNetworkInterceptor(new LogbookInterceptor(logbook)) .build(); ``` @@ -963,7 +905,7 @@ The transparent gzip support built into OkHttp will run after any network interc logbook to log compressed binary responses. ```java -OkHttpClient client=new OkHttpClient.Builder() +OkHttpClient client = new OkHttpClient.Builder() .addNetworkInterceptor(new LogbookInterceptor(logbook)) .addNetworkInterceptor(new GzipInterceptor()) .build(); @@ -998,19 +940,17 @@ private val server = embeddedServer(CIO) { Alternatively, you can use `logbook-ktor`, which ships both `logbook-ktor-client` and `logbook-ktor-server` modules. ### Spring - The `logbook-spring` module contains a `ClientHttpRequestInterceptor` to use with `RestTemplate`: ```java - LogbookClientHttpRequestInterceptor interceptor=new LogbookClientHttpRequestInterceptor(logbook); - RestTemplate restTemplate=new RestTemplate(); - restTemplate.getInterceptors().add(interceptor); + LogbookClientHttpRequestInterceptor interceptor = new LogbookClientHttpRequestInterceptor(logbook); + RestTemplate restTemplate = new RestTemplate(); + restTemplate.getInterceptors().add(interceptor); ``` ### Spring Boot Starter -Logbook comes with a convenient auto configuration for Spring Boot users. It sets up all of the following parts -automatically with sensible defaults: +Logbook comes with a convenient auto configuration for Spring Boot users. It sets up all of the following parts automatically with sensible defaults: - Servlet filter - Second Servlet filter for unauthorized requests (if Spring Security is detected) @@ -1021,7 +961,6 @@ automatically with sensible defaults: Instead of declaring a dependency to `logbook-core` declare one to the Spring Boot Starter: ```xml - org.zalando logbook-spring-boot-starter @@ -1033,15 +972,14 @@ Every bean can be overridden and customized if needed, e.g. like this: ```java @Bean -public BodyFilter bodyFilter(){ - return merge( - defaultValue(), - replaceJsonStringProperty(singleton("secret"),"XXX")); - } +public BodyFilter bodyFilter() { + return merge( + defaultValue(), + replaceJsonStringProperty(singleton("secret"), "XXX")); +} ``` -Please refer -to [`LogbookAutoConfiguration`](logbook-spring-boot-autoconfigure/src/main/java/org/zalando/logbook/autoconfigure/LogbookAutoConfiguration.java) +Please refer to [`LogbookAutoConfiguration`](logbook-spring-boot-autoconfigure/src/main/java/org/zalando/logbook/autoconfigure/LogbookAutoConfiguration.java) or the following table to see a list of possible integration points: | Type | Name | Default | @@ -1065,18 +1003,16 @@ or the following table to see a list of possible integration points: Multiple filters are merged into one. #### Autoconfigured beans from `logbook-spring` - Some classes from `logbook-spring` are included in the auto configuration. You can autowire `LogbookClientHttpRequestInterceptor` with code like: - ```java private final RestTemplate restTemplate; - MyClient(RestTemplateBuilder builder,LogbookClientHttpRequestInterceptor interceptor){ - this.restTemplate=builder - .additionalInterceptors(interceptor) - .build(); - } +MyClient(RestTemplateBuilder builder, LogbookClientHttpRequestInterceptor interceptor){ + this.restTemplate = builder + .additionalInterceptors(interceptor) + .build(); +} ``` #### Configuration @@ -1111,15 +1047,15 @@ logbook: predicate: include: - path: /api/** - methods: - - GET - - POST + methods: + - GET + - POST - path: /actuator/** exclude: - path: /actuator/health - path: /api/admin/** - methods: - - POST + methods: + - POST filter.enabled: true secure-filter.enabled: true format.style: http @@ -1178,15 +1114,12 @@ for outputs like ## Known Issues -1. The Logbook Servlet Filter interferes with downstream code using `getWriter` and/or `getParameter*()`. - See [Servlet](#servlet) for more details. -2. The Logbook Servlet Filter does **NOT** support `ERROR` dispatch. You're strongly encouraged to not use it to produce - error responses. +1. The Logbook Servlet Filter interferes with downstream code using `getWriter` and/or `getParameter*()`. See [Servlet](#servlet) for more details. +2. The Logbook Servlet Filter does **NOT** support `ERROR` dispatch. You're strongly encouraged to not use it to produce error responses. ## Getting Help with Logbook -If you have questions, concerns, bug reports, etc., please file an issue in this -repository's [Issue Tracker](https://github.com/zalando/logbook/issues). +If you have questions, concerns, bug reports, etc., please file an issue in this repository's [Issue Tracker](https://github.com/zalando/logbook/issues). ## Getting Involved/Contributing @@ -1216,7 +1149,6 @@ more details, check the [contribution guidelines](.github/CONTRIBUTING.md). ## Credits and References ![Creative Commons (Attribution-Share Alike 3.0 Unported](https://licensebuttons.net/l/by-sa/3.0/80x15.png) -[*Grand Turk, a replica of a three-masted 6th rate frigate from Nelson's days - logbook and -charts*](https://commons.wikimedia.org/wiki/File:Grand_Turk(34).jpg) +[*Grand Turk, a replica of a three-masted 6th rate frigate from Nelson's days - logbook and charts*](https://commons.wikimedia.org/wiki/File:Grand_Turk(34).jpg) by [JoJan](https://commons.wikimedia.org/wiki/User:JoJan) is licensed under a [Creative Commons (Attribution-Share Alike 3.0 Unported)](http://creativecommons.org/licenses/by-sa/3.0/).