18

I have this REST resource:

@GET
@Path("{business},{year},{sample}")
@Produces(MediaType.APPLICATION_JSON)
public Response getSample(
        @PathParam("business") String business,
        @PathParam("year") String year,
        @PathParam("sample") String sampleId {
    Sample sample = dao.findSample(business, year, sampleId);
    return Response.ok(sample).build();
}

sample param can contain slash character: 6576/M982, for instance.

I'm calling it with http://ip:port/samples/2000,2006,6576/M982 but does not work, obviously.

I have also tried with http://ip:port/samples/2000,2006,6576%2FM982, encoding the slash as %2F, but doesn't work either, it doesn't reach the endpoint.

EDIT

I'm using Retrofit to call the endpoint and I do this:

@GET("/samples/{business},{year},{sampleId}")
Observable<Sample> getSampleById(
        @Path("business") String business,
        @Path("year") String year,
        @Path(value = "sampleId", encoded = true) String sampleId);

With encoded = true, but still not working.

Héctor
  • 24,444
  • 35
  • 132
  • 243

3 Answers3

20

Reserved characters such as , and / must be URL encoded.

  • , is encoded as %2C
  • / is encoded as %2F

Try http://ip:port/samples/2000%2C2006%2C6576%2FM982.


The RFC 3986 defines the following set of reserved characters that can be used as delimiters. Hence, they require URL encoding:

: / ? # / [ ] / @ ! $ & ' ( ) * + , ; =

Unreserved characters do not require URL encoding:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
a b c d e f g h i j k l m n o p q r s t u v w x y z
0 1 2 3 4 5 6 7 8 9 - _ . ~

If URL encoding , is not a good alternative for you, you could consider using query parameters. Your code will be like:

@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getSample(@QueryParam("business") String business, 
                          @QueryParam("year") String year,
                          @QueryParam("sample") String sampleId {
    ...
}

And your URL will be like http://ip:port/samples?business=2000&year=2006&sample=6576%2FM982.

Please note that the / still needs to be URL encoded.

Community
  • 1
  • 1
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • 1
    "Reserved characters such as , and / must be URL encoded." Although true of querysting content, that's not necessarily true for path content. From the same rfc: "Thus, characters in the reserved set are protected from normalization and are therefore safe to be used by scheme-specific and producer-specific algorithms for delimiting data subcomponents within a URI." So it's okay not to encode the slashes if they're being used as path delimiters. Furthermore, encoded slashes will get you in trouble with some webservers (tomcat) – Alkanshel Apr 30 '18 at 19:43
  • 3
    @Amalgovinus That's true. However, in the OP situation, looks like the `/` is not a path delimiter. So it's okay to encode. – cassiomolin Apr 30 '18 at 20:00
  • 1
    Note that URLs containing %2F are blocked by many http and application servers, because bugs in old http servers meant that would decode the %2F and treat it as a path delimiter without apply path secuirty checks – dan carter Sep 04 '19 at 00:36
4

Try to use {sample:.+} instead of {sample}

The @Path annotation is a regular expression and regex do not match / character.

To override the regex, we can add .+ at the end of the PathParam.

In this way we can allow / in our path and avoid using %2F.

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
steva1988
  • 49
  • 1
  • 4
1

Actually, .+ helped. Just that it needs to be part of @Path but not @PathParam.

Example:

@Path("{sample:.+}")
geekTechnique
  • 850
  • 1
  • 11
  • 38
Srinivas
  • 11
  • 2