I've been trying to send a GET request to an api to fetch data using Axios but always get a response object with status, headers, config, agents etc and response.data is always empty.
For example, the following code returns me an Axios response object with the hasBody set to true and data being empty.
axios.get(`https://fantasy.premierleague.com/api/leagues-classic/12000/standings/`).then(response => {console.log(response);
console.log(response.data);});
However, when I switched over to using Request library which has been deprecated, I am able to get the response body. For example, the following code works:
request(`https://fantasy.premierleague.com/api/leagues-classic/12000/standings/`, { json: true }, (err, res, body) => {
if (err) { return console.log(err); }
console.log(body);
});
Can someone tell me what am I doing wrong and how can I get the response body using axios? I'm a beginner and have spent hours trying to figure out so I would really appreciate any form of help.
It's not an axios library issue. From what I can tell, the server does't like the user-agents starting with "axios/". Specifying some user agent gives you the expected result:
const axios = require("axios");
axios.get(`https://fantasy.premierleague.com/api/leagues-classic/12000/standings`, {
headers: {
'user-agent': 'not axios',
}
}).then(response => {
console.log(response.data);
});
As for why the requests library works but axios does not: axios is setting the user-agent header to something like axios/0.21.1 or whatever version you have. requests on the other side, leaves the user-agent header unset. It's the server right to handle the request as he pleases.
I have verified the response from this URL https://fantasy.premierleague.com/api/leagues-classic/12000/standings/ - there is no data property in the response
Try like below to read the values:
It seem like your URL at https://fantasy.premierleague.com/api/leagues-classic/12000/standings/ had invalid response body.
Related
I am using getServerSideProps to fetch data from my firebase database into my Next.js application.
My code snippet looks like this:
export async function getServerSideProps(context) {
const session = await getSession(context);
const products = await fetch("https://database-73695.firebaseio.com/").then(
(res) => res.json()
);
return {
props: {
products,
session
},
};
}
The problem is that I get error message saying the following: "FetchError: invalid json response body at https://database-73695.firebaseio.com/ reason: Unexpected token F in JSON at position 0"
I have seen that some people report this error when the data fetched is actually text and not an object. I tried changing the response from res.json to res.text, but then I'm told that "text is undefined".
Does anybody have any idea of what could be happening?
UPDATE:
By testing different fetching methods, I have seen the error:
Firebase error. Please ensure that you have the URL of your Firebase Realtime Database instance configured correctly.
All fetching code (with or without getServerSideProps) work when used with other APIs.
My database URL comes from Firestore, and is formated as follows:
https://PROJECT-ID.firebaseio.com
It is located in us-central, which I know is important for the URL.
Something else that might be worth noting: the database has already a collection called "users" tied to Stripe transactions, which works.
Any ideas?
Thank you for your time.
->try adding headers:
headers:
{
Accept: 'application/json, text/plain, /'
'User-Agent': '*',
},
->try checking if data is not been fetch from the back-end
Axios POST request sends data to Express sever but Error 404
Hello, world, I am trying to build a user authentication server for a project I am working on, but I am running into a problem trying to send a POST request to my Node.js Express server.
I want to send a POST request using Axios containing a username and password from the browser. But once sending the request it gives me a 404 Not Found error. The request has to go to http://website/api/login and my Node.js code should return either "authed" or "invalid". I tested the API inside Postman and that seems to be working. I also exported the request code from Postman and tested it with fetch API, xhr, and Axios, all returning the same result.
The server receives the data and handles it properly, but when I look in the Chromium debugger it appears that the request URL is just http://website/ and not http://website/api/login. I am honestly lost and I have tried what feels like everything, but I can't seem to make it work. Any help in pointing me in the right direction would be amazing! Thank you!
The code I use for the POST request is:
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const data = JSON.stringify({"username": username, "password":password});
const config = {
method: 'post',
url: 'http://website/api/login',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios(config).then(function (response) {
console.log(JSON.stringify(response.data));
}).catch(function (err) {
console.log(err);
})
}
This is what I see in the Chromium debugger:
Headers
This is my Node.js / Express code:
app.post('/api/login', function (req, res, next) {
scriptFile.authUser(req.body, function (err, state) {
if (err) console.log(err);
else {
if (state) {
res.send("authed");
} else {
res.send("invalid");
}
}
});
})
Thank you for any help I can get.
I am stupid,
Breakdown of what happened:
Everything was working fine except that I put the input data and submit button inside a form, which will refresh the page...
I fixed it by changing the form to a div.
Hey checking your chrome console pic looks like your post request is hitting the root api address 'http://website/' and not the full path 'http://website/api/login
I have a custom Api which I secured with Azure AD like the following tutorial:
https://learn.microsoft.com/en-us/sharepoint/dev/spfx/use-aadhttpclient
Thats working great.
now I have the following Code to make a GET request to my custom API (working):
this.context.aadHttpClientFactory
.getClient('MY_API_URL')
.then((client: AadHttpClient) => {
console.log(AadHttpClient.configurations.v1);
return client
.get(
`MY_API_URL/SOME_ROUTE`,
AadHttpClient.configurations.v1
);
})
.then(response => {
var res= response.json();
return res;
}).then( (res: any[]) => {
...
HERE I WOULD LIKE TO GET MY TOKEN
});
So this is working how I expect it to work.
But the aadHttpClientFactory only supports GET and POST requests
Now my Idea was to just make some PUT/DELETE requests with jQuery and use the Bearer token I got above (tested with postman and its working).
But then I realised, that I won't get the token that easy.
When I console.log(AadHttpClient.configurations.v1) I only get this:
Sure I could just change my API to use POST instead of PUT/DELETE but that would be pretty ugly
Does anyone has an Idea on how I could get the token as a String to do custom requests with it?
AadHttpClient supports the fetch(url, configuration, options) method, where options can include all of the request configuration options supported by the Fetch API.
So, to make a DELETE request, you would do something along the lines of:
client
.get(
`MY_API_URL/SOME_ROUTE`,
AadHttpClient.configurations.v1,
{
method: 'DELETE'
}
);
I solved it now.
Maybe my answer will help someone later.
according to philippe Signoret's answer the is the fetch() function.
I had to use it like following:
this.context.aadHttpClientFactory
.getClient(api_url)
.then((client: AadHttpClient) => {
return client
.fetch(
MY_URL,
AadHttpClient.configurations.v1,
{
method: METHOD, //put/DELETE etc.
headers: [
["Content-Type", "application/json"]
],
body: JSON.stringify({
YOUR REQUEST BODY
})
}
)
});
I want to update a document in Mongo, but when I send an Axios POST request to the server with params for the updates I receive nothing but a blank object on the server side - I'm using Node.js with an Express server (MERN stack).
I have tried the qs library module and Node's querystring module. I tried including headers with
'Content-Type': 'application/x-www-form-urlencoded' and 'application/json'.
My Axios POST request:
const A = 1;
const B = 2;
const data = { A, B };
console.log(qs.stringify(data)); // A=1&B=2
axios.post(url('upVote'), qs.stringify(data));
The server route:
app.post('/upVote', async (req, res) => {
console.log(req.params); // {}
await DB.updateVote(ID, collection, voteCount);
res.end();
});
The headers as shown by Chrome's DevTools.
... Also, all my axios.get() requests work fine and grab data from Mongo and send it back to my app properly, and the url/endpoints match.
There are a couple of ways to send data to the server with axios.
I see the confusion with the documentation in axios, I have not seen this usage before and it does seem to be broken upon looking at the request logs and object.
1) axios.post receives body of the request as a second parameter. So if you want to pass parameters to axios, you should do something like this:
const B = 2;
const data = { A: 1, B: 1 };
axios.post(url('upVote'), {}, { params: data });
Note that axios will handle stringification on it's own and that the third parameter is a config object.
On the server the params will be available at request.query
2) If you want to stringify the parameters yourself, then you should append them into your URL like so
axios.post(`url('upVote')?${qs.stringify(data)}`);
Same here, data on the server will be under request.query
3) It's generally better to use the body of the post request to transfer large data payloads for convenience. You should also consider what your caching strategies are and if they rely on request url without the consideration of request body it may be a concern.
axios.post(url('upVote'), data);
In this case data on the server will be under request.body
UPD: Originally forgot to mention that you will need a body-parser middleware to access request.body.
4) You can use axios without method shorthands which may be useful for some people
axios({
method: 'POST',
url: url('upVote'),
params: data
})
This is identical to the example in 1.
And all of them return a Promise which you can .then().catch() or await.
I think you want .body instead of .params.As you are sending data in body by post using axios. You are printing params which will print nothing for this url/api .
Try
console.log(req.body) // instead of req.params
If this did not work then please show us your react code.
Moreover
In react you have to add .then() after axios else it will say unhanded promise
To get params on server side you have to make some changes
In axios (react)
axios.post(url('upVote/param'), qs.stringify(data));
In server
app.post('/upVote/:params', async (req, res) => {
console.log(req.params)
.....
})
I think you are calling res.end(). I think it should be res.send(...)
This answer should help: https://stackoverflow.com/a/29555444/1971378
I am trying to send a new push subscription to my server but am encountering an error "Uncaught (in promise) SyntaxError: Unexpected end of JSON input" and the console says it's in my index page at line 1, which obviously is not the case.
The function where I suspect the problem occurring (because error is not thrown when I comment it out) is sendSubscriptionToBackEnd(subscription) which is called in the following:
function updateSubscriptionOnServer(subscription) {
const subscriptionJson = document.querySelector('.js-subscription-json');
const subscriptionDetails = document.querySelector('.js-subscription-details');
if (subscription) {
subscriptionJson.textContent = JSON.stringify(subscription);
sendSubscriptionToBackEnd(subscription);
subscriptionDetails.classList.remove('is-invisible');
} else {
subscriptionDetails.classList.add('is-invisible');
}
}
The function itself (which precedes the above function):
function sendSubscriptionToBackEnd(subscription) {
return fetch('/path/to/app/savesub.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(subscription)
})
.then(function(response) {
if (!response.ok) {
throw new Error('Bad status code from server.');
}
return response.json();
})
.then(function(responseData) {
if (!(responseData.data && responseData.data.success)) {
throw new Error('Bad response from server.');
}
});
}
I have tried replacing single quotes with double quotes in the fetch call but that yields the same results.
I know that the JSON should be populated because it prints to the screen in the updateSubscriptionOnServer() function with subscriptionJson.textContent = JSON.stringify(subscription);, and I used that output in the google codelab's example server to receive a push successfully.
EDIT: Here is the JSON as a string, but I don't see a mistake in syntax:
{"endpoint":"https://fcm.googleapis.com/fcm/send/dLmthm1wZuc:APA91bGULRezL7SzZKywF2wiS50hXNaLqjJxJ869y8wiWLA3Y_1pHqTI458VIhJZkyOsRMO2xBS77erpmKUp-Tg0sMkYHkuUJCI8wEid1jMESeO2ExjNhNC9OS1DQT2j05BaRgckFbCN","keys":{"p256dh":"BBz2c7S5uiKR-SE2fYJrjPaxuAiFiLogxsJbl8S1A_fQrOEH4_LQjp8qocIxOFEicpcf4PHZksAtA8zKJG9pMzs=","auth":"VOHh5P-1ZTupRXTMs4VhlQ=="}}
Any ideas??
This might be a problem with the endpoint not passing the appropriate parameters in the response's header.
In Chrome's console, inside the Network tab, check the headers sent by the endpoint and it should contain this:
Example of proper response to allow requests from localhost and cross domains requests
Ask the API developer to include this in the headers:
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Credentials" : true
This happened to me also when I was running a server with Express.js and using Brave browser. In my case it was the CORs problem. I did the following and it solved the problem in my case:
(since this is an Express framework, I am using app.get)
-on the server side:
res.set({
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
});
-on client side I used Fetch to get data but disabled the CORS option
// mode: "no-cors" //disabled this in Fetch
That took care of my issues with fetching data with Express
This can be because you're not sending any JSON from the server
OR
This can be because you're sending invalid JSON.
Your code might look like
res.end();
One of the pitfalls is that returned data that is not a JSON but just a plain text payload regardless of headers set. I.e. sending out in Express via something like
res.send({a: "b"});
rather than
res.json({a: "b"});
would return this confusing error. Not easy to detect in network activity as it looks quite legit.
For someone looking here later. I received this error not because of my headers but because I was not recursively appending the response body to a string to JSON.parse later.
As per the MDN example (I've taken out some parts of their example not immediately relevant):
reader.read().then(function processText({ done, value }) {
if (done) {
console.log("Stream complete");
return;
}
result += chunk;
return reader.read().then(processText);
});
For my issue I had to
Use a named function (not an anonymous ()=>{}) inside the .then
Append the result together recursively.
Once done is true execute something else on the total appended result
Just in case this is helpful for you in the future and your issue is not header related, but related to the done value not being true with the initial JSON stream response.
I know this question has already been answered but just thought I add my thoughts.
This will happen when your response body is empty and response.json() is expecting a JSON string. Make sure that your API is returning a response body in JSON format if must be.