1

Let's say i have a route

POST       /api/{id}/{application}    Application.doSomething

How Application.doSomething can have convenient access to all query parameters, including 'id' and 'application'?

If i call it as

curl -X POST -d 'id=test&application=test' -v /api/12345/myapp

Then request.params 'id' and 'application' will be set to ROUTE parameters '12345' and 'myapp', not query parameters 'test'.

And i can't see how i can access those without parsing request.params 'body' manually, which is kind of silly.

EDIT: Sorry, maybe it's not very clear. Let's say that doSomething controller saves all query parameters in the key-value store somewhere. For this id and application. And it's completely arbitrary keys really. So now with this structure you can't have 'id' and 'application' as a key, just because i've used those names as route parameters, which shouldn't be the concern of the client. Basically i just need to have an access to normal query parameters, without play putting route parameters in the same bucket!

Eugene
  • 345
  • 1
  • 4
  • 14
  • I made a proposal for some minor edits in your question so that it's more clear than you are not asking to modify `params` - which is what I had understood at first :) . Please check them out and feel free to improve/decline! – Stefano Mar 07 '12 at 15:26

3 Answers3

0

I think you are confusing the usage of routes. This line:

POST       /api/{id}/{application}    Application.doSomething

sets that when you get a request, let's say /api/12345/myapp, the middle part will be matched with the request and any parameters you defined will be extracted.

In the sample request /api/12345/myapp the parameter id will get the value 12345 and the parameter application the value myapp.

In your request, as you are calling /api/12345/myapp the parameters are already assigned and the fragment id=test&application=test is ignored.

You should call it like /api/test/test/ to get the result you expect.

Pere Villega
  • 16,429
  • 5
  • 63
  • 100
  • Yes, but the point being that you need to call /api/{id}/{application} with ANY query parameters, including those which i've used for constructing the url. So it's not always id and not always application, it can be anything. And then something happens with all those parameters. But now i have a conflict between query parameters and route parameters, so i can't use ANY query parameters anymore. – Eugene Mar 06 '12 at 14:35
  • Err, maybe i'm explaining it porrly. I've updated the original post to illustrate it better i hope. – Eugene Mar 06 '12 at 14:42
  • @Eugene why would you want to call the ROUTE params and GET params the same? It does not make much sense... You should be calling /api/application/ without /id/ if you want to pass it via querystring – Stefano Mar 06 '12 at 14:44
  • No-no-no, it's not whether i want to call route and get params the same. It's just that api can receive ANY get parameter. And it CAN BE 'id=...' or 'application=...'. And in that case the API ignores those parameters, just because there are already ROUTE parameters with name 'id' or 'application'! – Eugene Mar 06 '12 at 14:46
0

Play does this stuff for you. Play is able to bind even complex Java Objects out of request parameters. This POST request deserialization is default in play I think.

You make a Java Object that was sent by your request params:

public class MyObject {
  public String id;
  public String application;
}

And in your Application controller method this object is your argument:

public static void doSomething(MyObject aObject) {
   // do your thing
}
adis
  • 5,901
  • 7
  • 51
  • 71
  • Yes, but the point being that you need to call /api/{id}/{application} with ANY query parameters, including those which i've used for constructing the url. So it's not always id and not always application, it can be anything. And then something happens with all those parameters. But now i have a conflict between query parameters and route parameters, so i can't use ANY query parameters anymore. – Eugene Mar 06 '12 at 14:34
0

There's a simple way to access the original querystring:

inside the controller action access the 'request' object, eg.

public static void action(){
     String qs = request.querystring;
}

That said, it does not sound very clear to have the same parameter name in the query string and the route, REST-wise;

make the ROUTE 'id' and 'application' names more explicit in the route file, and you'll have no more collisions...

[edit 1]

I understand that the query string could be 'any' parameter: still, if you name it:

POST       /api/{object_id}/{play_application}    Application.doSomething

I really doubt you'll have a collision ;-)

[edit 2]

Parsing a query string in Java is really trivial, eg. see https://stackoverflow.com/a/2969715/422670

Most of the complexity of creating the "params" map in Play is due to combining post/get/route/etc... so you can't ask play to do the job for you in a way that would break it for everybody else!

Community
  • 1
  • 1
Stefano
  • 18,083
  • 13
  • 64
  • 79
  • Sure, but then i need to parse querystring myself. How to name them more explicitly? ______MYPRIVATEID98123981239______? So it's less likely to occur as a query param? Well, it's not really solving the problem in principle, isn't it? – Eugene Mar 06 '12 at 14:55
  • @Eugene parsing the query string yourself is simple; making your usecase work for Play would mean Play wouldn't work for anybody else anymore... so I think my solution(s) do solve your problem as far as it is solvable! (PS. yes, that's really unlikely to occur as a query param :) ) – Stefano Mar 06 '12 at 15:01
  • Well, i knew that, but i was hoping that it can be done somehow more elegantly and i've just missed some method or map somewhere...I'm not advocating for breaking the existing functionality, but just additional method on request.params which will return you only the map of query parameters would be definetely useful. Especially considering the obvious fact that play combines route params and query params itself, but you can't access just query params... – Eugene Mar 06 '12 at 15:07
  • @eugene I can't but insist that it's so easy to parse the querystring yourself that making the `params` Map parametric (sorry for the pun) would totally be overengineering... – Stefano Mar 06 '12 at 17:20
  • request.querystring can be used for GET parameters, but in my example i'm using POST, so i can access body params either through request.body and read InputStream(niiice!), or request.params.get("body"), which is silly really. And yea, i need to parse it myself afterwards. – Eugene Mar 06 '12 at 18:03
  • I don't think it's overengineering if i want to know the origin of my params. It may be useful to merge all of them together, but i still want to know type of params if i need to. No need for parametric maps, just another method on request which will give me either queryparams or bodyparams, maybe both. There is also separate map request.routeArgs for route params, so why not query/body? – Eugene Mar 06 '12 at 18:04
  • check `play/data/parsing/UrlEncodedParser.java` it knows how to parse both String and InputStream; http://www.playframework.org/documentation/api/1.2.4/play/data/parsing/UrlEncodedParser.html . Indeed it does not seem difficult to add a GET and POST maps to the request – Stefano Mar 06 '12 at 18:24