Home > Enterprise >  Spring Boot. How to test http protocol version?
Spring Boot. How to test http protocol version?

Time:11-25

I'm using Spring Boot 2.6.0 and Spring MVC in my application. I want to switch my controller protocol from version http/1.1 to http/2. First of all, I've written the next integration test for that:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class IntegrationTest {

    @Autowired
    private TestRestTemplate template;

    @Test
    public void canGet() {
        ResponseEntity<JsonResponse> entity = template.getForEntity("/foo", JsonResponse.class);
        assertEquals(HttpStatus.OK, entity.getStatusCode());
        assertNotNull(entity.getBody());
        //todo: assertEquals("http/2", entity.getProtocol());
        //todo: assertEquals("http/1.1", entity.getProtocol())
    }
}

But entity.getProtocol() method doesn't exist and I can't find any other way to test protocol version. Does anyone know how to test the protocol version correctly in spring boot application?

CodePudding user response:

Having a simple Spring-Starter application, with a (rest) controller like:

@GetMapping("/foo")
public String foo() {
    return "bar";
}

With java >= 11, we can test the HTTP protocol version with java.net.http.*:

package com.example.test.http.version;

import java.io.IOException;
import java.net.URI;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class IntegrationTests {

    @LocalServerPort
    private int port;

    @Test
    public void testJavaDotNet() throws IOException, InterruptedException {
        java.net.http.HttpClient client = java.net.http.HttpClient.newBuilder()
                .build(); // or configure a (test) bean
        java.net.http.HttpRequest request = java.net.http.HttpRequest.newBuilder()
                .uri(URI.create("http://localhost:"   port   "/foo"))
                .build();
        java.net.http.HttpResponse<String> response = client.send(request, java.net.http.HttpResponse.BodyHandlers.ofString());

        assertNotNull(response);
        assertEquals(java.net.http.HttpClient.Version.HTTP_1_1, response.version());
    }
}

Key points:


With java < 11 but also alternatively, we can use:

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <!--  <version>4.5.13</version> managed via spring-boot-dependencies -->
  <scope>test</scope>
</dependency>

..and:

@Test
public void testApache() throws IOException {
    org.apache.http.client.HttpClient client = org.apache.http.impl.client.HttpClientBuilder.create()
       .build();// or configure (test) bean(s)
    org.apache.http.HttpResponse response = client.execute(
        new org.apache.http.client.methods.HttpGet("http://localhost:"   port   "/foo")
    );
    org.apache.http.ProtocolVersion protocolV = response.getStatusLine().getProtocolVersion();

    assertNotNull(protocolV);
    assertEquals("HTTP", protocolV.getProtocol());
    assertEquals(1, protocolV.getMajor());
    assertEquals(1, protocolV.getMinor());
}


Probably this is not the last option... And when you somehow manage to access the ServletRequest (in your test), you can issue: getProtocol(), like here.

CodePudding user response:

You can use OkHttp with Spring for that, as answered on following answer: Springboot 2: Is there any way to configure TestRestTemplate to only use HTTP/2 protocol?

  • Related