Closed zx-max closed 1 month ago
@zx-max , I believe what's happening here is that you ran into a limitation of the binding mechanism. The annotations @Get
, @PathVariable
etc. can only bind one variable from each template expression. Take for example this contrived example:
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.PathVariable;
@Controller
public class Section323Controller {
/* works the same if you remove the arguments' annotations */
@Get("1)/{+path},{x}/here")
public String getExpansionWithMultipleVars(@PathVariable("path") String path, @PathVariable("x") String x) {
return "1) path=" + path + " AND x=" + x ;
}
@Get("2)/{+path,x}/here")
public String getExpansionWithOneVar(@PathVariable("path") String path, String x) {
return "2) path=" + path + " AND x=" + x ;
}
@Get("3)/{+path,x}/here")
public String getExpansionWithNoVar(String path, String x) {
return "3) path=" + path + " AND x=" + x ;
}
}
A simple test for it could be:
import io.micronaut.core.type.Argument;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.MutableHttpRequest;
import io.micronaut.http.client.HttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@MicronautTest
class Section323ControllerTest {
@Inject
@Client("/")
HttpClient client;
@Test
void testTwoPathVars() {
MutableHttpRequest<String> request = HttpRequest.GET("1)/foo/bar,1024/here");
HttpResponse<Object> httpResponse = client.toBlocking().exchange(request);
assertEquals(HttpStatus.OK, httpResponse.getStatus());
assertEquals("1) path=foo/bar AND x=1024", httpResponse.getBody(Argument.STRING).get());
}
@Test
void testOnePathVar() {
MutableHttpRequest<String> request = HttpRequest.GET("2)/foo/bar,1024/here");
HttpResponse<Object> httpResponse = client.toBlocking().exchange(request);
assertEquals(HttpStatus.OK, httpResponse.getStatus());
/* fails; the result is "2) path=f AND x=oo/bar,1024" */
assertEquals("2) path=foo/bar AND x=1024", httpResponse.getBody(Argument.STRING).get());
}
@Test
void testNoPathVar() {
MutableHttpRequest<String> request = HttpRequest.GET("3)/foo/bar,1024/here");
HttpResponse<Object> httpResponse = client.toBlocking().exchange(request);
assertEquals(HttpStatus.OK, httpResponse.getStatus());
/* fails; the result is 3) path=f AND x=oo/bar,1024" */
assertEquals("3) path=foo/bar AND x=1024", httpResponse.getBody(Argument.STRING).get());
}
}
Bottom line: you cannot have a template like {var1,var2,var3}
. To have it working with Micronaut you need one expression per variable, something like {var1}{var2}{var3}
.
Thanks a lot !!!
I added your example in the demo and i have fixed the template in the @Get
.
Expected Behavior
Given this uri template:
{+path,x}/here
as described in: rfc6570 section-3.2.3If a write a method in a controller who use it
And i send a request with the example values: path=/foo/bar x=1024
When the controller receive the http request, for the variables, i expect this values : path=/foo/bar x=1024
Actual Behaviour
The values assigned to the variables are: path = / and x = foo/bar,1024
Steps To Reproduce
to reproduce, just run the test here:
test on git hub
https://github.com/zx-max/micronaut-tutorial/blob/main/uri-templates/demo/src/main/java/http/client/UriTemplateExpanderSpecController.java
Environment Information
I use window, jdk 21, the project has been created from command line with this command:
Example Application
https://github.com/zx-max/micronaut-tutorial/tree/main/uri-templates/demo
Version
4.4.2