Axios .get request weird behaviour - reactjs

I have the following get request:
return axios
.get<ArticlesResponse>(SUGGESTED_ARTICLES, {
headers: {
'Content-Type': 'application/json',
},
})
.then(onRequestSuccess)
.catch(onRequestError);
It returns me an object with the data I need, however, the data field inside the object is a string instead of an actual object. Anyone has any ideea about why? I looked it up and saw that adding that header above will fix the issue but it doesn't. Thanks in advance!
My onRequestSucces is:
export function onRequestSuccess<T = any>(response: AxiosResponse<T>) {
console.log('Request Successful!', response);
return response.data;
}
JSON.Parse() also won't fix it.

The problem may be due to the API returning a response that contains invalid JSON data, now JSON.parse would throw an error, but Axios manages the exception by setting the invalid JSON as string in the data property. Try using the Fetch API.

Since you're using a GET request (doesn't have a body) the 'Content-Type' is not being useful. This header is used to tell the server which type of content you're sending, but you're sending none. You should use it only on POST/PUT requests.
See this question for more details on this.
In order for your request to be read as JSON you have to set the header in the server. This will tell the browser you're receiving a JSON, which will then be parsed automatically by axios.

Related

fetch function returns 400 bad request error for content-type 'application/x-www-form-urlencoded'

This question has been asked before but those solutions i have already tried and i shall
explain along the way.
Task:
I want to send data to api with content-type as "application/x-www-form-urlencoded".
Problem:
The URL works fine in Postman and returns me the correct response. When i try the same body parameters through my Reactjs app, it responds with 400 bad request error.
What i have tried:
myBody:{
grant_type:"XYZ",
client_id:"XYZ"
}
var request = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: "POST",
body:myBody
};
Then i fetch something like this.
const data = yield fetch(complete_url,request);
I also tried to compose myBody as a formData . Still gives the same error.
Apologies i have not given the URL because of restrictions. I am looking for possibilities of errors i could make.
With 'Content-Type': 'application/x-www-form-urlencoded',
Your request body should follow certain rule (https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST).
the keys and values are encoded in key-value tuples separated by '&', with a '=' between the key and the value,
example:
grant_type =value1&client_id=value2.
So i suggest what it looks like in debugger -> network tab.
If the request body is not a problem. Then you should check if there's any special chars.
You also will need to escape symbols and special chars.

How do I retrieve data in localStorage for me to call in the axios request header?

This is my axios, how do I retrieve data in localStorage for me to call in the axios request header?
For example I want to get / post data to postman but we need a header to get the data:
import axios from 'axios'
export default axios.create({
baseURL: 'http://forexample/api',
headers: {
'timeout' : 30000,
'APP_TOKEN': 'forexampe',
'USER_TOKEN': JSON.parse(localStorage.getItem('data').data.DATA.TOKEN)
}
})
and this is a data request that I will send to Postman using the header
async componentWillMount(){
await API.post('url/api', this.state)
.then((response)=> {
let responJSON = response
})
console.log(this.state)
}
how do I retrieve data in localstorage for me to call in the axios request header?
for example I want to get / post data to postman but we need a header to get the data
and this is a data request that I will send to Postman using the header
From the docs:
The keys and the values are always strings (note that, as with objects, integer keys will be automatically converted to strings).
So the reason that you're not getting the result you expect is you're trying to access nested data as if it were a real JS object. This seems to be an issue with how you are storing the data, rather than how you are accessing it, as the localStorage.getItem('myKey') syntax you are using is ultimately correct. What you want to do is store only the single value you want to access as its own explicit key in the localStorage object and remove all of the dot notation you have after your getItem call.

why axios send OPTIONS request method not DELETE or PUT method

why I use axios.delete(url) or axios.put() to send request, but when I check request from NetWork in Chrome Dev Tools the Request Method is OPTIONS and Access-Control-Request-Method is DELETE or PUT like this:
DELETE or PUT (or other non-simple) requests first send out a preflighted OPTIONS request to determine if you're allowed to send this request. The request method is given in the Access-Control-Request-Method header.
See more here https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests
Axios uses JSON as the default content type, the call was always going with a browser as a OPTIONS call not a POST method. To overcome, we need to set the ‘Content-Type’ correctly. My configuration as following
let config={
headers: {'Content-Type' : 'application/x-www-form-urlencoded'}
}
return axios.post(postUrl,postJson,config).then(response=>{
return response.data;
}).catch(error=>{
return error;
});

Error 400 when POST'ing JSON in angularjs + Spark Single Page Application

I'm new to Single Page Application area and I try to develop app using angularjs and Spark framework. I get error 400 bad request when I want to post JSON from my website. Here is code fragment from client side:
app.controller('PostTripCtrl', function($scope, $http) {
$scope.newTrip = {};
$scope.submitForm = function() {
$http({
method : 'POST',
url : 'http://localhost:4567/trips/add',
data : $scope.newTrip,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
}
}).success(function(data) {
console.log("ok");
}).error(function(data) {
console.log("error");
console.log($scope.newTrip);
});
};
});
Values that are to be assigned to newTrip are read from appropriate inputs in html file. Here is server-side fragment:
post("/trips/add", (req, res) -> {
String tripOwner = req.queryParams("tripOwner");
String startDate = req.queryParams("startDate");
String startingPlace = req.queryParams("startingPlace");
String tripDestination = req.queryParams("tripDestination");
int tripPrice = Integer.parseInt(req.queryParams("tripPrice"));
int maxNumberOfSeats = Integer.parseInt(req.queryParams("maxNumberOfSeats"));
int seatsAlreadyOccupied = Integer.parseInt(req.queryParams("seatsAlreadyOccupied"));
tripService.createTrip(tripOwner, startDate, startingPlace, tripDestination, tripPrice, maxNumberOfSeats,
seatsAlreadyOccupied);
res.status(201);
return null;
} , json());
At the end I obtain error 400 bad request. It is strange for me that when I want to see output on the console
System.out.println(req.queryParams());
I get json array of objects with values written by me on the website. However, when I want to see such output
System.out.println(req.queryParams("tripOwner"));
I get null. Does anyone have idea what is wrong here?
I think the main problem is that you are sending data to your Spark webservice with the 'Content-Type' : 'application/x-www-form-urlencoded' header. Try sending it as 'Content-Type' : 'application/json' instead, then in your Java code declare a String to receive req.body(), you'll see all your data in there.
Note: When you try to acces your data like this req.queryParams("tripOwner"); you're not accessing post data, but you're seeking for a get parameter called tripOwner, one that could be sent like this http://localhost:8080/trips/add?tripOwner=MyValue.
I would advise using postman to post a request to your server and see if it works. Try a different content type too. Try using curl and play with the various headers you are sending. 400 suggests the wrong data is being sent or expected data is missing or the data is the wrong type but based on your code you've provided I can see nothing wrong (but see below).
When your server receives a request log all request headers being received and see what changing them does. If it works in postman then you can change your client code to mirror the headers postman is using.
Does your spark server validate the data being sent before your controller code is hit? If so ensure you are adhering to all validation rules
Also on looking at your code again your client is sending the data in the post data but your server is expecting the data in the query string and not in the post data?
What happens if your server just sends a 201 response and does nothing else? Does your client get a 201 back? If so it suggests the hook up is working but there is something wrong with the code before you return a 201, build it up slowly to fix this.
Ok, I managed to cope with that using another approach. I used Jackson and ObjectMapper according to Spark documentantion. Thanks for your answers.
You can see more about that here: https://sparktutorials.github.io/2015/04/03/spark-lombok-jackson-reduce-boilerplate.html
You're probably just needed to enable CORS(Cross-origin resource sharing) in your Spark Server, which would have allowed you to access the REST resources outside the original domain of the request.
Spark.options("/*", (request,response)->{
String accessControlRequestHeaders = request.headers("Access-Control-Request-Headers");
if (accessControlRequestHeaders != null) {
response.header("Access-Control-Allow-Headers", accessControlRequestHeaders);
}
String accessControlRequestMethod = request.headers("Access-Control-Request-Method");
if(accessControlRequestMethod != null){
response.header("Access-Control-Allow-Methods", accessControlRequestMethod);
}
return "OK";
});
Spark.before((request,response)->{
response.header("Access-Control-Allow-Origin", "*");
});
Read more about pre-flighted requests here.

"Failed to parse UUID" error message on attempting to login via TrueVault api

On attempting to login via the truvault api using angular js, I am getting this error message: Failed to parse UUID. I am passing the username, password and account_id as params. I am successful using the curl command and get the success response.
The 400 error is not described in the api docs for authorization. I am not sure about if this UUID is linked to the schema_id. Would anyone (truevault guys!!) know what I am doing wrong?
I contacted truevault support on this one. Dan helped me get through it.
I was passing the username/password/account_id as url string query parameters. I had to make two changes to the code:
1. Pass the above as form data parameters
2. add the angular-post-fix.js to my project.
(Note: I am not adding the link as there are editors who will disallow the post with links to elsewhere. It has happened in the past!)
When using Node.js, the querystring API is really useful. Just pass an object to the querystring.stringify() function, and the resulting output is ready to be sent to TrueVault for login.
Additionally, I found that adding the header 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' might be necessary (which is one of the things the Angular post-fix library does).
#orthodoc is right, but is kind of tricky how to actually build the request. Lets say we are using fetch with formData params, I'd like to add an example of a successful request:
...
var formData = new FormData();
formData.append('username', username);
formData.append('password', password);
formData.append('account_id', accountId);
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
},
body: formData
});
...

Resources