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();
Другие вопросы по тегам