POST request not returning Allow-Origin header - node.js

I'm trying to make a POST request on a AWS lambda that has cors enabled and I using the cors package in the API.
Then I make a POST request with fetch but I get this error:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
The cors package was not supposed to take tare of this or I need to do some additional configuration?
api.js
import { json, urlencoded } from 'body-parser'
import express from 'express'
import cors from 'cors'
import recipe from './routes/recipe'
import login from './routes/login'
import unit from './routes/unit'
const app = express()
app.use(cors()) // enabling cors
app.use(json())
app.use(urlencoded({ extended: true }))
app.use('/recipes', recipe)
app.use('/login', login)
app.use('/units', unit)
request.js
const params = { 'POST', body, mode: 'cors' }
return await (await fetch(baseURL + endpoint, params)).json()
recipe.js
import { Router } from 'express'
const router = Router()
router.post('/', async ({ body }, res) => {
// save recipe in database
res.json(recipeId)
})
export default router
full source code - api: https://github.com/EliasBrothers/zanzas-recipes-api/tree/beta-develop
frontend - https://github.com/EliasBrothers/zanzas-recipes-web/tree/develop

I made it work by updating the packages from the project and changing the request
const stringifiedBody = JSON.stringify(body) // added
const params = {
method,
body: stringifiedBody,
mode: 'cors',
headers: { // added
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}

I'm not sure if this is a copying error, you didn't specify the fetch method POST in right way. Sometimes a Not Found page will also be recognized as CORS problem. Have you tried to normalize your fetch parameters?
params = {
method: 'POST',
body: body,
mode:'cors'
}

Related

React - How to send a cookie along fetch and get it in the backend NodeJS?

I have a project where I set a cookie with universal-cookie.
cookies.set('auth-token', data);
I then have a fetch request:
const getMeals = async (date: Date) => {
let res= await fetch("http://127.0.0.1:5000/meals/", {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
date: date
}),
});
const data = await res.json();
console.log(data);
}
And a backend where it gets checked (NodeJs, ExpressJs):
module.exports = function(req, res, next){
const token = req.header('auth-token');
if(!token){
return res.status(401).json('Access denied!');
}
}
I see the cookie in my mozilla:
But I always get "Access denied!" -> that means the auth-token is not there...
I hardcoded the auth-token into the fetch and it worked.
I checked several websites and almost all stackoverflow posts on this theme. I also checked the fetch-api documentation, but I couldnt come up with a solution...
Both the client and the server are running on localhost.
I hope someone can help me with this topic.
UPDATE
Andreas suggested that I should either set the header(frontend) or look for cookie- instead of header-values(backend).
I decided to do the second approach.
Server.js
var cookieParser = require('cookie-parser')
const usersRouter = require('./routes/users'); //where auth.js gets imported
app.use(cors());
app.use(express.json());
app.use(cookieParser());
app.use('/users', usersRouter);
I tried changing the position of app.use(cookieParser()); to above all others - didnt help.
auth.js
module.exports = function(req, res, next){
const cookie = req.cookies['auth-token'];
console.log(cookie);
}
The problem I now have is that the cookie value is undefined even though the cookie gets displayed in FireFox.
I tried to do the steps of this post, but this doesnt work afterwards I went to their official documentation and found nothing.
I also stumbled upon this one, which makes me think that something is wrong in the frontend...
Frontend-File where I set the cookie:
import Cookies from 'universal-cookie';
const cookies = new Cookies();
const login = async () => {
let res= await fetch("http://127.0.0.1:5000/users/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: (e.target as HTMLFormElement).email.value,
password: (e.target as HTMLFormElement).password.value,
}),
});
const data = await res.json()
if(res.status === 200){
cookies.set('auth-token', data);
setUserId((jwt_decode(data) as any)._id);
navigate("/");
}else{
alert(data);
}
}
Does someone have an idea?
I could fix the problem with the help of a friend. I had to add "proxy": "http://localhost:5000/" to my package.json in my React-Project, because the port is important for the cookie so localhost:5000 and localhost:3000 are not the same for it. I could also remove the app.use(cors()) from my NodeJs-Project, because of it.
I would suggest you run your front end on http://127.0.0.1:3000. If you are already doing that then you have to call fetch with credentials options set to include.
This is because unless fetch() is called with the credentials option set to include, fetch():
won't send cookies in cross-origin requests
won't set any cookies sent back in cross-origin responses
As of August 2018, the default credentials policy changed to same-origin. Firefox was also modified in version 61.0b13)

No CORS error when making GET requests, but CORS error when making POST requests

I have a Node/Express server that interacts with a React app.
I need to make POST and GET requests, the problem is that when making POST requests I get a CORS error, the usual:
Access to fetch at 'http://localhost:9000/testAPI' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I specified on the response on the server the Access-Control-Allow-Origin header, but I am not sure if I have to set this header for a POST request as well. And if I do, what domain should it specify?
I am also not willing to use hacks like CORS extensions, or npm packages. I want to use CORS.
The server-side looks like so:
const express = require("express");
const router = express.Router();
router.get("/", (req, res, next) => {
console.log(req.url);
res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
res.send("API is working properly");
});
module.exports = router;
In the React app, the GET request looks like so (works just fine):
const res = await fetch('http://localhost:9000/testAPI');
console.log(res);
The POST request looks like so (CORS error thrown):
const res = await fetch('http://localhost:9000/testAPI', {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ someData: "POST requests are working properly" })
});
Do I need to specify some additional headers or properties on the POST request? Or do I have to modify something on the server-side?
If I will not have this problem when going live, than I do not mind using a hack like CORS extension.
You may use this package cors
// Install
npm install cors
yarn add cors
// server.js
const express = require('express');
const cors = require('cors');
const app = express();
// global middleware
app.use(cors());
// You can use route based middleware too
router.post("/", cors(), (req, res, next) => {
// process request & send response to client
});

Access to XMLHttpRequest at 'localhost:3000/users' from origin 'http://localhost:62521' has been blocked by CORS policy

I am getting this error even though I have allowed CORS in my code. This one is in Node js:
app.use(cors());
app.get('/users', (req, res) => {
res.set({
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Methods': 'POST,GET,DELETE,PUT,OPTIONS'
});
User.find({}, function(err, users){
if(err)
{
return res.status(500).send({err});
}
return res.send(users);
});
});
I am just trying to do a GET request from http://localhost:3000/users using Flutter:
import 'package:retrofit/http.dart' as head;
#head.RestApi(baseUrl: "http://localhost:3000")
abstract class ApiClient {
factory ApiClient(Dio dio, {String baseUrl}) = _ApiClient;
#head.GET("/users")
Future<User> getUsers();
}
Doing this GET request works just fine in Postman but it doesn't work in Flutter because of the CORS. Can anyone help with this?
You only allowed Headers and Method, try adding Access-Control-Allow-Origin and assigning it to * or website URLs.
res.set({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Methods': 'POST,GET,DELETE,PUT,OPTIONS'
});
Are you using Express?
Try this:
const express = require("express");
const app = express();
...
const cors = require("cors");
...
const corsOptions = {
origin: ['http://localhost:62521'],
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
};
app.use(cors(corsOptions)); // CORS policy
if u use node js ,
do this steps,
1- in ur terminal write npm install cors
2- in ur server.js write this
let cors = require("cors"); //use this
app.use(cors()); //and this

Solving CORS using a firebase function

As you know we can't fetch a url on a client side due to CORS.
I am trying to create a function, that will fetch the file for me with the right headers as an agent, and will return it to the client.
So, on Firebase Function :
exports.urlToBlob = functions.https.onRequest((request,response) => {
cors(request, response, () => {
var url = "https://..."; //request.query.url;
fetch (
url,
{
method: 'GET',
headers: { 'Accept': '*/*' }
}
)
.then ((res) => {console.log(res);return res;})
.catch((err) => response.status(400).send(err))
});
});
I can see that it will access the url and get a respond on shell simulator, but not on browser, which will return nothing.
The client suppose to access it with :
var url = "https://us-central1-myproject-6xxxx.cloudfunctions.net/urlToBlob";
$.get(
url,
{url :imgurl, platform : 'xxx'},
function(data) {
console.log(data);
}
);
I know i am doing it wrong, but i have to find a way to use the function to solve the CORS.
Have you tried use cors lib from nodejs.
You can make a configuration for cors to allow cors in your instance.
First install cors lib:
npm install cors --save
After that you can configure cors in you main module application.
As an example:
const cors = require('cors')
//cors config
app.use(cors({
origin: ['https://example.com'] //<-- Here you put the domain you want to call your api
methods: "GET, POST, PUT, DELETE",
optionsSuccessStatus:200,
credentials: true
}))
In your code:
.then ((res) => {console.log(res);return res;})
You should change to:
.then ((res) => {
console.log(res);
//return res;
response.status(200).send(res);
})

"message":"Request failed with status code 500","name":"Error","stack":"Error: Request failed with status code 500\n

I wanted to fetch data from open API from this link. According to the documentation, The HTTP method must be POST and Content-Type must be either "application/graphql" or "application/json". I used node express server to fetch the data. But when run the server I got error. From this API I wanted to display on browser public transportation timetables between one location to another location.
Ps. I never fetched Graphql open api.
const express = require("express");
const app = express();
const port = 3000;
const bodyParser = require("body-parser");
const axios = require("axios");
const morgan = require("morgan");
const cors = require("cors");
app.use(morgan("common"));
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
const url = "https://api.digitransit.fi/routing/v1/routers/hsl/index/graphql";
app.get("/hsl/timetables", async (req, res, next) => {
axios
.get(url, {
method: "POST",
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/graphql"
}
})
.then(response => res.send(response.data))
.catch(err => {
console.log("catch error", err), res.status(500).send(err);
});
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
If you notice in the Axios docs here you do not need to have the method in your options . (Remove this method: "POST",).
Also, you will want to change the request to a .post( instead of a .get( like you have
You will need to include a body in your request as well. This will be where you need to figure out what you want. I'm not sure what routes you are looking to display but as an example,
let data = {
routes(name: "10") {
gtfsId
shortName
longName
mode
}
}
You can find lots of examples on what you data should be for whatever query you want
To add it all up, you would have something like this:
axios.post(url, data, {
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/graphql"
}
})

Resources