如何使用 Spring rest 模板发送带正文的 HTTP OPTIONS 请求?

How to send HTTP OPTIONS request with body using Spring rest template?

我正在尝试调用 RESTfull 网络服务资源,该资源由第三方提供,该资源使用 OPTIONS http 动词公开。

为了与该服务集成,我应该发送一个带有特定主体的请求,该主体由提供者标识,但是当我这样做时,我收到了一个错误的请求。之后我跟踪我的代码然后我认识到请求的主体被基于以下代码的其余模板忽略:

if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) ||
            "PATCH".equals(httpMethod) || "DELETE".equals(httpMethod)) {
        connection.setDoOutput(true);
    }
    else {
        connection.setDoOutput(false);
    }

我的问题是,是否有一种标准方法可以覆盖此行为,或者我应该使用其他工具?

您粘贴的代码来自

SimpleClientHttpRequestFactory.prepareConnection(HttpURLConnection connection, String httpMethod)

我知道,因为我几个小时前调试过该代码。 我必须使用 restTemplate 对正文执行 HTTP GET。所以我扩展了 SimpleClientHttpRequestFactory,覆盖了 prepareConnection 并使用新工厂创建了一个新的 RestTemplate。

public class SimpleClientHttpRequestWithGetBodyFactory extends SimpleClientHttpRequestFactory {

@Override
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
    super.prepareConnection(connection, httpMethod);
    if ("GET".equals(httpMethod)) {
        connection.setDoOutput(true);
    }
}

}

基于这个工厂创建一个新的 RestTemplate

new RestTemplate(new SimpleClientHttpRequestWithGetBodyFactory());

使用 spring 引导 (@RunWith(SpringRunner.class) 证明解决方案有效的测试 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT))

public class TestRestTemplateTests extends AbstractIntegrationTests {

@Test
public void testMethod() {
    RestTemplate restTemplate = new RestTemplate(new SimpleClientHttpRequestWithBodyForGetFactory());

    HttpEntity<String> requestEntity = new HttpEntity<>("expected body");

    ResponseEntity<String> responseEntity = restTemplate.exchange("http://localhost:18181/test", HttpMethod.GET, requestEntity, String.class);
    assertThat(responseEntity.getBody()).isEqualTo(requestEntity.getBody());
}

@Controller("/test")
static class TestController {

    @RequestMapping
    public @ResponseBody  String testMethod(HttpServletRequest request) throws IOException {
        return request.getReader().readLine();
    }
}

}