Тело запроса отправляется как json, даже если тип содержимого установлен как application / x-www-form-urlencoded.

Это связано с поднятым мной существующим вопросом о весенней загрузке (Тело запроса неправильно закодировано и скрыто при использовании кодировщика пружинных форм в Feign Client).

Согласно this question, мы можем добавить либо тип контента в заголовки, либо добавить во время сопоставления запроса как потребление.

Итак, я добавил тип контента в заголовки в классе конфигурации клиента.

public class EmailClientConfiguration  {
    
    @Bean
    public RequestInterceptor requestInterceptor(Account<Account> account) {
        return template -> {
             template.header("Content-Type", "application/x-www-form-urlencoded");
        };
    }
    
    @Bean
    public OkHttpClient client() {
        return new OkHttpClient();
    }
    
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
    
    @Bean
    public Decoder feignDecoder() {
        return new JacksonDecoder();
    }
    
    @Bean
    public Encoder feignFormEncoder () {
        return new SpringFormEncoder(new JacksonEncoder());
    }
}

и я вижу в заголовках, что тип контента правильно установлен как application / x-www-form-urlencoded при отправке запроса. Но тело запроса по-прежнему отправляется в формате json и также не скрывается.

Тело запроса:

Map<String, String> requestBody = new HashMap<>();
requestBody.put("username", "xyz");
requestBody.put("email", "[email protected]");
requestBody.put("key", "xxx");

Тело запроса получено на стороне сервера:

{"{\n  \"key\" : \"xxx\",\n  \"email\" : \"[email protected]\",\n  \"username\" : \"xyz\"\n}"

Когда я добавляю потребление в сопоставлении запросов как application / x-www-form-urlencoded

@FeignClient(name = "email", url = "localhost:3000", 
    configuration = EmailClientConfiguration.class)
public interface EmailClient {

    @PostMapping(value = "/email/send", consumes = "application/x-www-form-urlencoded")
    ResponseDto sendEmail(@RequestBody Map<String, String> requestBody);
    
}

он работает нормально (тело запроса скрыто на стороне сервера и также правильно закодировано). И когда я удалил заголовок в классе конфигурации и добавлял только потребление, все работает нормально без проблем, но наоборот, есть эта проблема.

Я искал это в Интернете и не нашел ответа.


person hacker painters    schedule 20.03.2021    source источник


Ответы (1)


Feign кодирует тело запроса и параметры перед передачей запроса любому RequestInterceptor (и это правильно). Если вы не объявляете consumes = "application/x-www-form-urlencoded", SprinFormEncoder не знает, что вы пытаетесь отправить данные формы, поэтому он делегирует сериализацию внутреннему JacksonEncoder, который выполняет только JSON (посмотрите сами, напечатав template.body() перед установкой заголовка).

Обработка такого хорошо поддерживаемого заголовка в перехватчике не кажется хорошей идеей, если у вас уже есть consumes. Если вы настаиваете на этом, вы должны предоставить свой собственный кодировщик, который не полагается на значение заголовка и всегда выводит данные в формате urlencoded.

person ttzn    schedule 20.03.2021