micronaut-core
micronaut-core copied to clipboard
Customizing x-www-form-urlencoded request body in HTTP Client
Problem
I'm trying to make an x-www-form-urlencoded
HTTP request, with attribute names that don't follow Java's conventions, because of a 3rd party that uses snake_case.
I try to illustrate this in the following code snippet, by using @JsonProperty("some_attribute")
(note: this is not working).
Link to sample repo: https://github.com/Kidlike/mn-form-urlencoded-jackson
import com.fasterxml.jackson.annotation.JsonProperty;
import io.micronaut.core.annotation.Introspected;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Body;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.client.annotation.Client;
import reactor.core.publisher.Mono;
@Client("/echo")
public interface SampleClient {
@Post(produces = MediaType.APPLICATION_FORM_URLENCODED, consumes = MediaType.APPLICATION_JSON)
Mono<SampleDto> echo(@Body SampleDto sampleDto);
@Introspected
class SampleDto {
@JsonProperty("some_attribute")
private String someAttribute;
public SampleDto() {
}
public SampleDto(String someAttribute) {
this.someAttribute = someAttribute;
}
public String getSomeAttribute() {
return someAttribute;
}
public void setSomeAttribute(String someAttribute) {
this.someAttribute = someAttribute;
}
}
}
Investigation
After some digging in Micronaut's source code, I found that this media type has special handling: https://github.com/micronaut-projects/micronaut-core/blob/c7731627a9856157809aa0a53840ab7154f3fe6f/http-client/src/main/java/io/micronaut/http/client/netty/DefaultHttpClient.java#L1673-L1682
Then buildFormDataRequest
is called:
https://github.com/micronaut-projects/micronaut-core/blob/c7731627a9856157809aa0a53840ab7154f3fe6f/http-client/src/main/java/io/micronaut/http/client/netty/DefaultHttpClient.java#L2274-L2282
And in the end, BeanMap.of
:
https://github.com/micronaut-projects/micronaut-core/blob/c7731627a9856157809aa0a53840ab7154f3fe6f/core/src/main/java/io/micronaut/core/beans/BeanMap.java#L45-L49
Workaround
According to the above, this means that the only way to manipulate in any way the parameters of this x-www-form-urlencoded
request, are by the real field members of the body class. Or more specifically with this adjustment:
public String getSome_attribute() {
return someAttribute;
}
This works, but obviously the name of the getter is very weird, and does not follow modern java's naming conventions. Also it's not possible to hide it, because it has to be public in order for it to be serialized.
Suggestion
Since Jackson annotations seem to be respected in the request body of controllers that consume x-www-form-urlencoded
requests, it would be sensible to also do it for the outgoing requests (http client). Of course I don't know if this is technically feasible; I guess it depends on the capabilities of Jackson.
#1853
#1853
thanks for this... I actually searched and couldn't find anything :(
i'm running into this after upgrading to 4.1.1. i was getting the right behavior in 3.10
I can confirm that this used to work for Micronaut 3.4.3 by either annotating with @JsonProperty
or adjusting the names of the getters e.g. the getter for the field private String grantType
had to be getGrant_type()
in order to serialize to grant_type
in the URL form.
For Micronaut 4.2 i can confirm that this behavior actually doesn't work anymore so the only workaround is to use a Map
instead as there is a dedicated execution branch for this.
I'd appreciate if you'd fix this e.g. by a @FormProperty
annotation as you've mentioned in a different thread.
I think the label "workaround available" can be added.