Print the JSON response from GET request in Finagle - scala

I am trying to do a GET request and print the JSON response that I get back. The JSON response should look like this.
{
"request_status": "Success",
"workflow_step": "End"
}
Here's my code:
handle(GetStatus) { args: GetStatus.Args =>
val client: Service[http.Request, http.Response] =
Http.client.withTlsWithoutValidation.newService("idm-preprod-fe1.twitter.biz:80")
val request = http.Request(
http.Method.Get,
"/plugin/rest/groupmanagement/getStatus/Create Group Request for mygroup (1638800484991)")
request.host = "idm-preprod-fe1.twitter.biz"
Future.value(GetStatusResponse(Option(client(request).toString)))
}
Now when my client sends the request to the server, I want to print the JSON but the format that I am getting is. Can someone please guide me as how to achieve this.
Promise#1589131174(state=Transforming(WaitQueue(size=1),Promise#1823443423(state=Transforming(WaitQueue(size=1),Promise#859399396(state=Transforming(WaitQueue(size=4),Promise#1441370332(state=Transforming(WaitQueue(size=2),Promise#1459834(state=Transforming(WaitQueue(size=2),Promise#156947070(state=Transforming(WaitQueue(size=1),Promise#1739595981(state=Transforming(WaitQueue(size=1),Promise#273198152(state=Transforming(WaitQueue(size=1),Promise#478329071(state=Transforming(WaitQueue(size=2),Promise#1175786031(state=Transforming(WaitQueue(size=1),Promise#1749285277(state=Transforming(WaitQueue(size=1),Promise#1733124454(state=Transforming(WaitQueue(size=1),Promise#1257379837(state=Transforming(WaitQueue(size=1),Promise#1192050340(state=Transforming(WaitQueue(size=1),Promise#1114225943(state=Transforming(WaitQueue(size=1),Promise#1417620904(state=Transforming(WaitQueue(size=1),Promise#1638767611(state=Interruptible(WaitQueue(size=2),<function1>))))))))))))))))))))))))))))))))))

client(request) is giving you a Future[http.Response]: it represents a response that will be available some time in the future.
You cannot use toString() on it directly because it's a Future and also because even if it was not a Future it would be a Response, which is a whole HTTP response, not only the body.
I'd recommend reading more about how Future works and how to use it.
In your case, you should do something like following (pseudo code as I'm not familiar with Twitter's Future):
client(request).map { httpResponse =>
val responseBody = httpResponse.body
GetStatusResponse(Option(responseBody))
}

Related

Calling API from Saleforce is giving error code 500

I have a REST API to callout from Salesforce.
The authorization of the API is through access token.
I am able to get the access token through POST request in Salesforce. Also tested from Postman through that token and able to get a successful response.
I am using the below code to callout the API using the access token:
String endpoint_x = '*****';//Putting my endpoint here
Http httpObject;
HttpResponse response;
String accessToken;
accessToken = MyUtilityClass.getAccessToken();
jsonBody = json.serializePretty('', true);//Yes, My JSON is empty
HttpRequest request = new HttpRequest();
request.setEndpoint(endpoint_x);
request.setHeader('Authorization', 'Bearer '+accessToken);
request.setMethod('POST');
request.setBody(jsonBody);
httpObject = new Http();
response = httpObject.send(request);
System.debug('Response=' + response);
Getting Response value as below:
System.HttpResponse[Status=Internal Server Error, StatusCode=500]
I have tried putting '{}' in the Jsonbody. Added 'Content-Type' in header but nothing worked.
Where should I lookout for this?
In the Postman, I was not putting anything in the body, and getting a successful response.
To get the same behaviour, I was using empty string in Apex, like this:
jsonBody = json.serializePretty('', true);
But the parser was not working correctly.
To solve this, I created a class without any field:
class ClassForEmptyBody{
}
And used object of that class in the serializer:
ClassForEmptyBody classForEmptyBodyObject = new ClassForEmptyBody();
jsonBody = json.serializePretty(classForEmptyBodyObject , true);
Why are you passing json body if nothing is in there. Just skip setbody code and try.

How to mock response.readEnity(String.class), passing mock Response object

I want to mock response with payload as a simple string.
Below code is in my test :
Response response = mock(Response.class, RETURNS_DEEP_STUBS);
when(mockRestClient.get("someMockUrl")).thenReturn(response);
when(response.readEntity(String.class)).thenReturn("XXXYYYZZZ");
Also tried with:
Response response = Response.status(Status.OK).entity("XXXYYYZZZ").build();
MyCode looks something like this :
Response response = restClient.get(tokenUrl); // I was mocking this and getting mock response
String requestToken = response.readEntity(String.class); //failing at this line
None of the above is working.
Help is Appreciated!
I see the issue was with using the deep stubs. It was not necessary in my case.
Response mockResponse = mock(Response.class);
when(mockResponse.readEntity(String.class)).thenReturn("XXXYYYZZZ");

Verify API Response

Am getting the response of a request like this:
var response = command.PostCommand(testCommand);
I will like to validate that the response is in a json format so am doing it like this:
Assert.AreEqual("application/json", response.ContentType);
Is this way correctly or do i need to specifically validate it from the content-type header response?
You can use the IRestRequest.OnBeforeDeserialization callback to check the response content type before it gets deserialised:
var request = new RestRequest(url)
.AddQueryParameter(x, y); // whatever you need to configure
request.OnBeforeDeserialization =
response => CheckContentType(response.ContentType);
await client.PostAsync<MyResponse>(request);

Angular 2 how to read Custom error message from backend

My problem with Angular 2 that was not exist in AngularJS, that I was sending the error message as a string with backend API call in case I have error, with error status 401 as example, the problem now that I can't read this message from Angular2 http response message, while I can do that from AngularJS:
I tried the following codes and nothing was helpful:
Promise:
this._http.post('/login',{email: 'email#example.com', password: '123'})
.toPromise()
.then((resp) => console.log(resp), (error) => console.log(error));
Observable:
this._http.post('/login',{email: 'email#example.com', password: '123'})
.subscribe(response =>console.log(response), (error) => console.log(error));
And from back-end I send response as a text, for OK or Unauthorized, for OK i send back String token == UUID.randomUUID().toString();, for error I send back message like String error = " Invalid credentials ";, the problem is that the console.log works and print the text for success (token in this case), but in case error, its just prints: Response with status: 200 for URL: null.
If I change code to JSON.stringify(error) I get something like this:
{"_body":{},"status":401,"ok":false,"statusText":"Unauthorized","headers":{"null":["HTTP/1.1 401 Unauthorized"],"Access-Control-Allow-Headers":["Origin"," X-Requested-With"," Content-Type"," Accept"," Referer"," User-Agent"],"Access-Control-Allow-Met
hods":["POST"," GET"," PUT"," DELETE"," OPTIONS"],"Access-Control-Allow-Origin":["*"],"Allow":["*"],"Content-Length":["36"],"Content-Type":["text/plain; charset=utf-8"],"Date":["Tue"," 23 Aug 2016 14:53:25 GMT"]},"type":2,"url":null}
As you can see the error test not even mentioned inside the Object !!
I tried to change the response for error from backend to return json like this:
{
"message": "invalid email or password"
}
I can get the result inside _body, and I can only read it like this: console.log(error._body.message) ! but i feel its something wrong this way, and I don't want to response as a json in this case.
For angularjs (angular 1), its so simple just to print the response and everything is cool, while in angular 2 its a really problem.
What the problem, and how I can solve this issue without any refactor to backend?
Edit:
I'm using Angular 2.0.0-rc.4 and same for http : `"#angular/http": "2.0.0-rc.4"
Mothanfar
In my case I'm working with the Asp Web Api as back end,this thing is making me crazy as well, the only solution I found is transform in a json and read the message, I know is really ugly but works for me.
Regards.
CheckError(error: any) {
let servermsg: any = JSON.parse(error._body)["ModelState"]["Login"][0];
if (servermsg) {
this.showMsg = true;
this.msg = servermsg;
}
}
If you are returning JSON object from the server, you may use the below code at client side:
let errMsg: ErrorMessage = err.json();
console.log(errMsg.message)
export class ErrorMessage {
message:string;
}

Idiomatic way to create a basic HTTP Post request with Akka HTTP

I'm trying to figure out how to create a basic HTTP POST request with the Akka HTTP library. This is what I came up with:
val formData = Await.result(Marshal(FormData(combinedParams)).to[RequestEntity], Duration.Inf)
val r = HttpRequest(POST, url, headers, formData)
The thing is that it seems a bit non-idiomatic to me. Are there other ways to create a HttpEntity from FormData? Especially the fact that I have to use Await or return a Future even though the data is readily available seems overly complex for such a simple task.
You can use Marshal in a for comprehension with other Futures, such as the ones you need to send the request and unmarshall the response:
val content = for {
request <- Marshal(formData).to[RequestEntity]
response <- Http().singleRequest(HttpRequest(method = HttpMethods.POST, uri = s"http://example.com/test", entity = request))
entity <- Unmarshal(response.entity).to[String]
} yield entity
Apparently a toEntity method was added to the FormData class at some point. So this now seems like the simplest solution to the problem:
val formData = FormData(combinedParams).toEntity
val r = HttpRequest(POST, url, headers, formData)
You can also use RequestBuilding:
Http().singleRequest(RequestBuilding.Post(url, formData)).flatMap(Unmarshal(_).to[String])