Read full request URL in Play Web Framework - scala

I am trying to read full URL which comes with #params. How can i read in Play controller? I am able to read query parameters but not route directive
ex : https://x.app.com/callback#x=1
Action.async{ implicit request =>
val fullUrl = ??? //Read full url of request
}
I tried request.uri and request.path. both are not helpful.
response of request.uri => /callback
response of request.path => /callback
There are no #params in the response.

you can use:
request.path
or
request.uri

You cant pass fragment (# part) to server, it is browser only. Use query parameter instead

Related

How get access_token from body for use in another method

Good afternoon. Slightly confused in the Gatling documentation, I can not find a solution. I want to get a token to use in another method as a header. Here is an example of the first method where I get a token:
exec(
http("HTTP Request auth")
.post("http://blabla:9001/connect/token")
.header("Content-Type","application/x-www-form-urlencoded")
.formParam("grant_type","password")
.formParam("username", "${login}")
.formParam("password", "${password}")
.formParam("client_id","ro.client")
.formParam("client_secret","secret")
.check(status is 200)
.check(header("access_token").saveAs("access_token"))
.check(header("token_type").saveAs("token_type"))
)
Here's the second method, where I want to pass the token:
.exec(
http("HTTP Request createCompany")
.post("/Companies/CreateCompany")
.header("Authorization","${token_type} + ${access_token}")
.check(status is 200)
)
As a result, writes that a token was not found:
Request:
HTTP Request auth: KO header(access_token).find(0).exists, found nothing
But then he writes:
body={"access_token":"7e8c1d997dd92f16a87fa7ffb8a88ab14eb05a8883d78fe8652d072f24b5ca4a","expires_in":31536000,"token_type":"Bearer"}
I guess I find it wrong here:
.check(header("access_token").saveAs("access_token"))
.check(header("token_type").saveAs("token_type"))
The body of the first request is a Json payload, you need to use jsonPath, which is like XPath for Json:
.check(jsonPath("$.access_token").saveAs("access_token"))
.check(jsonPath("$.token_type").saveAs("token_type"))
Also, the header of the second request will print as:
.header("Authorization", "${token_type} + ${access_token}")
=> Authorization: Bearer + 7e8c1d997dd92f16a87fa7ffb8a88ab14eb05a8883d78fe8652d072f24b5ca4a
Unless you really want the extra +, the right header construction might be:
.header("Authorization", "${token_type} ${access_token}")
One way is to do like this ->
exec { session => var access_token ='' ;
your exec code
session.setAll( "token_type" -> access_token );
}
Then token_type is available to use.

Why requests are forbidden from Google URL Shortener

#staticmethod
def _google_url_shortener(original_url):
try:
data = json.dumps({'longUrl': original_url})
result = requests.post(conf.GoogleURL, headers={
'Content-Type': 'application/json'}, data=data)
shortened_url = result.json()['id']
return shortened_url
except Exception as e:
print('err {}'.format(e))
return original_url
I am using Google URL Shortener to make my URLs shorter, from google, it says 1,000,000 requests per day, unfortunately, I got 403 ERROR after 2500+ requests have been sent out. It doesn't help even I drop the request TPS to 0.5
Can anyone help?

Using cors across two independently running local apps

I have two applications running indepepently, one taking care of my backend (written in Scala Play) then other one being my frontend (Angular with a static Node server).
I try to request data on my frontend through a form from my Scala Play app.
this.insertionOrder = function(){
$http({
method: 'POST',
url: '//localhost:9000/insertsupplier',
header: {
'Content-type': 'application/json',
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS'
},
data:{
'supplier_id': 1,
'suppliername': 'xxx',
'supplier_address': 'xxx xxx xxx xxx',
'contact': 'xxx#xxx.com',
'datecreated': '2017-10-15T09:45:00.000UTC+00:00'
}
}).then(function(response){
console.log(response);
return response.data
}, function(err){
console.log(err)
});
};
and my play app looks like this:
Controller:
def insertsupplier = Action(parse.json) { implicit request =>
val json = request.body
val sup: Supplier = json.as[Supplier]
sup.insertSql(con)
Ok("test")
}
my build.sbt contains filters:
libraryDependencies ++= Seq(
cache ,
ws,
jdbc,
filters
)
and the MyFilters.scala
class MyFilters (implicit inj:Injector) extends HttpFilters with Injectable {
implicit val as = inject[ActorSystem]
implicit val mat = ActorMaterializer()
val gzip = new GzipFilter()
val csrf = inject[CSRFFilter]
val cors = inject[CORSFilter]
//println(s"csrf: ${csrf.tokenProvider}")
//println(s"csrf: ${csrf.tokenProvider.generateToken}")
def filters = Seq(gzip,cors,csrf)
}
and finally my application.conf
play.filters.cors {
pathPrefixes = ["*"]
allowedOrigins = ["http://localhost:3000","https://localhost:3000","http://localhost:3000/*","https://localhost:3000/*"]
allowedHttpMethods = ["GET", "POST", "OPTIONS"]
allowedHttpHeaders = ["Accept"]
# preflightMaxAge = 1 hour
}
play.filters.csrf {
cookie.name = "XSRF-TOKEN"
header.name = "X-XSRF-TOKEN"
}
play.http.filters = "filters.MyFilters"
I keep getting the error "XMLHttpRequest cannot load http://localhost:9000/insertsupplier. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500."
I feel that first my CORS setup is wrong anyway --> What needs to be changed? I am new to this.
And am I even able to use cors in order to access data from localhost?
It may be that there’s nothing wrong at all with your CORS setup, because the “The response had HTTP status code 500” part of the error message indicates that the actual immediate problem is that an OPTIONS request to your server caused some unexpected failure on the server side.
From just the code snippets in the question, it’s not possible to tell what might be causing that 500 failure in the server side. It may be completely unrelated to your CORS config.
But regardless, you should drop the parts of your frontend code that are adding the header 'Access-Control-Allow-Origin' : '*', and 'Access-Control-Allow-Methods'. Those headers are response headers that must be sent from the server side, not from frontend code.
But the 'Content-type': 'application/json' part of your frontend code is valid, and assuming it’s actually necessary in order to get the expected response from the server, there’s no way you can make your request without triggering browsers to do a CORS preflight OPTIONS request.
But if the CORS preflight OPTIONS request fails, the browser never gets around to trying the POST request your code is actually attempting to send. And if your backend responds to that OPTIONS request with a 500 response, then the preflight fails. It must instead respond with a 200 or 204.

Getting 'Access denied' when calling REST service

I'm building a small app that consumes a REST service.
The REST service expects that the URL i interact with always have the API key as an URL parameter.
So no matter if i GET, POST, UPDATE or DELETE, my URL should always contain be something like this:
https://rest.service.tld:443/list?api_key=MY-KEY
https://rest.service.tld:443/lists/1/profiles/search?api_key=MY-KEY
I tried with the sample code from RestSharp webpage, but it get the statuscode Access Denied
Here's my code:
// Create client
var client = new RestClient( "https://rest.service.tld:443" );
client.Authenticator = new SimpleAuthenticator( "api_key", "MY-KEY", "", "" );
// GET list of items
var requestLists = new RestRequest( "lists", Method.GET );
IRestResponse<List<ListResponse>> listResponse = client.Execute<List<ListResponse>>( requestLists ); // Returns the correct list
// POST search
var requestProfiles = new RestRequest( "lists/1/profiles/search", Method.POST );
requestProfiles.AddParameter( "Criteria", "{\"email\":\my#email.tld\"}" );
IRestResponse profileResponse = client.Execute( requestProfiles ); // Returns 'Access Denied' status code
As far as i can tell, the POST method doesn't contain the correct querystring, instead my api_key is added as a parameter in the POST.
Is there a way to keep my API_KEY in the Querystring like i need it to be?
By default the api_key is added as a normal parameter, you need to explicitly enforce that you want the parameter to be embedded into the URL, by setting the ParameterType as follows:
var requestProfiles = new RestRequest( "lists/1/profiles/search{api_key}", Method.POST );
requestProfiles.AddParameter( "Criteria", "{\"email\":\my#email.tld\"}" );
requestProfiles.AddParameter( "api_key", MY-KEY, ParameterType.UrlSegment);
More info here

Scala Play Templates: Reverse routing with HTTP POST

when reverse routing to a GET route, i simply do
Hello
this means theres a GET route to the sayHello function. What if it was POST and needed an attached payload? is the POST implicit? how is the payload data attached?
The HTTP method for the reverse router is derived from your route configuration file.
Here is an example from a route configuration where I have two different requests with the same URL but different HTTP methods pointing to different methods:
GET /login controllers.Application.login
POST /login controllers.Application.authenticate
The login() method in the Application controller simply streams out the HTML form:
def login = Action { implicit request =>
Ok(html.loginForm(loginForm))
}
the authenticate() method however binds the request to a form allowing further processing:
def authenticate = Action { implicit request =>
loginForm.bindFromRequest.fold(
formWithErrors => BadRequest(html.loginForm(formWithErrors)),
user => {
// OTHER CODE HERE
Redirect(routes.Blog.createPost).withSession("user" -> user)
}
)
}
This second method requires a form definition in the controller:
val loginForm = Form(
tuple(
"username" -> text,
"password" -> text
) verifying ("Invalid username or password", result => result match {
case (username, password) => Account.authenticate(username, password).isDefined
})
)
So depending which method you put to the reverse router in your view, that is the HTTP method which will be used for the request.