CORS 400 Bad Request with fetch, express server - express

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.

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.

CORS header ‘Access-Control-Allow-Origin’ missing on response in addon but not on request

I am creating a Firefox extension which posts some data to a database.
I made all parts in a modular fashion and am now combining everything piece by piece.
As such I know that my code to POST data to the database works.
Now here is the part that stumps me :
When I then add this code to my firefox extension
I get the following error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3003/timed_shot_create. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 400.
Now ofcourse CORS was nothing new and to be expected when dealing with Cross Origin Resource Sharing, it is even in the name.
But the reason why I am here is because this pertains only to the response of the POST request. The request itself is fine and allowed with the following piece of config in the server:
app.use(
cors({
//todo change to proper origin when live
origin: "moz-extension://d07f1e99-96a0-4934-8ff4-1ce222c06d0d",
method: ["GET", "POST"],
})
);
Which was later changed to:
app.use(
cors({
origin: "*",
method: ["GET", "POST"],
})
);
And then simplified even more to:
app.use(cors())
This is in Nodejs btw using cors middleware.
But none of this seems to work when it is used inside a firefox extension, as a local client page works as intended but as soon as I add this to a firefox extension I get a CORS error specifically pertaining to the reponse message.
The client side post (in the background script of the extension) is:
async function postTimedShot(post_options) {
const response = await fetch(post_endpoint, post_options);
//console.log(response);
const json_response = await response.json();
console.log(json_response);
}
let post_options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(response_data),
};
postTimedShot(post_options);
And the api looks like this:
app.post("/timed_shot_create", (req, res) => {
console.log("Received POST request");
const data = req.body;
console.log(data);
const timeStamp = data.time_stamp;
//TODO add screenshot and Description text maybe??
//const lastName = data.last_name
const queryString =
"INSERT INTO " + timed_shots_database + " (time_stamp) VALUES (?)";
getConnection().query(queryString, [timeStamp], (err, results, fields) => {
if (err) {
console.log("Failed to insert new user: " + err);
res.sendStatus(500);
return;
}
//Todo change this message when adding more data in body
//res.header("Access-Control-Allow-Origin", "moz-extension://d07f1e99-96a0-4934-8ff4-1ce222c06d0d");
res.json({
status: "Success!!!",
time_stamp: timeStamp,
});
console.log("Inserted a new user with id: ", results.insertId);
});
});
Furthermore, this extension is only for personal use and will work with a local server under my complete control so complications due to security or cloud usage that people want to mention are appreciated but not necessary (I think, I am a bit of novice).
I will be happy to clarify anything that is unclear, or change this post if necessary, but I think it is a unique question as far as I could see on SO. Additionally if I need to provide more of the codebase I will.
I will also update this post if I find out more about this problem.
Thank you for reading :3.
After reading about this post https://stackoverflow.com/a/53025865/5055963
on SO I found out that it had to do with the permissions in the manifest of the extension.
Adding this line: "://.localhost/*".
Solved the issue for me.

Express JS - Handling POST request

I am having trouble interpreting the following POST request sent via Postman in Express.js: (sending "temp": 97.7, "device": "one")
My POST router (in ./routes/sensors) is a simple
router.post('/', function(req, res, next) {
console.log(req.body)
});
and my index.js contains
var sensorsRouter = require('./routes/sensors');
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use('/sensors', sensorsRouter);
Question: When I send the above mentioned POST request, my console understands it's a POST, but the output of req.body is empty: {}
How can I interpret the "temp" and "device" sent as a POST request in Express.js? I found many instructions involving body-parser, but as far as I understand express.json and express.urlencoded are supposed to be used instead these days.
As i see your postman settings are wrong.you are sending data as GET data in the URL even you set request type as POST. Here is my POST setting for once of my api.
1.set header content-type as application/json
2.In the body tab select raw option and json/application from dropdown box. Then give your data as json object

Vue Resource Cross-site HTTP request

Normally, when I make a jQuery request to a non-local server, it applies Cross-site HTTP request rules and initially sends an OPTIONS request to verify the existence of an endpoint and then it sends the request, i.e.
GET to domain.tld/api/get/user/data/user_id
jQuery works fine, however I would like to use Vue Resource to deal with requests. In my network log, I see only the actual request being made (no OPTIONS request initially), and no data is being received.
Anybody has an idea how to solve this?
Sample Code:
var options = {
headers: {
'Authorization': 'Bearer xxx'
}
};
this.$http.get(config.api.base_url + 'open/cities',[options])
.then(function(response){
console.log('new request');
vm.cities = response;
}, function(error){
console.log('error in .js:');
console.log(error);
});
jquery-request
Solution:
As #Anton mentioned, it's not necessary to have both requests (environment negligible). Not sure what I have changed to make it work, but the request gave me an error. It consisted in setting the headers correctly. Headers should not be passed as options but as a property of http:
this.$http({
root: config.api.base_url + 'open/cities', // url, endpoint
method: 'GET',
headers: {
'Authorization': 'Bearer xxx'
}
}).then(function(response){
console.log('new request');
vm.cities = response;
}, function(error){
console.log('error in .js:');
console.log(error);
});
Thank you guys, it was a team effort :)
Is it a requirement that an additional OPTIONS request is being made? I have created a small (32 LOC) example which works fine and retrieves the data:
https://jsfiddle.net/ct372m7x/2/
As you can see, the data is being loaded from a non-local server. The example is located on jsfiddle.net and the request is made to httpbin.org - this leads to CORS being applied (you can see the Access-Control-Allow-Origin header in the screenshot below).
What you also see is that only the GET request has been executed, no OPTIONS before that.

mootools Request class and CORS

I'm trying to use CORS to have a script do an Ajax request to geonames.
My script calls this web service method: http://www.geonames.org/export/web-services.html#findNearby
If you check the response headers of the sample call, they include:
Access-Control-Allow-Origin: *
When I try this with mootools (version 1.4.5 just downloaded):
var urlGeonames = "http://api.geonames.org/findNearbyPlaceName";
var req = new Request({
method: 'get',
url: urlGeonames,
data: {
'lat': '89.18',
'lng': '-0.37',
'username': 'myusername',
'radius': '5'
}
}).send();
then I get an error that says :
XMLHttpRequest cannot load
http://api.geonames.org/findNearbyPlaceName?lat=89.18&lng=-0.37&username=myusername&radius=5.
Origin http://127.0.0.1 is not allowed by Access-Control-Allow-Origin.</pre>
On the other hand, when I try old style Ajax code like this:
invocation = new XMLHttpRequest();
if(invocation)
{
invocation.open('GET', urlFlickr, true);
invocation.onreadystatechange = handler;
invocation.send();
}
then it works and I get the XML response in the XHR responseXML.
I found this post A CORS POST request works from plain javascript, but why not with jQuery? that is similar. But here I'm not dealing with my server so I can only work on the javascript side.
Has anyone worked with CORS and mootools and can help on this issue ?
Thanks so much
JM
Hey man check out mootools more JSONP this will solve your problem:
http://mootools.net/docs/more/Request/Request.JSONP
Also it looks like your forgetting to ask for it in JSON format from geonames.org
Try something like:
var myJSONP = new Request.JSONP({
url: 'http://api.geonames.org/findNearbyPlaceNameJSON',
data: {
'lat': '89.18',
'lng': '-0.37',
'username': 'myusername'
},
onRequest: function(url){
// a script tag is created with a src attribute equal to url
},
onComplete: function(data){
// the request was completed.
console.log(data);
}
}).send();
Hope this helps!
The first answer on this other thread:
MooTools CORS request vs native Javascript
Might help.
Basically, the X-Requested-With header is automatically sent by the Mootools with the request, but the server either has to be configured to accept that header or you can remove it using
delete foo.headers['X-Requested-With'];
Before calling
foo.send();
To allow it by the server, you can add this to the .htaccess file of your script that gives back the JSON data:
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
So yours would look like:
var myJSON = new Request({
url: 'http://api.geonames.org/findNearbyPlaceNameJSON',
data: {
'lat': '89.18',
'lng': '-0.37',
'username': 'myusername'
},
onRequest: function(url){
// a script tag is created with a src attribute equal to url
},
onComplete: function(data){
// the request was completed.
console.log(data);
}
});
delete myJSON.headers['X-Requested-With'];
myJSON.send();