Closed as not planned
Closed as not planned
Description
Hello!
Summary
Please add support for sending application/x-www-form-urlencoded
request bodies using the @HttpExchange
/ @PostExchange
abstraction.
Currently, it is not possible to annotate a method argument which is POJO in an @HttpExchange
interface to send form-encoded data in the request body.
Example
@HttpExchange("/token") interface AuthClient { @PostExchange(contentType = MediaType.APPLICATION_FORM_URLENCODED_VALUE) fun getToken( @RequestBody form: MyForm ): TokenResponse }
data class MyForm( val login: String, val password: String, }
authClient.getToken( MyForm("login", "pwd") }
This code leads to org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/x-www-form-urlencoded' not supported for bodyType=MyForm
Currently to avoid limitations we can use custom org.springframework.http.codec.HttpMessageWriter
class FormUrlencodedWriter : HttpMessageWriter<Any> { private val supportedMediaType = MediaType.APPLICATION_FORM_URLENCODED override fun canWrite(elementType: ResolvableType, mediaType: MediaType?): Boolean { return supportedMediaType == mediaType } override fun getWritableMediaTypes(): MutableList<MediaType> { return mutableListOf(supportedMediaType) } override fun write( inputStream: Publisher<out Any>, elementType: ResolvableType, mediaType: MediaType?, message: ReactiveHttpOutputMessage, hints: MutableMap<String, Any> ): Mono<Void> { return Flux.from(inputStream).next().flatMap { value -> val form = LinkedMultiValueMap<String, String>() value.javaClass.declaredFields.forEach { field: Field -> field.isAccessible = true val fieldValue = field.get(value) if (fieldValue != null) { val annotation = field.getDeclaredAnnotation(FormProperty::class.java) if (annotation != null) { form.add(annotation.name, fieldValue.toString()) } else { form.add(field.name, fieldValue.toString()) } } } val encoded = UriComponentsBuilder.newInstance() .queryParams(form) .build() .toUri() .rawQuery val bytes = encoded.toByteArray(UTF_8) message.headers.contentType = supportedMediaType message.headers.contentLength = bytes.size.toLong() message.writeWith(Mono.just(message.bufferFactory().wrap(bytes))) } } }
and add it to WebClient
@Bean fun exchangeStrategies(): ExchangeStrategies = ExchangeStrategies.builder() .codecs { config -> config.customCodecs().register(FormUrlencodedWriter()) } .build() @Bean fun webClient(exchangeStrategies: ExchangeStrategies): WebClient = WebClient.builder() .exchangeStrategies(exchangeStrategies) .baseUrl("http://localhost:8081") .build()
I understand that if use org.springframework.util.MultiValueMap
as @RequestBody
type then everything works fine but POJO support might be good enhancement
This request is similar to https://github.com/OpenFeign/feign-form/ which design was nice