Java log http headers

Reading HTTP Headers in Spring REST Controller

A quick guide on How to Read HTTP Headers in Spring REST Controller.

Overview

This tutorial explains How to read HTTP Headers in a Spring Controller. First, we will have a brief of Spring @ResquestHeader annotation that maps all headers or a specific header into controller method arguments. Next, we will explore various ways to bind request HTTP Headers in a Spring Controller. Lastly, we will cover how to use the HttpServletRequest instance to read the header values in the Spring REST Controller.

Reading HTTP Headers using @RequestHeader

Spring provides @RequestHeader annotation that maps all or a particular header values to an argument of a controller method. The type of @RequestHeader annotation is ‘parameter’. Thus we can add it directly to a controller method argument.

@RequestHeader Annotation

@Target() @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestHeader < @AliasFor("name") String value() default ""; @AliasFor("value") String name() default ""; boolean required() default true; String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n"; >Code language: Java (java)

The data type of the header value and the controller method argument must match, or they must be compatible.

Reading HTTP Headers as Java HashMap

In the following example, we read all HTTP headers in a HashMap. We use @RequestHeader annotation to map all HTTP headers into the Java Map instance.

@PostMapping("v1/students") public void postStudent( @RequestHeader Map headers, @RequestBody Student student) < log.info("Header values: <>", headers); >Code language: Java (java)
curl -L -X POST 'http://localhost:8080/v1/students' \ -H 'Content-Type: application/json' \ --data-raw '< "id" : "123" >' -- Header values: 

Reading HTTP Headers as HTTPHeaders Instance

Alternatively, we can inject the HTTP Headers into an instance of HttpHeaders class. The HttpHeaders is an implementation of a MultiValueMap class.

Читайте также:  Python pip list installed packages

Next is an example of reading HTTP Header values in the HttpHeader instance.

@PostMapping("/v2/students") public void postStudent( @RequestHeader HttpHeaders headers, @RequestBody Student student) < log.info("Header values: <>", headers); >Code language: Java (java)
curl -L -X POST 'http://localhost:8080/v2/students' \ -H 'Content-Type: application/json' \ --data-raw '< "id" : "123" >' -- Header values: [host:"localhost:8080", user-agent:"curl/7.64.1", accept:"*/*", content-type:"application/json", content-length:"20"]

Reading HTTP Headers as Java MultiValueMap

While mapping HttpHeader values to a Map, Spring only maps the first value of the key into the Map. However, if a header key has more than one value, to read all values, we can use the MultiValueMap.

Example of Reading HttpHeaders to MultiValueMap in Spring REST Controller.

@PostMapping("/v3/students") public void postStudent( @RequestHeader MultiValueMap headers, @RequestBody Student student) < log.info("Header values: <>", headers); >Code language: Java (java)
curl -L -X POST 'http://localhost:8080/v3/students' \ -H 'Content-Type: application/json' \ --data-raw '< "id" : "123" >' -- Header values: 

Reading Specific HTTP Headers using @RequestHeader

We can also read only a specific header using @RequestHeader by providing the header key as an annotation value.

Example of Reading a specific header in Spring REST Controller.

@PostMapping("/v4/students") public void postStudent( @RequestHeader("content-type") String contentType, @RequestBody Student student) < log.info("Header value - Content-Type: <>", contentType); >Code language: Java (java)
curl -L -X POST 'http://localhost:8080/v4/students' \ -H 'Content-Type: application/json' \ --data-raw '< "id" : "123" >' -- Header value - Content-Type: application/json

Spring treats it as a mandatory header if a particular header is mapped into the Controller method argument. Thus, Spring returns an HTTP status code of 400 (Bad Request) if the mapped header is not present in the request.

To make the header optional, we can use the required attribute of @RequestHeader annotation.

@PostMapping("/v4/students") public void postStudent( @RequestHeader( value = "content-type", required = false) String contentType, @RequestBody Student student) < log.info("Header value - Content-Type: <>", contentType); >Code language: Java (java)

Next is an example of setting a default header value if a particular header is not present in the request. To set a default value, we can use the defaultValue attribute of the @RequestHeader annotation.

@PostMapping("/v4/students") public void postStudent( @RequestHeader( value = "content-type", defaultValue = "application/json") String contentType, @RequestBody Student student) < log.info("Header value - Content-Type: <>", contentType); >Code language: Java (java)

Make a note that Spring injects the default value only if the original header is missing or is Null.

Reading HTTP Headers using HttpServletRequest

Alternatively, we can also read request header values directly from the HTTPServletRequest instance.

To access the HttpServletRequest instance in a Spring REST Controller, we need to add it as a method argument.

Next is an example of Reading all header values in Spring REST Controller, using HttpServletRequest.

@PostMapping("/v5/students") public void postStudent( HttpServletRequest request, @RequestBody Student student)  < EnumerationheaderNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) < String key = headerNames.nextElement(); log.info(key + ": " + request.getHeader(key)); > >Code language: Java (java)
curl -L -X POST 'http://localhost:8080/v5/students' \ -H 'Content-Type: application/json' \ --data-raw '< "id" : "123" >' -- host: localhost:8080 user-agent: curl/7.64.1 accept: */* content-type: application/json content-length: 20

Summary

This tutorial talked about How to read HTTP Headers in Spring REST Controllers. We learned that using @RequestHeader annotation, we can map all headers or a particular header into an argument of the controller method. Also, we covered how to make a header values optional or provide a default value for a missing header. Lastly, we learned how to use HttpServletRequest and read headers manually.

You can refer to our Github Repository for the complete source code of the examples used in this tutorial.

Источник

Logging Practices

ApacheCon

Being a library HttpClient is not to dictate which logging framework the user has to use. Therefore HttpClient utilizes the logging interface provided by the Commons Logging package. Commons Logging provides a simple and generalized log interface to various logging packages. By using Commons Logging , HttpClient can be configured for a variety of different logging behaviours. That means the user will have to make a choice which logging framework to use. By default Commons Logging supports the following logging frameworks:

By implementing some simple interfaces Commons Logging can be extended to support basically any other custom logging framework. Commons Logging tries to automatically discover the logging framework to use. If it fails to select the expected one, you must configure Commons Logging by hand. Please refer to the Commons Logging documentation for more information.

HttpClient performs three different kinds of logging: the standard context logging used within each class, HTTP header logging and full wire logging.

Context Logging

Context logging contains information about the internal operation of HttpClient as it performs HTTP requests. Each class has its own log named according to the class’s fully qualified name. For example the class DefaultHttpClient has a log named org.apache.http.impl.client.DefaultHttpClient . Since all classes follow this convention it is possible to configure context logging for all classes using the single log named org.apache.http.impl.client .

Wire Logging

The wire log is used to log all data transmitted to and from servers when executing HTTP requests. The wire log uses the org.apache.http.wire logging category. This log should only be enabled to debug problems, as it will produce an extremely large amount of log data.

HTTP header Logging

Because the content of HTTP requests is usually less important for debugging than the HTTP headers, the org.apache.http.headers logging category for capturing HTTP headers only.

Configuration Examples

Commons Logging can delegate to a variety of loggers for processing the actual output. Below are configuration examples for Commons Logging , Log4j 2 and java.util.logging .

Commons Logging Examples

Commons Logging comes with a basic logger called SimpleLog . This logger writes all logged messages to System.err . The following examples show how to configure Commons Logging via system properties to use SimpleLog . It is strongly recommended configuring Commons Logging system properties through JVM process arguments at the start up.

    Enable header wire + context logging — «Best for Debugging»

-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG -Dorg.apache.commons.logging.simplelog.log.org.apache.http.wire=ERROR 
-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG 
-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.org.apache.http.impl.conn=DEBUG 
-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.org.apache.http.impl.conn=DEBUG -Dorg.apache.commons.logging.simplelog.log.org.apache.http.impl.client=DEBUG -Dorg.apache.commons.logging.simplelog.log.org.apache.http.client=DEBUG 

Log4j 2 Examples

The simplest way to configure Log4j 2 is via a log4j2.xml file. Log4j 2 will automatically configure itself using a file named log4j2.xml when it’s present at the root of the application classpath.

Below are some Log4j configuration examples.

Note: The Log4j 2 implementation a.k.a “core” is not included in the HttpClient distribution. You can include it in your project using Maven, Ivy, Gradle, or SBT.

    Enable header wire + context logging — Best for Debugging

The Log4J 2 manual is the best reference for how to configure Log4J 2 . It is available at https://logging.apache.org/log4j/2.x/manual/.

java.util.logging Examples

Since JDK 1.4 there has been a package java.util.logging that provides a logging framework similar to Log4J . By default it reads a config file from $JAVA_HOME/jre/lib/logging.properties which looks like this (comments stripped):

handlers=java.util.logging.ConsoleHandler .level=INFO java.util.logging.FileHandler.pattern = %h/java%u.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.count = 1 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter java.util.logging.ConsoleHandler.level = INFO java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter com.xyz.foo.level = SEVERE 

To customize logging a custom logging.properties file should be created in the project directory. The location of this file must be passed to the JVM as a system property. This can be done on the command line like so:

$JAVA_HOME/java -Djava.util.logging.config.file=$HOME/myapp/logging.properties -classpath $HOME/myapp/target/classes com.myapp.Main 

Alternatively LogManager#readConfiguration(InputStream) can be used to pass it the desired configuration.

    Enable header wire + context logging — Best for Debugging

.level = INFO handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.level = ALL org.apache.http.level = FINEST org.apache.http.wire.level = SEVERE 
.level = INFO handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.level = ALL org.apache.http.level = FINEST 
.level = INFO handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.level = ALL org.apache.http.impl.conn.level = FINEST 
.level = INFO handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.level = ALL org.apache.http.impl.conn.level = FINEST org.apache.http.impl.client.level = FINEST org.apache.http.client.level = FINEST 

More detailed information is available from the Java Logging documentation.

Источник

Оцените статью