Send POST request with a body using scala and play framework - scala

I`m trying to send post request to external url using play framework and scala. I want to add some parameters to the body also.
I want to send a post request to "http://www.posonlinedemo.tk" with parameters TransactionNo='T10000' and reqtype='T'
how could i do it?
here is my Action
def test(para:String) = Action {
val url: Option[String] = Some("http://www.posonlinedemo.tk")
url match {
case Some(url) => Redirect(url)
case None => NotFound("This URL leads nowhere. :(")
}
}

You can use the Play WS API.
As you can see in the documentation, it is that simple:
ws
.url(url)
.post(Map(
"TransactionNo" -> Seq("T10000"),
"reqtype" -> Seq("T")))
Don't forget to add ws to your library dependencies.

Related

MockWS with dynamic url

I want to parse dynamic url into case url of MockWS like this
val ws = MockWS {
case ("POST", mockServer.getUrl + "/predict-nationality") =>
Action {
Ok(Json.obj(
"ARE" -> 0.0015790796301290394,
"ARG" -> 0.0015750796301290393,
"AUS" -> 0.027795471251010895
))
}
}
However, I got error saying that stable identifier required. Only String without any modification is accepted there. But I really need to use mockServer.getUrl + "/predict-nationality" as url in this case. I also can't define it as val because of the MockWS {} scope.
How can I deal with this? any other ways to use MockWS with dynamic url? or if this can be solved with play framework or anything, I'm happy to do so too. It just that I want to mock ws request and response (written in scala)

Parse request body with custom content-type to json in Play Framework

I'm using play to proxy my API calls from the ui. For example POST:
def post(url: String) = Action { implicit request =>
Async {
WS.url(proxyUrl + request.uri)
.withQueryString(request.queryString.mapValues(_.head).toSeq: _*)
.withHeaders(request.headers.toMap.mapValues(_.head).toSeq: _*)
.post(request.body.asJson).map(response => Ok(response.body))
}
}
but this can only handle "application/json" and "text/json" content types. But now I want to make requests with custom content type: "application/vnd.MyCustomType-v1+json;charset=utf-8" and of course it doesn't work with current implementation. Have tried different solutions, but nothing seems to work. Any ideas?
I'm using play 2.1
The source for the json body parser looks like this:
def json(maxLength: Int): BodyParser[JsValue] = when(
_.contentType.exists(m => m.equalsIgnoreCase("text/json") || m.equalsIgnoreCase("application/json")),
tolerantJson(maxLength),
createBadResult("Expecting text/json or application/json body")
)
tolerantJson is, itself, a body parser that does the json parsing without a check of the content-type header, so you should just be able to use that to parse your request instead of parse.json.
If you want to go further and have a parser that checks your specific content-type header then you could use
when(
_.contentType.exists(m => m.equalsIgnoreCase(expectedContentType)),
tolerantJson(maxLength),
createBadResult("Wrong content type")
)
to create your own parser.

Play Framework Redirect all traffic

I'm slowly converting a REST API from Rails to Scala. I've got some methods working with play, but others have to fall back to the Rails server.
I want all requests to go through Play, but if they aren't implemented yet to redirect. Specifically if URL requested is play-app.com/api/v1/.* then it should be redirected to rails-app.com/api/v1/.*, with URL and all params in tact. I've tried this route:
GET /api/v1/*path
But now I don't know what to do with it.
If your route is
GET /api/v1/*path controllers.Api.v1(path: String)
Then your controller function would look something like this:
object Api extends Controller { request =>
val queryString: String = if(request.rawQueryString.nonEmpty) "?" + request.rawQueryString else ""
def v1(path: String) = Action {
TemporaryRedirect("rails-app.com/api/v1/" + path + queryString )
}
}

Basic Play framework routing and web sockets example

I'm trying to learn how to use web sockets in Play 2.1, and I'm having trouble getting the web socket URL to work with my app's routing configuration. I started with a new Play application and the Play framework documentation on websockets.
Here is my conf/routes:
# Home page
GET / controllers.Application.index
# Websocket test site
GET /wstest controllers.Application.wstest
Then I added the wstest function to my controller class:
object Application extends Controller {
def index = Action {
Ok(views.html.index("Websocket Test"))
}
def wstest = WebSocket.using[String] { request =>
// Log events to the console
val in = Iteratee.foreach[String](println).mapDone { _ =>
Logger.info("Disconnected")
}
// Send a single 'Hello!' message
val out = Enumerator("Hello!")
(in, out)
}
}
However, so far, I can only access the websocket with the URL ws://localhost:9000/wstest (using the sample code at websocket.org/echo.html). I was looking at the sample/scala/websocket-chat app that comes with the Play framework, and it uses the routing configuration file to reference the websocket, like this:
var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
var chatSocket = new WS("#routes.Application.chat(username).webSocketURL()")
I tried replacing my websocket URL with #routes.Application.wstest.webSocketURL() and #routes.Application.wstest. The first one doesn't compile. The second one compiles, but the client and server don't exchange any messages.
How can I use my Play routing configuration to access this websocket? What am I doing wrong here?
Edit
Here is a screenshot of my compilation error, "Cannot find any HTTP Request Header here":
Without the compiler error it's hard to guess what might be the problem.
Either you have to use parens because of the implicit request, i.e. #routes.Application.wstest().webSocketURL(), or you have no implicit request in scope which is needed for the webSocketURL call.
Marius is right that there was no implicit request in scope. Here's how to get it in scope:
Update the index function in the controller:
def index = Action { implicit request =>
Ok(views.html.index("Websocket Test"))
}
Add the request as a curried parameter to index.scala.html:
#(message: String)(implicit request: RequestHeader)
#main(message) {
<script>
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket("#routes.Application.wstest.webSocketURL()");
.
.
.
And now the RequestHeader is in scope.

Getting an HTTP response as Array[Byte] with Scala and Dispatch

I'm trying to download the response of an HTTP GET request as an Array[Byte] in Scala using dispatch, but the documentation is not helping and online searches didn't turn out to be helpful.
Additionally, I need to retrieve the value of a header in the response.
Could anyone please provide a working snippet, possibly with a custom header?
Thanks in advance!
Came up with my own way:
val (someHeaderVal, buf) = Http x (url(fileUrl) <:< Map("ACustomHeader" -> "MyValue") >:+ {
(headers, req) => req >> {
stream => (headers("ResponseCustomHeader").head, IOUtils.toByteArray(stream))
}
})
This seems to work just fine.