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
}
Related
I am using refined for my requests in order to ensure that the request body confronts to certain specs, such as
case class NewGenreRequest(
name: GenreNameParam,
parent: Option[GenreParentParam]
)
where
type GenreNameString = String Refined MinSize[3]
When the request body sends something with 2 characters, this results in the error Predicate taking size(me) = 2 failed: Predicate (2 < 3) did not fail.: DownField(name) in the response body. However I think this isn't the best error to return to the client.
I would like to find a way to customize this response. The logical thing to try was to write a middleware
def handleErr(resp: Response[F]): Response[F] =
resp match {
case Status.BadRequest(resp) =>
logger.info("HERE IS MY ERR")
resp.????
case _ =>
resp
}
However I need to extract the info regarding which field has failed the predicates. The response body is an fs2 Stream and I am not quite sure about how to go about effectively modifying it using the existing info in the body. I tried maping it but to no result.
Is there an easy way of modifying these error messages?
P.S.: Cross posting from http4s discord as I wasn't able to get an answer
I can't believe this isn't in the http4s documentation, and the example code I was able to dig up online (after poking around long enough to discover the UrlForm class) is not working for me.
The relevant bit of code looks like this:
case req # POST -> Root / "compose" =>
req.decode[UrlForm] { ps =>
println("ps.values: " + ps.values)
val content = ps.getFirstOrElse("content",
throw new IllegalStateException("No content given!"))
// Do something with `content`...
}
When submitting the associated form, the IllegalStateException is thrown. ps.values is an empty map (Map()).
I can see (using println) that the Content-Type is application/x-www-form-urlencoded, as expected, and I can see from my browser's Network tab that request "paramaters" (the encoded form values) are being sent properly.
The problem is that I had a filter (javax.servlet.Filter) in place that was calling getParameterMap on the HttpServletRequest. This was draining the InputStream for the request, and it was happening before the request got passed off to the servlet (BlockingHttp4sServlet) instance.
It seems to me the BlockingHttp4sServlet should raise an IllegalStateException (or something more descriptive) when it receives an InputStream with isFinished returning true. (I've filed an issue with the http4s project on Github.)
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
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())
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.