Finch: how can i define Endpoint with param in the middle - scala

i am trying to define an Endpoint with param in the middle.
something similar to:
get("foo" :: param("id") :: "goo")
so, i can call it with the following rest call:
http://mydomain/foo?id=99/goo
but, for some reason, it doesn't work.
any idea ?
thanks,
Eran.

In your get("foo" :: param("id") :: "goo") handler, this "foo" :: param("id") :: "goo" is is called route path.
And this param("id") is actually a path-parameter and not a query-parameter.
Standard URL scheme looks like following,
scheme:[//[user[:password]#]host[:port]][/path][?query][#fragment]
path-parameters are actually not part of standard URL scheme but are extracted from path part of URL using regular expression matching by modern http frameworks.
So... you need to access it with http url - http://mydomain/foo/99/goo

Related

go-restful extract URL pattern path from request

I am using a the emicklei/go-restful framework to deal with rest API.
I wish to access the route path from the request. Meaning that when I configure a dummy route like this:
ws := new(restful.WebService)
ws.Path("/resources/names")
ws.Route(ws.GET("/{name}").To(getName))
restful.DefaultContainer.Add(ws)
I wish to access the information that the route was "/resources/names/{name}"
I can access the actual URL which is call by calling:
req.Request.URL.Path
But this will return the specific URL, not the generic one.
Any suggestion?
After more research I finally found that the method req.SelectedRoutePath() will return expected value.

POST form parameters with Unfiltered

I have problem extracting form parameters (in body) from POST with Unfiltered.
From http://unfiltered.databinder.net/Within+the+Parameters.html I understood that Params(p) would put into p both url parameters and also form parameters inside body. But I just can't get form parameters in body.
Of course I could take body as string and build parser for that, but it would just be silly as would expect there would be something ready for such basic operation ...but I just can't find it.
My service is following and it prints out any parameters from url but not form-data parameters, if I use x-www-form-urlencoded then it seems to works.
def intent {
case POST(ContextPath(_, Seg("accounts" :: "providers" :: AsLong(id) :: "mfa" :: Nil)) & Params(params)) ⇒
println(s"${params.mkString("\n")}")
Ok
}

Can't pass parameter to reverse router in playframework

I have defined a route like this:
GET /login controllers.Login.showForm(continue: Option[String] = None)
Login.showForm is this:
def showForm(continue: Option[String] = None) = Action { implicit request =>
val nextPage = continue match {
case None => routes.CtrlIndex.index().absoluteURL().toString()
case Some(page) => page
}
Ok(views.html.login(nextPage))
}
Now, using action composition I made an authenticated action that performs this when the user is not authenticated:
val continue =
if (request.method == "GET") request.uri
else routes.CtrlIndex.index().absoluteURL().toString() // This is not code duplication for reasons that are out of the scope of this question.
Redirect(routes.Login.showForm(Some(continue)))
This fails to compile with this message:
too many arguments for method showForm: ()play.api.mvc.Call
[error] Redirect(routes.Login.showForm(Some(continue)))
Changing the route definition makes it work:
GET /login controllers.Login.showForm(continue: Option[String])
But then when I use the javascript reverse router, it generates the following error in the generated javascript:
SyntaxError: missing formal parameter
function(continue) {
---------^
I have tried all combination of the definition of the function signatures but when the javascript works, the other stops working or the other way around. How can I use
Optional parameter on /login
Use the reverse javascript router
Redirect to /login with the "continue" parameter
I would also like to change request.uri for something that returns an absolute path.
Thanks in advance
PS. If you see something in Spanish, let me know and I'll fix it, the code is originally in Spanish; I may have missed something even after I read it.
The likely cause is that "continue" is a reserved word in javascript
Play's javascript reverse router constructs a given route using the controller path and method argument(s) specified in the routes file; in your case, "continue" may be tripping up the js parser, much like a method named "delete", which works fine server-side but will blow up in the client-side reverse router.
This may be a non-issue for newer browsers, but have been bitten by "delete" method name on older versions of Internet Explorer (that we are required to support).

Scala Lift - REST-Get on dynamic generated image

I use Scala and Lift for REST web-services and I have a method that generates dynamic jpg images that should be made accessible via a Get Request, so that for each Get-Request the method generates an image again and sends it back in the response.
I made a case in serve:
case "img.jpg" :: Nil Get _ => Full(OkResponse())
case _ => Full(NotFoundResponse())
But this case does not seem to be recognised, it always catches the Default-Case.
What is the proper way to serve routes on a . url? And what response type can be used to deliver the jpg?
The file extension is handled separately from the rest of the path, so matching as you do above won't work. You can see some more discussion about this in the Lift Cookbook.
To make the above work, you should be able to do this:
case "img" :: Nil Get req if req.path.suffix == "jpg" => Full(OkResponse())
I believe you can also use the Req object, which will let you specify the suffix like this:
case Req("img" :: Nil, "jpg", GetRequest) => Full(OkResponse())

Define template to be used in a Loc in sitemap

Using the Sitemap, one can set certain paths to work on prefix matching, and allow requests for subpaths to be served. I'd like to specify that all requests below the given path go to a certain template. So I would like:
Menu(Loc("show_theme", Link("show" :: "theme" :: Nil, true, "/show/theme"), "Show Theme") )
to catch all requests to /show/theme/* (which it does), but serve them using the template at /show/theme (which it doesn't)
I want (e.g.) /show/theme/1 to use the template at /show/theme, and the snippets within that to pull the id out of the Req.
Is this possible? Or am I doing things the wrong way? At the moment, I'm using /show_theme?theme=1, but this is a bit ugly, and makes working with forms difficult
EDIT: I'm trying to get away from using CGI params to encode IDs, and keep them as part of the path structure
A Loc represents one page and one template. If you want to map multiple URLs to the Loc than you'll want to use Lift's URL rewriting. For example:
LiftRules.statefulRewrite.append {
case RewriteRequest(ParsePath("show" :: "theme" :: theme :: Nil, _, _, _), _, _) =>
RewriteResponse(ParsePath("show_theme" :: Nil, "", true, false), Map("theme" -> theme), false)
}
What that will do is match requests to /show/theme/* and rewrite them to /show_theme?theme={theme}. You them create your Loc to respond to that URL and you access the theme variable as a query parameter (S.param("theme")).
Note: You can do this more concisely by using the Loc DSL but I think it's good to understand what is going on behind the scenes.
If you need more help I would suggest you post a message to the Lift Google Group. I think you'll find quicker answers there than you will on SO.