How to call entity(as[String]) from postman scala spray - scala

I am new to scala and spray. I'm trying to hit POST api from Postman. From front-end it is working but how can I hit from postman.
POST /api/admin/users/:userId/update-role
path("update-role") {
postCsrf {
entity(as[String]) { role => ctx =>
// TODO: This is not the optimal way to do this, but with the 2.4 time crunch, it's going in as tech debt.
}
} ~

Related

Abort spray request when aborted from reactjs

I am new to scala and spray. I am able to abort request from reactJS. And it shows in network tab of browser console that the request is cancelled. But from scala it is not aborting. In logs i can see
api is getting hitted. For Rest API I am using spray in scala.
Here is my reactJS code:
new Promise((accept, _reject) => {
fetch("/api/complete", {
method: "post",
signal: controller.signal,
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(requestBody)
})
Ans here is my scala code:
pathPrefix("complete") {
post {
entity(as[completeRequest]) { completeRequest =>
complete {
completeService()
}
}
}
}
def completeService(): Future[HttpResponse] = {
val pipeline: HttpRequest => Future[HttpResponse] = sendReceive ~> unmarshal[HttpResponse]
val response: Future[HttpResponse] = pipeline(Post(someremoteUrl.concat("complete"), botCompleteRequest)
~> addHeader("demo", "test"))
response
}
So how to abort this complete request when it is aborted from reactJS/promise
Short answer: You don't.
It does matter if it is React (or Angular, or jQuery) on the client-side and it does not matter what is on the server-side (scala, PHP, .NET).
What matters is the HTTP between client and server.
In HTTP you can't "catch" a request that is already sent. The abort function in js/browser pretty much only means that it will ignore the response. Once a request is sent and is in the network, it will hit the server, and the server will process it. The server never gets notified that the client canceled the request.
This question and the answer cover the topic quite well: https://softwareengineering.stackexchange.com/questions/362187/can-a-caller-abort-an-execution-of-code-invoked-by-http-request

Does testcafe support testing of rest api

Tests hang in the testcafe browser when you try to test a rest api url directly.
I am trying to run a test against my rest API endpoint using request hooks, but when I run the test from the command line, the browser opens the API endpoint and loads it and hangs. The test doesn't pass or fail and hangs. The rest API endpoint just returns a JSON response.
const logger = RequestLogger('https://example.com/search/suggestions?search=testkeyword');
fixture `test`
.page('https://example.com/search/suggestions?search=testkeyword');
test
.requestHooks(logger)
('test', async t => {
// Ensure that the response has been received and that its status code is 200.
await t.expect(logger.contains(record => record.response.statusCode === 200)).ok();
const logRecord = logger.requests[0];
console.log(logRecord.userAgent);
console.log(logRecord.request.url);
console.log(logRecord.request.method);
console.log(logRecord.response.statusCode);
});
I expect the test to pass checking for 200 status code, but the test hangs without showing pass/fail. Does testcafe support testing of rest API endpoints? I have checked this issue - https://github.com/DevExpress/testcafe/issues/1471 where it says testcafe doesn't support non-html pages. Please confirm.
You are right, TestCafe is intended to work with html pages, but it will use the "about:blank" page if you don't define any url. You can use the regular node.js HTTP API without request hooks for this case. Look at the following example:
import http from 'http';
const getResponseData = (url) => new Promise((resolve, reject) => {
http.get(url, res => {
const { statusCode } = res;
const contentType = res.headers['content-type'];
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => resolve({ statusCode, contentType, rawData }));
}).on('error', e => reject(e));
});
fixture `Test REST API`;
test('Simple Test', async t => {
const response = await getResponseData('http://example.com/api/1');
await t
.expect(response.statusCode).eql(200);
});
TestCafe 1.20.0+ offers the t.request method. You can use it for REST API testing. In other words, you can incorporate API testing right into your existing functional TestCafe tests. You no longer need to use any third-party libraries.
You can read about the API testing feature in the corresponding guide.

Basic Authentication in play framework

How to implement Basic Authentication for web sockets using play framework.
I am creating a web socket using play framework.
I would like to do basic authentication and send 401 if authentication fails.
Below is my code and i am not able to send "{code=401, message=unauthorized access}" as response
def ChatServer(): WebSocket = WebSocket.accept[String, String] { request =>
if (Util.doBasicAuthentication(request.headers)) {
ActorFlow.actorRef { out =>
ChatActor.props(out)
}
} else throw new RuntimeException("Unauthorized Access")
}
Whenever authentication fails, i am not able to send the response back as "unauthorized access" instead i am ending up with exceptions
As described in the Play documentation, use WebSocket.acceptOrResult:
def socket = WebSocket.acceptOrResult[String, String] { request =>
Future.successful {
if (Util.doBasicAuthentication(request.headers)) {
Right(ActorFlow.actorRef { out =>
ChatActor.props(out)
})
} else {
Left(Unauthorized)
}
}
}

Very strange/inconsistent behaviour when making a GET request to a external api

I am busy with a angular4 web app that uses the youtubeInMp3 API. Everything works as it should when downloading mp3 files using the API however it doesn't work for all videos, I'm not sure which videos give the issue, I've noticed that it often happens when the YouTube video ID contains the _ character. when it does I get the below error... I know that the issue isn't with the video as it works when I test it http://www.youtubeinmp3.com I've tried urlEncoding the id before passing it to the API, replacing _ with - and replacing _ with %20 with no success. Any idea what might be going wrong here/how I can go about fixing it?
My error (from chrome developer console)
core.es5.js:3046 Angular is running in the development mode. Call
enableProdMode() to enable the production mode.
main.bundle.js:368 id: t0sS60Jx51c main.bundle.js:788 url
main.bundle.js:789
http://www.youtubeinmp3.com/fetch/?format=JSON&video=https://www.youtube.com/watch?v=t0sS60Jx51c
main.bundle.js:376 SyntaxError: Unexpected token < in JSON at position
0
at Object.parse ()
at Response.Body.json (vendor.bundle.js:37736)
at MapSubscriber.project (main.bundle.js:791)
at MapSubscriber._next (vendor.bundle.js:22171)
at MapSubscriber.Subscriber.next (vendor.bundle.js:242)
at XMLHttpRequest.onLoad (vendor.bundle.js:38165)
at ZoneDelegate.webpackJsonp.576.ZoneDelegate.invokeTask (polyfills.bundle.js:2496)
at Object.onInvokeTask (vendor.bundle.js:5501)
at ZoneDelegate.webpackJsonp.576.ZoneDelegate.invokeTask (polyfills.bundle.js:2495)
at Zone.webpackJsonp.576.Zone.runTask (polyfills.bundle.js:2263)
When I make this request that gives me an error in the insomnia REST client I get the following response:
metahttp-equiv="refresh" content="0" url="http://www.youtubeinmp3.com/download/?video=https://www.youtube.com/watch?v=t0sS60Jx51cautostart=1n=x="
An example of a response successful request to the youtubeInMp3 Api, the id logged in the console is the YouTube video id:
id: bjLorSJAB70 main.bundle.js:788 url main.bundle.js:789
http://www.youtubeinmp3.com/fetch/?format=JSON&video=https://www.youtube.com/watch?v=bjLorSJAB70
main.bundle.js:371 Objectlength: "199"link:
"http://www.youtubeinmp3.com/download/get/?i=fOzuoPTm06oBoLw3aidWejXF7Yc2JB3T&e=33"title:
"Santo Daime EU CHAMO A CURA"proto: Object main.bundle.js:373
http://www.youtubeinmp3.com/download/get/?i=fOzuoPTm06oBoLw3aidWejXF7Yc2JB3T&e=33
My code:
//function that passes the video id to a restService for downloading:
download(id: string) {
console.log("id: " + id);
this.restService.yDownload(id)
.subscribe(
(res) => {
console.log(res);
let url = res.link;
console.log(url);
window.location.href = `${url}target="_blank"`;
}, (res) => {
console.log(res)
});
}
//rest service function for getting the download link from youtubeInMp3 api
yDownload(id: string) : Observable<any> {
let params = [
`format=JSON`,
`video=https://www.youtube.com/watch?v=${id}`
].join('&');
let queryUrl = `${this.Y_DOWNLOAD_URL}?${params}`;
console.log("url");
console.log(queryUrl);
return this.http.get(queryUrl)
.map((res: Response) => res.json())
.catch((err: any) => Observable.throw(err || 'server error'));
}

Setting cookie with spray

How would I save the "secret token" as a cookie before redirecting so that I can retrieve it later?
#Mustafa Simav's answer is correct. Everything strangely started working when I cleaned my project (deleted sbt generated files)
First of all, I don't now details of OAuth so I am not sure whether it is good idea to store token on cookie or not. However if you want to store and retrieve cookie with spray, you can do it like this:
val routes =
path("redirect") {
setCookies(HttpCookie("random_token", random_token)) {
redirect("twitter.com/authorize", Found)
}
} ~
path("get-cookie") {
parameters('token) { token =>
optionalCookie("random_token") {
case Some(random_token) if random_token == token => complete("OK")
case _ => complete("Error", BadRequest)
}
}
}
PS: Don't forget to concatenate routes with ~