AWS CloudFront возвращает неверный запрос от Spring WebClient, но работает с Postman
У меня есть API, который запущен и работает в AWS CloudFront. Когда я тестирую API от Postman, кажется, что он работает нормально.
Вот запрос от консоли Postman.
Но при вызове того же API из Spring WebClient он возвращает 400 неверных запросов с ответом:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>400 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Bad request.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: pGx0NHPSaU3H2EHJwtQrYEdLDjL_UPxO90esPoH3d9efZX_bvzjFQw==
</PRE>
<ADDRESS>
</ADDRESS>
</BODY></HTML>
Вот мой код:
@Component
public class SyncTranscriberClient {
private final WebClient webClient;
@Value("${transcriber.sync.username}")
private String username;
@Value("${transcriber.sync.password}")
private String password;
public SyncTranscriberClient(@Value("${transcriber.sync.base-url}") String baseUrl) throws SSLException {
var sslContext = SslContextBuilder
.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
var client = HttpClient.create().secure(t -> t.sslContext(sslContext));
webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(client))
.baseUrl(baseUrl)
.filter(logRequest())
.build();
}
private static ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
log.info("Request: {} {}", clientRequest.method(), clientRequest.url());
clientRequest.headers().forEach((name, values) -> values.forEach(value -> log.info("{}={}", name, value)));
return Mono.just(clientRequest);
});
}
public Map<String, String> getCredentials() {
return webClient.post()
.uri("my-url-hidden-for-security-reasons")
.headers(headers -> headers.setBasicAuth(username, password))
.headers(headers -> headers.set("Accept", "*/*"))
.headers(headers -> headers.set("Host", "hidden-for-security-reasons"))
.retrieve()
.onStatus(HttpStatus::isError, response -> response.bodyToMono(String.class) // error body as String or other class
.flatMap(error -> Mono.error(new RuntimeException(error)))
)
.toBodilessEntity()
.map(HttpEntity::getHeaders)
.map(headers -> Map.of(
"Authorization", Objects.requireNonNull(headers.getFirst("Authorization")),
"JSESSIONID", Objects.requireNonNull(headers.getFirst("JSESSIONID"))
))
.block();
}
}
Что я здесь делаю неправильно?
1 ответ
Мне пришлось отправить Content-Type: text/plain и пустое тело.
webClient.post()
.uri("my-url-hidden-for-security-reasons")
.headers(headers -> {
headers.setBasicAuth(username, password);
headers.set("Content-Type", "text/plain");
})
.body(BodyInserters.fromValue(""))
.retrieve()
.onStatus(
HttpStatus::isError,
response -> response.bodyToMono(String.class)
.flatMap(error -> Mono.error(new RuntimeException(error)))
)
.toBodilessEntity()
.map(HttpEntity::getHeaders)
.map(headers -> Map.of(
"Authorization", Objects.requireNonNull(headers.getFirst("Authorization")),
"JSESSIONID", Objects.requireNonNull(headers.getFirst("JSESSIONID"))
))
.block();