Using HTTP/2 in your Spring Boot application
Prerequisites
For this tutorial I’m assuming that you have a Unix-based environment on which you are able to run both the openssl
and curl
commands.
Generating a test project
Using https:
- Maven
- Java 11
- Spring Boot 2.2
- Dependencies
- Spring Web
Once generated, open this project in your favorite IDE, so we can start adding HTTP/2.
Creating an endpoint for testing
In your main application package create a simple TestController
class, that we can use to verify our Spring Boot
application is running HTTP/2.
@RestController
public class TestController {
@GetMapping
public String test() {
return "successful";
}
}
Let’s start up our application and have a look.
curl http://127.0.0.1:8080
This should return the string successful
.
Enabling HTTP/2 at the Spring Boot level
In the application.properties
file, enable HTTP/2 and restart the application.
server.http2.enabled=true
Now, let’s use curl
to validate the HTTP version in use.
curl -sI http://127.0.0.1:8080
This provides us with a response, like the one shown below.
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 10
Date: Sat, 01 Feb 2020 09:45:54 GMT
Based on the first line of the response: HTTP/1.1 200
, we can easily spot the fact that HTTP/1.1 is still being used.
The reason for this is that HTTP/2 only works over HTTPS. Let’s enable HTTPS on our application and verify that this is
indeed the missing component.
Setting up HTTPS
In order to be able to set up HTTPS in our local environment, we need to have an SSL certificate. Let’s generate a self-signed certificate that we can use for testing purposes. Use the command below to generate this certificate. (Source: Let’s Encrypt)
openssl req -x509 -out localhost.crt -keyout localhost.key \
-newkey rsa:2048 -nodes -sha256 \
-subj '/CN=localhost' -extensions EXT -config <( \
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
This generates two files localhost.crt
, the public key, and localhost.key
, the private key.
We can now use openssl
to generate a PKCS truststore file that contains both our certificate and key.
openssl pkcs12 -export -in localhost.crt -inkey localhost.key -name localhost -out localhost.p12
The result of this command is a localhost.p12
file that we can use in our application. Copy this keystore file to your
src/main/resources
directory of your project and add the below configuration to your application.properties
file in
order to configure HTTPS. (make sure to replace <password>
with the password you entered when generating the PKCS
file)
# Changes the server port used by Spring Boot to the default one used for HTTPS on Tomcat
server.port=8443
# The format used for the keystore. It could be set to JKS in case it is a JKS file
server.ssl.key-store-type=PKCS12
# The path to the keystore containing the certificate
server.ssl.key-store=classpath:localhost.p12
# The password used to generate the certificate
server.ssl.key-store-password=<password>
# The alias mapped to the certificate
server.ssl.key-alias=localhost
This should be everything to enable HTTPS for the application.
Putting our configuration to the test
Finally, start the application and use the curl
command to connect to our test
endpoint. (I’m using the -k
option, as curl
does not by default trust self-signed certificates)
curl -k -sI https://127.0.0.1:8443
The output of this should show that HTTP/2 is now successfully enabled.
HTTP/2 200
content-type: text/plain;charset=UTF-8
content-length: 10
date: Sat, 01 Feb 2020 10:15:09 GMT
Congratulations, you’ve successfully upgraded your application to use HTTP/2. There are still a couple of other things you could configure, such as a redirect from HTTP to HTTPS at the Tomcat level and setting up Spring Security to force SSL on all connections. Below in the references you can find a tutorial explaining this in more detail.