Lift RewriteResponse not finding a valid url - scala

Hi I'm having some trouble with Lift and URL rewriting. I've written a simple rewrite rule:
LiftRules.rewrite.append {
case RewriteRequest(
ParsePath(List("user", userID), _, _, _), _, _) => {
println(userID)
RewriteResponse(List("viewUser"), Map("userID" -> urlDecode(userID)))
}
}
So when I enter http://localhost:8080/user/brian I expect a call to be made to the viewUser.html file I have placed in the webroot directory.
The mark up of viewUser.html is very simple:
<lift:surround with="default" at="content">
<p>ViewUser</p>
</lift:surround>
But instead of seeing viewUser I get an error:
The Requested URL /user/brian was not found on this server
Also if I enter the URL of viewUser by hand: http://localhost:8080/user/brian I get the same error.
I am out of ideas on this one, I did find a similar error which happens through the SiteMap system.
I've tried this with a cleanly checked out lift-archetype-blank project, by adding the viewUser.html and adding the single chunk of rewrite code.

Make sure you've added "viewUser" to the site map. Without doing so Lift doesn't know where to find page.

Related

Spray.io test response not matching actual output

I'm trying to set up some tests for an API made by a coworker with spray.io, and I'm encountering some odd behavior. When a request results in an error for any reason, we want to return a JSON value along the lines of:
{"status":false,"message":"useful message here"}
This happens just fine in the actual browser. I have navigated to an unhandled route in the web browser, and I get the desired JSON value. So, I want to test this. Now, since I'm new to spray.io, I started off with the very simple test:
"leave GET requests to root path unhandled" in {
Get() ~> myRoute ~> check {
handled must beFalse
}
}
This went fine, no problems. Since it's my first time playing with spray.io, I looked at some of the sample tests for testing false routes, and wrapped myRoute with sealRoute() so I could check the response without failing tests:
"leave GET requests to root path unhandled" in {
Get() ~> sealRoute(myRoute) ~> check {
handled must beTrue
}
}
This also works fine. So, I decided to just make sure the text of the response was usable with this, before I went to the trouble of parsing JSON and verifying individual values:
"leave GET requests to root path unhandled" in {
Get() ~> sealRoute(myRoute) ~> check {
responseAs[String] contains "false"
}
}
This is failing. To investigate, I threw a simple line of code in to log the actual value of responseAs[String] to a file, and I got this:
The requested resource could not be found.
Can anyone tell me what I'm doing wrong? I'm thinking that one of the following is occurring:
responseAs[String] is doing more than taking the exact response and giving it back to me, applying some type of filter along the way
The framework itself is not fully evaluating the query, but rather making a mockup object for the test framework to evaluate, and therefore not executing the desired 'turn errors to json' methods that my co-worker has implemented
I have tried searching google and stack overflow specifically for similar issues, but I'm either not putting in the right queries, or most other people are content to have the default error messages and aren't trying to test them beyond checking handled must beFalse.
Edit - This is the relevant part of the RejectionHandler:
case MissingQueryParamRejection(paramName) :: _=>
respondWithMediaType(`application/json`) {
complete(BadRequest, toJson(Map("status" -> false, "message" -> s"Missing parameter $paramName, request denied")))
}
Okay, so with insight from here and a coworker, the problem has been found:
Basically, the custom RejectionHandler was defined within our custom Actor object, and it wasn't coming into scope in the tests. To resolve this, the following steps were taken:
Moved the definition for the custom RejectionHandler into its own object in a separate file (as it had to do its own imports, it was causing a "encountered unrecoverable cycle resolving import" error)
Imported this new object into both the original file and the test spec.
(fun fact - http://spray.io/documentation/1.2.2/spray-routing/key-concepts/rejections/#rejectionhandler seems to demonstrate the RejectionHandler as a top-level object but you can't have top-level implicit vals in Scala, hence the need for an object)

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())

Play scala openid redirect always to recover

Im trying to connect to my openid provider through play scala.
I use openID.redirectURL and than send the answer to a map function but somehow it never .sends any request to my provider. It always goes into the recover part.
My code
OpenID.redirectURL(myProviderUrl,ComeBackUrl).map( url => Redirect(url)).recover{ case t:Throwable =>{ Logger.info("recover") Redirect(routes.testCallBack.authError)}}
BTW, i dont have ide on my computer for scala, so if everything seems right at my code, i would be grateful if you would write the necessary imports for this code.
P.S. - if someone can pls edit this text to code block it would be great, im posting this through my phone..
Thanks !!
Try logging the actual error and you will probably see what is wrong:
OpenID.redirectURL(myProviderUrl, ComeBackUrl)
.map( url => Redirect(url))
.recover{
case t: Throwable =>
Logger.warn("Openid failed", t)
Redirect(routes.testCallBack.authError)
}

Why is Play! breaking apart the {format} param in routes?

Must be a syntax issue on my part, but can't quite pin it:
In my controller I have this defined:
request.format match {
case "json" => Json(output)
case "xml" => toXml(parse(output.toString))
case _ => BadRequest
}
And in my routes I have this defined:
# Map the API to the proper domain
GET /{key}/{action}/{param}.{format} API.{action}
POST /{key}/{action}/{param}.{format} API.{action}
I posted something like: /34523452345/job/today.json
So when I go to actually run the request, it takes {param} and includes the period. So the result for {param} is today.js and the {format} becomes on
The catch if I switch the period to a forward slash / it works just fine
What is the cause of the problem?
I believe you have to escape the dot as in \., as Play uses regexp in the routes files.

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.