Skip to content

Instantly share code, notes, and snippets.

@nzvtrk
Last active September 13, 2024 00:50
Show Gist options
  • Save nzvtrk/ebf494441e36200312faf82ce89de9f2 to your computer and use it in GitHub Desktop.
Save nzvtrk/ebf494441e36200312faf82ce89de9f2 to your computer and use it in GitHub Desktop.
Axios create/recreate cookie session in node.js enviroment
/* Basic example of saving cookie using axios in node.js and session's recreation after expiration.
* We have to getting/saving cookie manually because WithCredential axios param use XHR and doesn't work in node.js
* Also, this example supports parallel request and send only one create session request.
* */
const BASE_URL = "https://google.com";
// Init instance of axios which works with BASE_URL
const axiosInstance = axios.create({ baseURL: BASE_URL });
const createSession = async () => {
console.log("create session");
const authParams = {
username: "username",
password: "password"
};
const resp = await axios.post(BASE_URL, authParams);
const [cookie] = resp.headers["set-cookie"]; // getting cookie from request
axiosInstance.defaults.headers.Cookie = cookie; // attaching cookie to axiosInstance for future requests
return cookie; // return Promise<cookie> because func is async
};
let isGetActiveSessionRequest = false;
let requestQueue = [];
const callRequestsFromQueue = cookie => {
requestQueue.forEach(sub => sub(cookie));
};
const addRequestToQueue = sub => {
requestQueue.push(sub);
};
const clearQueue = () => {
requestQueue = [];
};
// registering axios interceptor which handle response's errors
axiosInstance.interceptors.response.use(null, error => {
console.error(error.message); //logging here
const { response = {}, config: sourceConfig } = error;
// checking if request failed cause Unauthorized
if (response.status === 401) {
// if this request is first we set isGetActiveSessionRequest flag to true and run createSession
if (!isGetActiveSessionRequest) {
isGetActiveSessionRequest = true;
createSession().then(cookie => {
// when createSession resolve with cookie value we run all request from queue with new cookie
isGetActiveSessionRequest = false;
callRequestsFromQueue(cookie);
clearQueue(); // and clean queue
}).catch(e => {
isGetActiveSessionRequest = false; // Very important!
console.error('Create session error %s', e.message);
clearQueue();
});
}
// and while isGetActiveSessionRequest equal true we create and return new promise
const retryRequest = new Promise(resolve => {
// we push new function to queue
addRequestToQueue(cookie => {
// function takes one param 'cookie'
console.log("Retry with new session context %s request to %s", sourceConfig.method, sourceConfig.url);
sourceConfig.headers.Cookie = cookie; // setting cookie to header
resolve(axios(sourceConfig)); // and resolve promise with axios request by old config with cookie
// we resolve exactly axios request - NOT axiosInstance's request because it could call recursion
});
});
return retryRequest;
} else {
// if error is not related with Unauthorized we just reject promise
return Promise.reject(error);
}
});
@Splines
Copy link

Splines commented May 21, 2021

Sure, its about array destructuring in JavaScript. resp.headers["set-cookie"] returns array with one elem ['yourCookieHere'].
And we can use const [cookie] = resp.headers["set-cookie"]; instead of const cookie = resp.headers["set-cookie"][0];

@nzvtrk ah ok, thanks 👍

@Mengchen-He
Copy link

Have been stuck for 3h and your code works like a charm, thank you so much

@mscw
Copy link

mscw commented Jan 11, 2022

It works! Thank you so much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment