Making a post request via insomnia/postman works, gives me the correct response. However, in axios, I can't seem to make it work.
It doesn't give me an error, its a status 200, but doesn't actually login like postman/insomnia does. I feel something is wrong with my axios setup
const { email, password } = req.body.params
const endpoint = `https://xxxxxxxxx.com/account/login/`
try {
const response = await axios({
method: 'post',
url: endpoint,
data: qs.stringify({
'customer[email]': email,
'customer[password]': password,
'form_type': 'customer_login'
}),
headers: {
'content-type': 'application/x-www-form-urlencoded'
}
})
res.status(200).send(response.data)
} catch (error) {
res.status(500).send(error)
}
There are 2 solutions (I hope) :
1/ Following this post, you should probably use withCredentials like this :
const { email, password } = req.body.params
const endpoint = `https://xxxxxxxxx.com/account/login/`
axios.defaults.withCredentials = true;
try {
(...)
}
2/ Following this article, you need to set your Content-Type header to application/json so the data is automatically parsed :
Axios also sets the Content-Type header to application/json. This enables web frameworks to automatically parse the data.
Postman lets you generate the code necessary to recreate your request using axios.
More information on that here: https://learning.postman.com/docs/sending-requests/generate-code-snippets/
Click the code icon to the right of Postman
Then set the code snippet language to NodeJS - Axios and you'll have the exact code necessary to recreate the request.
Related
I am having some problems with trying to customize some code for Next-Auth, an authentication library for.Next.Js.
I want to be able to use Axios to manually make the post request rather than using a <form> element.
When I do the following, I have success.
<form method='POST' action='/api/auth/signout'>
<input name='csrfToken' value={csrfToken}/>
<button type='submit'>Submit</button>
</form>
But, when I try to do the same thing with axios, it doesn't work. I am attempting to call Next-auth's Signout endpoint, which I can do just fine using this html form element. I am expecting that the application with log the user out when calling this endpoint. When I do so with the form input, then it logs the user out. When calling the same endpoint with axios, it does not log the user out and instead nothing is happening
My axios request is
const submitForm = async () => {
if (csrfToken) {
const params = new URLSearchParams();
params.append("csrfToken", csrfToken);
try {
const response = await axios({
method: "POST",
url: "http://localhost:3000/api/auth/signout",
data: params,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
}).then((res) => console.log(res));
} catch (err) {
console.log(err);
}
}
};
I have tried adding additional headers that I saw on the request that works properly, like:
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-User": "?1"
I have tried making it multipart form data, passing it simply a body of {csrfToken}, and anything else I could think of.
Any tips or things that I might be overlooking?
I can't figure out why I am unable to make this work. I am using ANTD, rather than using regular html <form> elements throughout the application and would love to be able to use that additional functionality.
Edited:
I found the solution after a lot of headache. It turns out that everything was functioning as it should have previously, but Next-Auth has an issue with updating the client-side 'session' object when you make a manual change on the server side.
I fixed this by doing the following:
const res = await axios.post("/api/auth/signout", { csrfToken }).then(
async ({ request: { responseURL } }) =>
await router
.push(responseURL)
//this is from https://github.com/nextauthjs/next-auth/issues/596#issuecomment-943453568
//force the client side to refresh and revalidate since it doesn't want to do so on its own.
.then(() => document.dispatchEvent(new Event("visibilitychange")))
.catch((err) =>
console.log("err refreshing client side session ", err)
)
);
The trick that i was missing was the document.dispatchEvent(new Event('visibilitychange'). This is the magical piece that allows you to force the client side next-auth session to sync with cookies/db.
see here for more info https://github.com/nextauthjs/next-auth/issues/596#issuecomment-943453568
I was just wondering if someone could help me figure this out. My code to get the access token is:
const inputBody = 'client_id=00000000-0000-0000-0000-000000000001&secret=mySecretPassword';
const headers = {
'Content-Type':'application/x-www-form-urlencoded',
};
fetch('https://api.replicastudios.com/auth',
{
method: 'POST',
body: inputBody,
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
I then need to include the access token received from the first call in order to insert it below.
const headers = {
'Authorization':'Bearer {token}'
};
fetch('https://api.replicastudios.com/voice',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
What is the best way to save the access token and insert it into the second request?
Please, and one more time, please don't store users security tokens in session storage, local storage, cookies (by yourself, let browser do it securely for you), etc.
Browsers have pretty awesome way of handling those security sensitive stuff, and those ways are preventing session hijacking through XSS and bunch of other stuff.
Proper way of doing things:
On the frontend you call your login (or in your case) auth route, and from the backend instead of sending your security token in body you need to set it in the secure cookie. One of the common ways to do it with Node+Express is like this:
res.status(200)
.cookie('auth_cookie', token, { httpOnly: true, maxAge: 86400 * 1000, sameSite: 'none', secure: true})
.json({ success: true, message });
This was one example of it, you should learn what all those arguments do here: https://developer.mozilla.org/en-US/docs/Tools/Storage_Inspector/Cookies
And on the last part, you dont need to manually include those cookies with each other request after that, if you are using Axios you can just put { withCredentials: true } and it's gonna automatically include those secured tokens in the cookie part of your request. There is a good thread already on that here: Make Axios send cookies in its requests automatically
I understand that this can seem as much work but it will make web safe(er) and it promotes good practices.
If your code is in a browser which it seems like it is, you could save the access token to session storage for use in future calls. When the tab is closed, session storage will be cleared.
const inputBody = 'client_id=00000000-0000-0000-0000-000000000001&secret=mySecretPassword';
const headers = {
'Content-Type':'application/x-www-form-urlencoded',
};
fetch('https://api.replicastudios.com/auth',
{
method: 'POST',
body: inputBody,
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
// NEW CODE
// body.access_token is my guess, you might have to change this
// based on the response
window.sessionStorage.setItem('access_token', body.access_token)
});
Then you can get the access token using:
window.sessionStorage.getItem('access_token')
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.
So I was having a look at a codebase of a NodeJS application and there were some specific functions making HTTP requests to the backend. To be exact, those functions were making a GET request to the backend and one thing that I found confusing was that in some of the functions, the headers were mentioned explicitly whereas, in some other functions who were making the GET request, there was no mention of headers (i.e. headers were not being set explicitly). Below is an example:
In the code below, the function is making a GET request and there's no mention of headers (i.e. the headers are not being set explicitly):
// Method for fetching a single post from the backend on the basis of the post ID
export const singlePost = (postID) => {
return fetch(http://localhost:8080/post/${postID}, {
method: "GET",
})
.then((response) => {
return response.json();
})
.catch((error) => {
console.log(error);
});
};
In the code below, the function is making a GET request and the headers are being set explicitly:
// Helper Method for making the call to the backend and fetching all their details of all the posts
export const list = (page) => {
return fetch(http://localhost:8080/posts/?page=${page}, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
})
.then((response) => {
return response.json();
})
.catch((error) => console.log(error));
};
Now coming to the main question, could someone please explain to me when are we supposed to set the headers explicitly not only in just GET request but in other general HTTP requests as well (i.e. POST, PUT, OPTION etc).
It would be really great if some could refer a source or explain this concept here. Thanks!
HTTP request header is the information, in the form of a text record, that a user's browser sends to a Web server containing the details of what the browser wants and will accept back from the server. The request header also contains the type, version and capabilities of the browser that is making the request so that server returns compatible data.
Check this https://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039
I am using Axios to Signup to our server. Which is returning fine now. However, I do not know how to retrieve the access token from a separate url.
The signup request looks like this:
let settings = {
url: "https://api.dev.etcetc.com/user/signup",
data: {
Username : username,
Password : password },
method: 'POST',
headers : {
"Content-Type" : "application/json"
},
transformRequest: [(data) => {
return JSON.stringify(data);
}]
};
The access token is to be retrieved from a url like:
https://api.dev.etcetc.com/token
Do I run another Axios request( this time GET instead of POST)? I have not been given any info on how to or whether to provide any config for this access token call.
maybe the url will give you a code, you can use the code to get the token in you java or php code with the apt which Axios provide