春季启动。如何测试http协议版本?

Vol*_*ozo 5 java spring http spring-mvc spring-boot

我正在我的应用程序中使用Spring Boot 2.6.0and Spring MVC。我想将我的控制器协议从版本切换http/1.1http/2. 首先,我为此编写了下一个集成测试:

@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())
    }
}
Run Code Online (Sandbox Code Playgroud)

entity.getProtocol()方法不存在,我找不到任何其他方法来测试协议版本。有谁知道如何在 Spring Boot 应用程序中正确测试协议版本?

xer*_*593 2

有一个简单的 Spring-Starter 应用程序,带有一个(其余)控制器,例如:

@GetMapping("/foo")
public String foo() {
    return "bar";
}
Run Code Online (Sandbox Code Playgroud)

使用java >= 11,我们可以使用客户端测试HTTP协议版本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());
    }
}
Run Code Online (Sandbox Code Playgroud)

关键点:


对于 java < 11但也可以使用:

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <!--  <version>4.5.13</version> managed via spring-boot-dependencies -->
  <scope>test</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)

..和:

@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());
}
Run Code Online (Sandbox Code Playgroud)

抱歉,OkHttp

<dependency>
  <groupId>com.squareup.okhttp3</groupId>
  <artifactId>okhttp</artifactId>
  <!-- <version>3.14.9</version>  managed via spring-boot-dependencies -->
  <scope>test</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud)

并且,“瞧”:

@Test
public void testOkHttp() throws IOException {
  okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
  okhttp3.Request request = new okhttp3.Request.Builder().url(getUriString("/foo")).build();

  try (okhttp3.Response response = client.newCall(request).execute()) {
    assertEquals(okhttp3.Protocol.HTTP_1_1, response.protocol());
  } catch (RuntimeException reexc) {
    org.junit.jupiter.api.Assertions.fail(reexc);
  }
}
Run Code Online (Sandbox Code Playgroud)

也许这不是最后一个选择......当你以某种方式设法访问ServletRequest(在你的测试中)时,你可以发出:getProtocol(),就像这里一样