let headers = {
'Accept': xxxxx,
'Host': 'xxxx',
'Referer': 'https://xxxx/',
}
request.get(url, {
json: true,
headers: headers
}).on('response', function (response) {
let headers = response.headers['set-cookie'];
})
If I use
headers = {
'Accept': xxx,
'cookie':xxx
}
it will memory leak
According to the README of request, you can use request.jar() to set your own cookie to the request.
var j = request.jar();
var cookie = request.cookie('key1=value1');
var url = 'http://www.google.com';
j.setCookie(cookie, url);
request({url: url, jar: j}, function () {
request('http://images.google.com')
})
UPDATE:
They said,
Cookies are disabled by default (else, they would be used in subsequent requests). To enable cookies, set jar to true (either in defaults or options).
So you can enable request to use cookies just to set { jar: true }.
var request = request.defaults({jar: true})
request('http://www.google.com', function () {
request('http://images.google.com')
})
Related
I'm using sveltekit set-cookie in an endpoint but I'm unable to figure out how to set more than one cookie. I get three cookies back from expressjs server. I need to set the three of them in my endpoint.
I have this endpoint in sveltekit that fetch from an expressjs
import cookie from 'cookie';
export async function post (event) {
const info = await event.request.json()
let email = info.name
let password = info.password
let fetchresults = ""
//fetch from expressjs//
const letscookie = async () => {
let res = await fetch('http://localhost:3000/testcookie',{
method: 'POST',
credentials : 'include',
headers: {
'Accept': 'application/json',
'Content-type' : 'application/json',
},
body: JSON.stringify({
username : email,
password : password
})
})
const data = await res.json()
fetchresults = data
return data
}
let cookieresults = await letscookie()
return {
headers : {
"loginjs-cookieone" : fetchresults.accesstoken,
"loginjs-cookietwo" : fetchresults.refreshtoken,
"x-custom-header": "Whatever",
'set-cookie': cookie.serialize("loginjs", " setcookie_in_loginjs_headers")
},
body : {
//passthistofront,
//results,
cookieresults
}
}
}
My question is how to setup more than one cookie in my headers? if I do
headers : {
"loginjs-cookieone" : fetchresults.accesstoken,
"loginjs-cookietwo" : fetchresults.refreshtoken,
"x-custom-header": "Whatever",
'set-cookie': cookie.serialize("loginjs", " setcookie_in_loginjs_headers"),
'set-cookie' : [cookie.serealize("cookieone", "valueone"), cookie.serealize("cookietwo", "valuetwo")]
},
I get the last cookie set and anything before it is ignored or over written.
So how do I set more than one cookie in my headers using set-cookie?
I removed other set-cookie lines.
Just one set-cookie and put the cookies in an array like this
'set-cookie' : [cookie.serealize("cookieone", "valueone"), cookie.serealize("cookietwo", "valuetwo")]
One set-cookie in headers.
im new to this and spent all my time trying to figure out how to build a way to generate jwt tokens - given the understanding that you need them for user 'signed in' status.
i used fastapi, and when i login/register using my app, i now get a token, and 'bearer':
{access_token: 'super long string', token_type: 'bearer'}
how do i use this to show another view/page/component? what is the process? is there some sort of decoder? all the videos/tutorials i see are focused on how to get it using node or other means, but i already have it...
You will have to pass this token in your headers in order to access the API.
Consider the following Axios js example:
var axios = require('axios');
var config = {
method: 'get',
url: `http://${<your_api_url>}/v1/users/`,
headers: {
'Authorization': `${<token_type>} ${<access_token>}`
}
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
This is what I did:
Step 1 - set the state for my parent page:
const [jwtholder, setJwtHolder] = useState('non-bearer')
const [jwttoken, setJwtToken] = useState('');
const mainprops = {
// session,
jwtholder,
setJwtHolder,
jwttoken,
setJwtToken,
visitorType,
setVisitorType
};
Step 2 - adjust the conditional rendering in the parent page, and pass the states:
else if (jwtholder=='bearer' && visitorType =='buyside') {
return(
<div>
<Buyside {...mainprops}/>
</div>
)}
else if (jwtholder=='bearer' && visitorType =='sellside') {
return(
<div>
<Sellside {...mainprops}/>
</div>
)}
};
Step 3 - pass those main props through the formik component:
onSubmit={ (values, {setSubmitting, resetForm} ) => {
setTimeout(() => {
_handleLogin({mainprops, values});
resetForm();
setSubmitting(false);
}, 1000)
}}
Step 4 - use the handler to pass the request, and adjust the parent state:
export default async function _handleSubmit(mainprops,creds) {
if (creds.api == 'register'){
var publish_api = 'http://localhost:8007/register/'; //fastapi
}
else if (creds.api =='login') {publish_api = 'http://localhost:8007/login/';}//fastapi
const requestOptions = {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
// 'Content-Type': 'application/x-www-form-urlencoded',
},
body: JSON.stringify(creds.Data)
};
//wait for the promise to come back:
let response = await fetch(publish_api, requestOptions);
let authorization = await response.json()
mainprops.setJwtHolder(authorization.token_type);
mainprops.setJwtToken(authorization.access_token);
mainprops.setVisitorType('buyside')
// publish parses JSON response into native JavaScript objects
}
Obviously there are a few components in between.
When I make any future requests to other APIs, I'll include that jwttoken in the header. (I'm not sure why I repeat the word token here.)
AND add a conditional for a 401 response to change the jwtholder state.
I am using my API endpoint for authentication and setting a http only cookie with Lexik JWT token in the response when testing it with postman everything works fine the cookie gets set properly thing to note is that CORS is enabled with Nelmio Cors Bundle.
nelmio_cors:
defaults:
allow_credentials: true
origin_regex: true
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
allow_headers: ['Access-Control-Allow-Origin', 'X-Requested-With', 'X-HTTP-Method-Override', 'Content-Type', 'Accept']
expose_headers: ['Link']
max_age: 3600
Here is the LexikEvents::AUTHENTICATION_SUCCESS
<?php
namespace App\EventSubscriber;
use Symfony\Component\HttpFoundation\Response;
use Lexik\Bundle\JWTAuthenticationBundle\Events as LexikEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Lexik\Bundle\JWTAuthenticationBundle\Event\AuthenticationSuccessEvent;
use Symfony\Component\HttpFoundation\Cookie;
class LexikLoginSuccessSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
LexikEvents::AUTHENTICATION_SUCCESS => ['onAuthenticationSuccess']
];
}
public function onAuthenticationSuccess(AuthenticationSuccessEvent $event)
{
/** #var Response $response */
$response = $event->getResponse();
$hourLater = (new \DateTime())->modify('+1hours');
$cookie = new Cookie('jwt_token', $event->getData()['token'], $hourLater);
$response->headers->setCookie($cookie);
}
}
And at last is the fetch and axios config
const onSubmit = e => {
e.preventDefault();
fetch('http://127.0.0.1:8000/api/get-cookies', {
method: 'POST',
credentials: 'include',
body: JSON.stringify({
username: form.username,
password: form.password,
}),
headers: {
"Content-Type": "application/json",
}
})
.then( response => response.json()).then( json => console.log(json)).catch( error => console.log(error));
Axios.post('http://127.0.0.1:8000/api/get-cookies', {
username: form.username,
password: form.password,
}, {
withCredentials: true,
maxRedirects: 0,
headers: {
"Content-Type": "application/json",
}
}).then(response => console.log(response)).catch( error => console.log(error));
}
After firing the onSubmit function the response is indeed a JWT token but SET COOKIE header is not present and the cookies are not set.
After 3 hours of research in axios docs, reading plenty of similar questions suggesting different fixes and testing I finally came down to these things:
Step 1:
For AXIOS make sure to set the withCredentials in config to true(you are probably missing it if not you're fine just go to next step)
config = { ...yourConfig, withCredentials: true }
Axios.post(url, data, config).then.....
Note that the maxRedirects is not required(code in question)
For FETCH make sure to set credentials in config to "include"(you are probably missing it if not you're fine just go to next step)
config = { ...yourConfig, credentials: "include"
fetch(url, config).then....
Step 2:
This is the fun part, is your server running on something else than localhost domain like a 127.0.0.1:8000 url? Here is the catch Google Chrome and browser based on chrome engine will block cookies from any port postfixed urls(I'm not sure about other browsers but just in case serve your backend on http://localhost - 127.0.0.1:80, use hosts file to map your url to a domain, use localtunnel / ngrok just in case your browser decides to complain about your backend url)
Now you should be all set to store your cross origin http only cookies from response no matter the backend language it should be pretty much the same after you enable CORS.
I've got nodejs application which handles user's requests and receives cookies which i want to proxy to internal API service. How to approach this by using node-fetch?
Don't offer superagent please.
You should be able to pass along cookies by setting it in the header of your request:
const opts = {
headers: {
cookie: 'accessToken=1234abc; userId=1234'
}
};
const result = await fetch(`/some/url`, opts);
Read & write cookies like a bot
async function login() {
return fetch('<some_url>/login', {
'headers': {
'accept': '*/*',
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
'cookie': '',
},
'body': 'username=foo&password=bar',
'method': 'POST',
});
}
(async() => {
const loginResponse = await login();
const loginCookies = parseCookies(loginResponse);
})();
You may want to include: accept-language, user-agent, referer, accept-encoding, etc. (check a sample request on your Chrome DevTools via the Network tab)
For some reason the resulting cookies of node-fetch requests are not compatible with new requests, but we can parse them like this:
function parseCookies(response) {
const raw = response.headers.raw()['set-cookie'];
return raw.map((entry) => {
const parts = entry.split(';');
const cookiePart = parts[0];
return cookiePart;
}).join(';');
}
Pass cookies in your future requests through the same headers:
return fetch('<some_url>/dashboard', {
'headers': {
'accept': '*/*',
'cookie': parsedCookies,
},
'method': 'GET',
});
For simple, you can write a middleware which will include the cookies to global.fetch, like below.
const realFetch = fetch;
function cookieFetch(fetch, cookie) {
return (url, opts) => {
opts = opts || {};
return fetch(url, Object.assign(opts, {
headers: Object.assign(opts.headers || {}, { cookie })
}));
};
}
function middleware(req, res, next) {
const kuki = req.headers.cookie;
global.fetch = kuki ?
cookieFetch(realFetch, kuki) :
realFetch;
next();
}
module.exports = middleware;
I'm trying to connect to a remote server using nodejs 0.12, and i keep getting the response SELF_SIGNED_CERT_IN_CHAIN. I have looked at similar questions 1 2 but somehow their solutions don't work on my server.
I am connecting to a test environment outside of my control setted up with a self signed certificate. This is my request:
var https = require("https");
var fs = require('fs');
start();
function start()
{
var listadebancos =
{
language:"es",
command:"GET_BANKS_LIST",
merchant:
{
apiLogin:"111111111111111",
apiKey:"11111111111111111111111111",
},
test:true,
bankListInformation:
{
paymentMethod:"PSE",
paymentCountry:"CO"
}
};
var listadebancosString = JSON.stringify(listadebancos);
var headers =
{
'Content-Type': 'application/json',
'Content-Length': listadebancosString.length
};
var options= {
host: 'stg.api.payulatam.com',
rejectUnauthorized: false,
agent:false,
path: '/payments-api/4.0/service.cgi',
method: 'POST',
cert: fs.readFileSync('./stg.gateway.payulatam.crt'),
}
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var req= https.request(options, funcionRespuesta);
req.write(listadebancosString);
req.end();
function funcionRespuesta(res)
{ console.log(res);
}
}
Am i missing something obvious?
I decided to use a library call needle to make the request and this time i was able to receive the response with no SSL errors. Just in case anyone is in the same situation here is the code i used:
var listadebancos =
{
"language":"es",
"command":"GET_BANKS_LIST",
"merchant":{
"apiLogin:"111111111111111",
"apiKey:"11111111111111111111111111",
},
"test":false,
"bankListInformation":{
"paymentMethod":"PSE",
"paymentCountry":"CO"
}
};
};
// var listadebancosString = JSON.stringify(listadebancos);
var headers =
{
'Content-Type': 'application/json'
};
var options = {
host: 'stg.api.payulatam.com',
**json:true,**
path: '/payments-api/4.0/service.cgi',
method: 'GET',
headers: headers,
rejectUnauthorized: false,
requestCert: true,
agent: false,
strictSSL: false,
}
needle
.post('stg.api.payulatam.com/payments-api/4.0/service.cgi',listadebancos, options, funcionRespuesta)
.on('end', function() {
console.log('Ready-o, friend-o.');
})
function funcionRespuesta(err, resp, body)
{
console.log(err);
console.log(body);
}