Angular HttpClient post read headers from empty response - json

I'm trying to build my authentication on JWT. I'm using Spring filters to achieve that goal, and i'm returning positive (200) response with one header (Authorization) on successfull login. Unfortunately i'm still getting JSON parse problem from my Angular client.
Client code:
this.http.post<HttpResponse<void>>(EndPoint.LOGIN,
{'username': username, 'password': password } ,
{'headers' : new HttpHeaders ({'Content-Type' : 'application/json', 'responseType': 'text'})})
.subscribe(response => console.log(response.headers.get('Authorization')))
;
Response:
authorization โ†’Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJHZXJhbHQiLCJleHAiOjE1MjAwNTk4MzN9.813r4QmVgrnrsm4HwZID1M56hD42PLe0BvbCu-bQoQWSnxllOE0iAjS-fc-BI8R8eGGE0WPSSL0OaKxz2lxDjA
content-length โ†’0
Error:
message : "Unexpected end of JSON input"
It is working like a charm from REST client like Postman.
I was trying multiple things to get this done:
set responseType to text
add something to response body (error has changed - it can't parse first letter of new response body)
posting without generic HttpResponse object
No luck for now.

responseType is not a http header, but just an options for the http request
You also need to specify observe: response if you want to be able to retrieve the header
https://angular.io/guide/http#reading-the-full-response
Try that
this.http.post(EndPoint.LOGIN,
{'username': username, 'password': password } ,
{'headers' : new HttpHeaders ({'Content-Type' : 'application/json'}), 'responseType': 'text', observe:'response'})
.subscribe((response : any) => console.log(response.headers.get('Authorization')))
;

Related

Paypal Oauth2 Axios results in circular structure

I'm trying to get a oauth token from the paypal sandbox using axios. The request looks like this:
const response = await axios.post(
'https://api-m.sandbox.paypal.com/v1/oauth2/token',
new URLSearchParams({
'grant_type': 'client_credentials'
}),
{
auth: {
username: process.env.PP_CLIENT,
password: process.env.PP_SECRET
},
headers: {
'Accept': 'application/x-www-form-urlencoded',
'Accept-Language': 'en_US'
}
}
);
console.log(`response: ${JSON.stringify(response.data)}`);
As far as I can tell this code used to work, because I used it before. However now I'm getting the error:
"Converting circular structure to JSON
--> starting at object with constructor 'ClientRequest'
| property 'socket' -> object with constructor 'TLSSocket'
--- property '_httpMessage' closes the circle"
I have confirmed that my credentials are correct by testing it with curl, which works and by copying it directly into the code. I've also tries fetch (which always yields an empty response)

Flutter POST json request body is empty/null on server side

I am sending a post request from my flutter to a localhost api. However, the body on the server side is always empty/null. Whereas, if I send the exact same request on postman everything works fine.
String json = jsonEncode(toCheck);
Map<String,String> headers = {
"Accept": "application/json",
"content-type": "application/json",
};
var response = await http.post(
Uri.parse(userPath + 'validateUser/'),
headers: headers,
body: "{\"email\":\"david#hotmail.com\",\"username\":\"\",\"mobile_phone_number\":\"\",\"password\":\"david\"}");
print(response.statusCode);
if(response.statusCode == HttpStatus.ok){
return response.body as bool;
}
print(response.body.toString());
return false;
The status code is always 500 with the following error:
{"Message":"An error has occurred.","ExceptionMessage":"The value cannot be null"...
This error happens because the parameter "json" is null:
[HttpPost]
[Route("validateUser/", Name = "validadeUser")]
public async Task<IHttpActionResult> ValidateUser([FromBody] string json)
{
//get the username and password to validate the user
UserClient client = JsonConvert.DeserializeObject<UserClient>(json); //error happens here because the string json is null
//...
}
However, when making the same exact request on postman, everything is okay:
The host on the android emulator app is the following:
https://10.0.2.2:44304/api/user/validateUser/
PS: looks like a duplicate of Flutter POST request body is empty on server side and Flutter Dart HTTP POST request body is empty on server side but none of those solutions have worked for me, therefore I posting a new question.
It took me a while to spot the error... but in the end, I did!
Your API takes a String argument from the request body:
ValidateUser([FromBody] string json)
That may seem alright at first, since indeed, you are sending a json String as your request body. But the thing is that since you're also using these headers:
{
"Accept": "application/json",
"content-type": "application/json",
}
This bit: "content-type": "application/json" will translate your correctly formatted json String into an actual json Object! So when it reaches your API, it will no longer be a String, and so your API won't be able to receive it properly.
The solution would be to either remove the "content-type": "application/json" from your headers and keep the request body and the API function as they are, or to change the API to:
ValidateUser([FromBody] object json)
The latter is probably the most convenient, since you were going to parse it from json String to json Object anyway! ๐Ÿ™‚
(With this API function, you COULD also remove your "content-type": "application/json" bit from the headers, and then send the request body like this:
body: jsonDecode("{\"email\":\"david#hotmail.com\",\"username\":\"\",\"mobile_phone_number\":\"\",\"password\":\"david\"}"),
Or just not jsonEncode it in the first place... Just send it as an object. This will have the same effect as sending it as a json String with "content-type": "application/json" in the header.)
Btw, as a general rule, make sure you add lots of print and log statements in your code as you develop it! It will help you spot anything that didn't go quite as you had expected, along the way. ๐Ÿ˜‰ (That's how I spotted this.)
Before sending the request to the server please encode your object to complete the body property of the request. Try this:
body: json.encode({\"email\":\"david#hotmail.com\",\"username\":\"\",\"mobile_phone_number\":\"\",\"password\":\"david\"})
Cheers.

JSON is Malformed in Fetch POST request using React Native

I have a function in a React Native app that is supposed to send data to a server that I'm hosting. This function seems to be throwing errors though every time I press submit and this function is called. The function should be sending a POST request to my webserver and receive information back. It has no problem receiving information but sending is another story... The current code below is giving me an error that says "JSON Parse error: Unrecognized token '<'. But as you can see in my code below I do not even have that symbol present in the 2nd parameter of the fetch function. Occasionally, when I tweak what I have I get an error that also says 'JSON Parse error: Unexpected EOF'. I am not sure how exactly this request is I guess 'malformed'. I am pulling it straight from the docs given by Facebook. I have also tried Axiom & XMLHttpRequest and I am still seeing similar JSON errors. Anyone?
login = () => {
// check if the username is being passed off properly...
//alert(this.state.username);
fetch('MYURL', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
})
})
.then(function(response){ return response.json(); }) // transforms response into data that is readable for this app...
.then(function(data) {
console.log(data);
})
.done();
}
When I shoot that post request in Postman I get back header "Content-Type: text/html; charset=UTF-8". So you don't get json back at all, that's why it doesn't work. I would venture that you have to add the correct application/json header in your backend.

Express res.status(200).json(...) only sending json message. How to retrieve status code?

After a successful creation of new item in my database I send:
res.status(201).json({message:"Successfully Registered"});
On my angular front end I am able to console.log(res) and receive:
{message: "Successfully Registered"}
1) How do I get the status code on the front end? res.status returns undefined. The only response I'm getting is the JSON.
2) What would be the best way to confirm successful desired api calls? For example, when I log in and credentials are correct, should I check for a 200 and then proceed? Or send a custom JSON message and check if the message for example says "Successful login" then proceed?
A little bit late, but another option is to include the status in the JSON object:
res.status(201).json({message: "Successfully Registered", status: 201})
Now you can check the status in the front end doing res.status and use this to proceed with another action.
1- You can do res.status(200).send("You message here");
2- I would say your best option when doing the login and authenticating credentials is to create a session as such
req.session.user = req.body.username //username is the name attribute of the textfield
and then redirect to any page you'd like/you can also set status to 200
res.status(200);
I'm not familiar with Angular, but looking at the docs:
See https://angular.io/api/http/Response
You'll need to do something like:
http
.request('example.com')
.subscribe(response => console.log(response.status));
Sure, checking for 200 is fine. Typically with a REST API (inferred from what you've shown), after a login you're given back a JWT along with 200 OK. And any subsequent API all with that JWT will also yield a 200 OK along with the response body which is usually JSON.
You should tell your angular http client that you want to get the response status. By default, angular deserialize the response body, but you can set request option.observe:'response' to do so.
postData(model: MyModel): Observable<HttpResponse<{status: string}>> {
return this.http.post<{status: string}>(
model, { observe: 'response' });
}
See https://angular.io/guide/http#reading-the-full-response for details.
PS: sending a { status: 'message' } is not very useful, you may return an { id } or even nothing.
res.status(200).json({
status: 'success',
results: tours.length,
data:{
tour:tours
}
});
Usually, Jsend is a good choice to response, and also by convention. Absolutely you can see the 'status' in response data and the actually data you want in the data.
according to the angular guide, we can add observe in the options of our request.
getforgetpassword(email: string): Observable<any> {
const url = this.gatewayUrl + `newPasswordFor/${email}`;
return this.http.get(url, {observe: "response"});
}
using observe type as response will give total response along with request status, which you can use in your logic of controller.

Request Media Type[application/json] Error! Request Body is not JSON format issue for Extjs Ajax request

I am using Extjs 5.1.3. I have post request with params as-
{"root":{"countryId":"458","ruleId":"3386","ruleName":"Test1 \\","ruleType":"CELL_STORE","opType":"DETAILS"}}
I am creating ajax request as-
Ext.Ajax.request({
method: 'POST',
url: appurl.fetchRuleDetails,
params: win.jsonData,
callback: function(option, success, response){
})
})
From server side, response is coming as-
{
"rules":[
{
"countryId":"458",
"ruleId":"3386",
"ruleName":"Test1 \\",
"ruleType":"CELL_STORE",
"ruleParts":[
{
"seq":"1",
"attrId":"6",
"attrName":"Store Type",
"op":"=",
"val":"dsafdaf",
"charType":"GLOBAL_CHAR"
}
]
}
],
"Status":{
"StatusFlag":true,
"StatusCode":"SUCCESS",
"StatusMessage":"SUCCESS"
}
}
But in Ajax request's callback function, we are receiving response.responseText as-
Request Media Type[application/json] Error! Request Body is not JSON format.
My guess is like issue is because of rulename value as "Test1 \".
So can someone please help me whats missing.
The error message is not an ExtJS error message. If you receive an ExtJS error related to invalid JSON, it will look like this:
Uncaught Error: You're trying to decode an invalid JSON String: TestTest
My best guess is that the error message comes from the server, because it expects you to send your request as JSON. Right now you are sending it as FormData. To send the request as JSON, you have to put your object in the jsonData config and leave the params config undefined:
Ext.Ajax.request({
method: 'POST',
url: appurl.fetchRuleDetails,
jsonData: win.jsonData,
callback: function(option, success, response){
})
})
For future questions regarding server-client communication, please keep in mind that you should first check in your browser network tab what you send to the server and what the response from the server really is.