Why is browser using cached response headers if they are not present in the actual response? - express

I realized that a response header would be present in the Network tab of the Chrome console even if that header wasn't set in express. I found this answer suggesting disallowing caching. What confuses me is why the cached response is still used even if a request is made to the server.
request from react
const baseURL = 'http://localhost:3001'
const axiosClient = axios.create({
baseURL,
withCredentials: true,
})
let accessToken
axiosClient.interceptors.response.use((response) => {
const { data, headers } = response
//store access token in memory
accessToken = headers['x-access-token']
console.log(accessToken)
// if (accessToken) axiosClient.defaults.headers['X-Access-Token'] = accessToken
return data
})
async me() {
return await axiosClient.get('/auth/me')
}
request reaches route
router.get('/me', (req, res) => {
// res.set('X-Access-Token', 'test 4')
res.send('me')
})
vscode debug console
res.getHeaders()
{x-powered-by: 'Express', access-control-allow-origin: 'http://localhost:3000', vary: 'Origin', access-control-allow-credentials: 'true', access-control-expose-headers: 'X-Access-Token'}
req.headers
{host: 'localhost:3001', connection: 'keep-alive', sec-ch-ua: '"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"', accept: 'application/json, text/plain, */*', sec-ch-ua-mobile: '?0', …}
old token still appears in chrome
Since Chrome made a request to the server instead of just using the cached response (First, since there is no need to deliver the request to the origin server, then the closer the client and cache are, the faster the response will be), why isn't Chrome using the received response where the token header isn't present?

Related

Axios request to AEM servlet redirecting to login.html

I have a working servlet that tests properly with Postman, but I can't get the request to execute from the front end. The fact that Postman can execute the servlet with either a Get or a Post tells me the problem is likely with the front-end code.
Does anyone see where the misconfiguration is in this block? The Basic key and cookie are copied from Postman, there is no CORs problem.
const response = await axios.get(url, null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Accept': '*/*',
'Content-type': 'application/json',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, PATCH, DELETE',
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token',
'Authorization': 'Basic YWRtaW46YWRtaW4='
},
withCredentials: true,
Cookie: "cq-authoring-mode=TOUCH;",
params: {
path: rootPath,
maxCount: sourceMax
}
}).catch(err => {
console.log(err)
}, () => {
console.log(response)
}).then(res => {
console.log(res)
})
This is most likely the CSRF filter which rejects some requests that don’t contain a CSRF token. By default it checks only POST, PUT and DELETE requests.
It’s weird that it also checks your request, which seems to be a GET. Either your filter is configured differently or you sending a Content-type header – which describes the request body content type – makes axios switch the request from GET to POST (because GETs don’t have a request body and, thus, don’t need to declare their content type).
The CSRF filter can be configured in various ways and can exclude certain requests from filtering by path or user-agent:
You could also request a token from the /libs/granite/csrf/token.json endpoint and then send it along in your request. One way to do this is via the query, as the :cq_csrf_token param.

Make https request with Postman with Bearer token like different user would make it

Hi all!
I'm trying to solve a bit of load testing.
Our API has throttling on that particular endpoint, but requests are disctinted by user, the system solve from the provided token.
When I trying the same scenario from different windows/browsers the throttling is working as expected but when the request sent from Postman the response is 429.
Tried the header "Connection":"close", and disabling the "User-Agent" and not allowing the cookie reuse (ARRAffinity is by default because of azure).
Tried already to run two separate request, where the first is the token request with a user then the actual request to the endpoint where the throttling is enabled.
Tried also to send the request then in the Test part as a callback after the token request sending the request to throttled endpoint like that:
pm.test("got token", function() {
let token = pm.response.json().accessToken;
pm.expect(token).to.not.be.null;
const exportRequest = {
method: 'POST',
url: `${pm.environment.get("base_URL")}/api/Export/Gtin/Excel`,
header: {
"accept": "text/plain",
"Authorization": `bearer ${token}`,
"Content-Type": "application/json-patch+json",
"Connection": "close"
},
body:JSON.stringify({
"companyPrefixId": "098102700",
"exportType": "EveryKeys",
"includeProductInfo": true,
"productInfoLanguageCodes": null,
"exportFileMainLanguageCode": "en"
})
};
pm.sendRequest(exportRequest, (err, response) => {
pm.expect(response).to.not.be.null;
if (err) {
console.log(JSON.stringify(err));
}
});
});
I hope someone can help to solve that, thanks in advance!
Best regards

CORS 400 Bad Request with fetch, express server

I'm trying to send a POST request from 127.0.0.1:8080 to my express server in localhost:3000/trips
I'm having a lot of problem with the cors configuration
First, this is my method to do the POST request
async modifyTrip() {
let json = {
data: "test",
mezzo: "test",
coordinate: ["test"],
tappe: ["test"],
};
let modifyform = document.getElementById("add-form");
modifyform.onsubmit = async (e) => {
e.preventDefault();
await fetch("http://localhost:3000/trips", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: json,
});
};
}
On the server side if I put cors options at that point returns me that error:
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(
cors({
"Access-Control-Allow-Origin": "*",
"Allow-Methods": "GET, POST, DELETE, FETCH",
})
);
app.use("/user", userRoutes);
app.use("/trips", tripsRoutes);
If I try to change the position the error is different my it always gives me problem
app.use(
cors({
"Access-Control-Allow-Origin": "*",
"Allow-Methods": "GET, POST, DELETE, FETCH",
})
);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use("/user", userRoutes);
app.use("/trips", tripsRoutes);
I don't think the matter is of where I put it, but I can't fix this problem anyway. Maybe I have to change some headers in my client side, but i really can't figure it out
Thank you.
It's a 400 Bad Request error, so look up what that means:
The HyperText Transfer Protocol (HTTP) 400 Bad Request response status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (for example, malformed request syntax, invalid request message framing, or deceptive request routing).
So something is wrong with the request and the server is complaining (before it gets to the bit of code which would add the CORS response headers). The CORS error is a side-effect, not the main problem.
If you look at the Network tab of your browser's developer tools, you will be able to examine the request.
The body will look something like this:
[object Object]
Now, you said (using a Content-Type header) you were POSTing JSON, but [object Object] is not JSON (or even a usable representation of your data).
You need to pass JSON to body and not an object. Since you are passing an object, it gets stringified using the default JS mechanism (which gives "[object Object]").
Use JSON.stringify(your_object) to convert it to JSON.

How to enable CORS allow-origin header in express server with swagger-ui

My API server doesn't change or overwrite the Access-Control-Allow-Origin header.
I have an Angular 2+ application with an Express/Swagger-UI API.
The Access-Control-Allow-Origin header in the API cannot be '*' because I use 'withCredentials' in my requests and it's trigger an error on the browser.
I've used 'cors' for setting the CORS headers. Like this:
'use strict';
var configuration = require('./configuration');
var SwaggerExpress = require('swagger-express-mw');
var app = require('express')();
var mongoose = require('mongoose');
var bluebird = require('bluebird');
var bodyParser = require('body-parser');
var jwt = require('jsonwebtoken');
var compression = require('compression');
var cors = require('cors');
app.use(bodyParser.json({ limit: '50mb' }));
app.use(compression());
SwaggerExpress.create(config, function(err, swaggerExpress) {
if (err) { throw err; }
swaggerExpress.register(app);
var port = process.env.PORT || 10010;
mongoose.Promise = bluebird;
mongoose.connect(appConfig.dbConection());
mongoose.connection.on('error', console.error.bind(console, 'connection error: '));
mongoose.set('debug', true);
mongoose.connection.once('open', function() {
app.listen(port);
})
});
const swaggerUi = require('swagger-ui-express');
const YAML = require('yamljs');
const swaggerDocument = YAML.load('./api/swagger/swagger.yaml');
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
var allowedOrigins = ['http://localhost:4200', 'http://127.0.0.1:10010'];
app.use(cors({
origin: (origin, callback) => {
if (!origin) return callback(null, true);
if (allowedOrigins.indexOf(origin) === -1) {
return callback(new Error('The CORS policy for this site does not allow the specified Origin'), false);
}
return callback(null, true);
},
exposedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization', 'api_key', 'x-api-key'],
credentials: true
}));
The Access-Control-Allow-Origin should match the array of allowed hosts.
When I call the API from the browser, it first make an OPTIONS request, that look correct, like this:
Request URL: http://localhost:10010/v1/loginApp
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: [::1]:10010
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: x-api-key
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: http://localhost:4200
Access-Control-Expose-Headers: Origin,X-Requested-With,Content-Type,Accept,Authorization,api_key,x-api-key
Connection: keep-alive
Content-Length: 0
Date: Thu, 04 Apr 2019 08:25:53 GMT
Vary: Origin, Access-Control-Request-Headers
X-Powered-By: Express
But then it makes the GET/POST request, and then it has the default headers again:
Request URL: http://localhost:10010/v1/loginApp
Request Method: GET
Status Code: 200 OK
Remote Address: [::1]:10010
Referrer Policy: no-referrer-when-downgrade
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Origin,X-Requested-With,Content-Type,Accept,Authorization,api_key,x-api-key
Content-Length: 770
Content-Type: application/json; charset=utf-8
Date: Thu, 04 Apr 2019 08:25:53 GMT
ETag: W/"302-BwX5DjK/lUY+ueP6UZ9TgWOTw/s"
Vary: Origin
X-Powered-By: Express
I think something (probably swagger-UI) is overwriting my headers configuration, but I can't figure it out.
You need to register your CORS middleware before the Swagger GET/POST handlers.
The OPTIONS request is succeeding because Swagger doesn't register an OPTIONS handler, so the request reaches the middleware.
The GET/POST requests are failing before the Swagger handlers accept the request before it reaches the CORS middleware.
Move app.use(cors({... so it is before app.use('/api-docs', swaggerUi....
It seems as if swagger-express-mw comes with CORS support built-in, see swagger_controllers in your config/default.yaml. I had the same issue and fixed it by removing cors from there.
Like you, I suspect it's overwriting the Access-Control-Allow-Origin header but didn't have time to check it properly.

Does Axios support Set-Cookie? Is it possible to authenticate through Axios HTTP request?

I'm trying to authenticate express API back-end using Axios HTTP request call.
I was able to see 'Set-Cookie' in the response header, but cookie was not set. Is it possible to set cookies through Axios HTTP calls?
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 355
Content-Type: application/json; charset=utf-8
Date: Fri, 28 Sep 2018 05:59:01 GMT
ETag: W/"163-PAMc87SVHWkdimTJca7oRw"
Set-Cookie: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...; Max-Age=3.6; Path=/; Expires=Fri, 28 Sep 2018 05:59:04 GMT; HttpOnly
X-Powered-By: Express
Try this out!
axios.get('your_url', {withCredentials: true}); //for GET
axios.post('your_url', data, {withCredentials: true}); //for POST
axios.put('your_url', data, {withCredentials: true}); //for PUT
axios.delete('your_url', data, {withCredentials: true}); //for DELETE
For more information on this from the axios docs:
"withCredentials indicates whether or not cross-site Access-Control requests should be made using credentials" - https://github.com/axios/axios
More detail on withCredentials:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
Yes you can set cookies by Axios. The cookies need to be passed into the headers object. You can send cookies in a get/post/put/delete/etc. request:
As suggested by Aaron:
axios.get('URL', {
withCredentials: true
});
axios.post('URL', data, {
withCredentials: true
});
axios.put('URL', data, {
withCredentials: true
});
axios.delete('URL', data, {
withCredentials: true
});
Or you may also try this:
axios.get(url, {
headers: {
Cookie: "cookie1=value; cookie2=value; cookie3=value;"
}
}).then(response => {
console.log(response);
});
In case anyone else faces the problem I've had,
Here's a repost of my answer on a similar question https://stackoverflow.com/a/62821342/8479303
In my case, the network panel showed that the response had the 'Set-Cookie' header, but in axios the header wouldn't show up, and the cookie was being set.
For me, the resolution was setting the Access-Control-Expose-Headers header.
For explanation, from this comment on an issue in the axios repository I was directed to this person's notes which led me to set the Access-Control-Expose-Headers header -- and now the cookie is properly setting in the client.
So, in Express.js, I had to add the exposedHeaders option to my cors middleware:
const corsOptions = {
//To allow requests from client
origin: [
"http://localhost:3001",
"http://127.0.0.1",
"http://104.142.122.231",
],
credentials: true,
exposedHeaders: ["set-cookie"],
};
...
app.use("/", cors(corsOptions), router);
It was also important that on the axios side I use the withCredentials config in following axios requests that I wanted to include the cookies.
ex/
const { data } = await api.get("/workouts", { withCredentials: true });
I tried setting withCredentials: true but was still getting this error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:4000/users/register. (Reason: CORS request did not succeed).
CORS was configured to allow requests from the frontend port.
I had to change the default options for axios like so:
axios.defaults.withCredentials = true
And the issue was solved. No error and Set-Cookie working as expected.
cookie can't be touched, the thing is it gets bundled to request object after appended to the response object.
function sign(req,res){
res.cookie("x-token", signed, { maxAge: (new JWTService().jwtExpirySeconds *
1000) });
}
client after receiving this response just have to continue with requests, set-cookie in the name of "Cookie " will be bundled to those request, like this
caveat: when http cookie expires its is automatically removed and not bundled to request there after.