0

In Spring Boot 1.5.4 I have a request mapping like this:

@RequestMapping(value = "/graph/{graphId}/details/{iri:.+}", 
                method = RequestMethod.GET,
                produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public JSONObject getGraph(@PathVariable Long graphId, 
                           @PathVariable String iri) {
    log.debug("Details called for graph ID {} for IRI {}", graphId, iri);
    return detailsService.getDetails(graphId, iri);
}

Accessing

http://localhost:9000/api/v1/graph/2/details/http%3Anthnth33

works fine and the server maps the request correctly and the code returns the expected result

But accessing

http://localhost:9000/api/v1/graph/2/details/http%3A%2F%2Fserverurl.net%2Fv1%2Fus%2Fh.schumacher%408tsch.net%2Fn%2FLouSchumacher

gives a bad server request (Failed to load resource: the server responded with a status of 400 (Bad Request)). The request mapping to the end point isn't even done in that case.

Obviously the slash '/' encoded as %2F (using encodeURIComponent()) causes trouble. Why? What am I missing? How should uri parameter then be encoded?

The question is not only about how to extract PathVariables but more on how to force String to recognize the correct mapping.

Hubert Schumacher
  • 1,683
  • 1
  • 16
  • 25
  • Instead of GET API , make it a POST API request and send the URI in the request body. As a thumb rule whenever you have large number of parameters to pass , POST comes much more handy – TruckDriver Oct 21 '17 at 07:31
  • Possible duplicate of [Spring 3 RequestMapping: Get path value](https://stackoverflow.com/questions/3686808/spring-3-requestmapping-get-path-value) – Aleh Maksimovich Oct 21 '17 at 09:45
  • Spring 3 RequestMapping: Get path value (https://stackoverflow.com/questions/3686808/spring-3-requestmapping-get-path-value) is related but the question is not duplicate in the sense that this question is about mapping of the Rest endpoint and less about the extraction of the PathVariables afterwards – Hubert Schumacher Oct 21 '17 at 11:07

1 Answers1

1

The issue with your example is how Spring is doing path matching. The URL you have provided as example

http://localhost:9000/api/v1/graph/2/details/http%3A%2F%2Fserverurl.net%2Fv1%2Fus%2Fh.schumacher%408tsch.net%2Fn%2FLouSchumacher

will be decoded into by container

http://localhost:9000/api/v1/graph/2/details/http://serverurl.net/v1/us/h.schumacher@8tsch.net/n/LouSchumacher

before processing by Spring matcher. This makes matche think that this only http: corresponds {iri:.+} and as later goes / so it is some longer path you don't have a mapping for.

The approach described here should work for you: Spring 3 RequestMapping: Get path value

@RequestMapping(value = "/graph/{graphId}/details/**", 
                method = RequestMethod.GET,
                produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public JSONObject getGraph(@PathVariable Long graphId, 
                           HttpServletRequest request) {
    String iri = (String) request.getAttribute(
        HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
    log.debug("Details called for graph ID {} for IRI {}", graphId, iri);
    return detailsService.getDetails(graphId, iri);
}
Aleh Maksimovich
  • 2,622
  • 8
  • 19
  • This helps, but the mapping to the Rest endpoint does work that way if I do NOT encode the URL with encodeURIComponent(). If I do encode with encodeURIComponent() the mapping is not recognized and I get a "Bad Request (400)" error. So the mapping for http://localhost:9000/api/v1/graph/2/details/http://serverurl.net/v1/us/h.schumacher@8tsch.net/n/LouSchumacher works but for http://localhost:9000/api/v1/graph/2/details/http%3A%2F%2Fserverurl.net%2Fv1%2Fus%2Fh.schumacher%408tsch.net%2Fn%2FLouSchumacher doesn't. – Hubert Schumacher Oct 21 '17 at 11:02