Play Framework Redirect all traffic - scala

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

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)

Send POST request with a body using scala and play framework

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.

How can I redirect all unknown URLs in lift framework?

I'm not very familiar with lift framework and wanted to know if the following use case is possible using lift framework.
On server1, Lift is serving REST webservice at following url "/contact/"
However, if the client sends request to the following URL https://server1/contact/meet/" then it is not implemented on this specific server but "might" be implemented by another server. Can Lift redirect any such unsupported URLs to some specific server? Eg, in 302 response, can Location be specified by Lift to https://server2/contact/meet/ ?
Please note that these are unknown URLs and can't be configured statically.
Yeah, I get it. Maybe you need LiftRules.dispatch and net.liftweb.http.DoRedirectResponse. Following is the code I try to solve your trouble.
// The code should in the server1; JsonDSL will be used by JsonResponse
class Boot extends Bootable with JsonDSL {
def boot {
initDispatch
}
def initDispatch {
LiftRules.dispatch.append {
case Req("contact" :: url :: Nil, _, GetRequest) => {
() => Full(
if (url == "join") {
// or other url that match what will be implemented in server1
// your implementation, say JsonResponse
JsonResponse("server1" -> true)
} else {
// if the url part does not match simply redirect to server2,
// then you have to deal with how to process the url in server2
DoRedirectResponse("https://server2/contact/meet/")
}
)
}
}
}
}
Anyway, hope it helps.

Is there a quick built in way to forward a request in the scala Play framework

I'm looking for something like
def proxy = Action.async { implicit req =>
//do something with req
val newRequest = req.map( r = r.path = "http://newurl");
forward(newRequest)
}
I saw that there is a redirect method but that only allows me to pass the request parameters and not everything else, headers, etc.
I am hoping there is something built in so I don't have to build it myself.
I'm not sure if this meets your requirements, but have you had a look into Play's WS.
The action forwardTo gets an url, fetches the according page and returns it as this request's response. It's not exactly like an forward in the Spring framework but it does the job for me.
/**
* Like an internal redirect or an proxy. The URL in the browser doesn't
* change.
*/
public Promise<Result> forwardTo(String url) {
Promise<WS.Response> response = WS.url(url).get();
return response.map(new Function<WS.Response, Result>() {
public Result apply(WS.Response response) {
// Prevent browser from caching pages - this would be an
// security issue
response().setHeader("Cache-control", "no-cache, no-store");
return ok(response.getBody()).as("text/html");
}
});
}
(I'm using Play 2.2.3)

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.