Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring 4.1.1, mockmvc and do not want url encoding of HTTP GET request

Using MockMVC in tests and I need to test a GET URL that is already URL encoded:

http://host:port/app/controller/[ALREADY URL ENCODED]

The code:

mockmvc.perform(get("/controller/[ALREADY URL ENCODED]")

However in the logs I see that the URL has been url encoded again before it gets to the appropriate controller method. Is there a way that we can prevent spring mockmvc to url encode? Perhaps disable url encoding in the test?

Real example of the "[ALREADY URL ENCODED]" string:

MEUwQzBBMD8wPTAJBgUrDgMCGgUABBQ%2Fm36Fj2BE19VBYXRO62zrgIYp0gQVAQazEyvlq22wsMBkRyAeaUiZ%2BhTUAgMGJbQ%3D

This gets URL encoded again before the controller sees it.

This is from the logs (the string has been url encoded again)

xxxxx [main] DEBUG [o.s.t.w.s.TestDispatcherServlet]  DispatcherServlet with name '' processing GET request for [/app/controller/MEUwQzBBMD8wPTAJBgUrDgMCGgUABBQ%252Fm36Fj2BE19VBYXRO62zrgIYp0gQVAQazEyvlq22wsMBkRyAeaUiZ%252BhTUAgMGJbQ%253D]

Note that if I invoke using CURL then there is no url encoding performed by the spring framework and the controller gets what is sent across. However mockmvc would do the encoding before it gets to the appropriate controller method.

curl -X GET http:host:port/app/controller/[ALREADY URL ENCODED]

Thanks.

like image 671
Khanna111 Avatar asked Nov 03 '14 20:11

Khanna111


2 Answers

What works for me is MockMvcRequestBuilders.get(new URI([ENCODED_URL_STRING])).

I guess there is alternative using MockMvcRequestBuilders.get(String urlTemplate, Object... urlVariables), with appropriate urlVariables, but I haven't gone deeper.

like image 55
吴烜_中文编程 Avatar answered Nov 16 '22 14:11

吴烜_中文编程


A little late, but I created my own URI matcher to use with MockMvc:

public class RequestToUriMatcher implements RequestMatcher {

    private final String expectedUri;

    public RequestToUriMatcher(String expectedUri){
        this.expectedUri = expectedUri;
    }

    @Override
    public void match(ClientHttpRequest clientHttpRequest) throws IOException, AssertionError {
        URI requestUri = clientHttpRequest.getURI();
        //requestUri is encoded, so if request was made with query parameter already encoded, this would be double-encoded, so decoding it once here
        String decodedUri = URLDecoder.decode(requestUri.toString(), "UTF-8");
        assertTrue(decodedUri.endsWith(expectedUri));
    }
}

Followed by a static method:

public static RequestMatcher requestToUri(String uri){
    return new RequestToUriMatcher(uri);
}

Now I can use it like so:

String uri = "stuff%3Dvalue";
MockRestServiceServer.createServer(restTemplate)
    .expect(requestToUri(uri))/**/

It is not a perfect solution, but for the sake of lack of other solutions, it works...

like image 21
Daniel Gruszczyk Avatar answered Nov 16 '22 14:11

Daniel Gruszczyk