I have a react application with server side rendering using Express server . I want to make a POST request using axios but it is getting blocked with CORS error :
"Access to XMLHttpRequest at 'https://xyz/abc' from origin 'http://localhost:4249' 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.
I have tried after adding allow origin headers and cors module in my server call but that didn't work
import cors from "cors";
const server = express();
server.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Methods",
"OPTIONS, GET, POST, PUT, PATCH, DELETE"
);
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization");
next();
});
server.use(express.static("dist"));
server.use(cors());
Here is the axios request :
const headers = {
Accept: "application/json",
"x-ms-version": "2019-07-11",
Authorization: token,
"x-ms-date": date,
"x-ms-documentdb-isquery": true,
"Content-Type": "application/query+json",
"x-ms-documentdb-query-enablecrosspartition": "true",
"cache-control": "no-cache",
"Access-Control-Allow-Origin": "*",
};
useEffect(() => {
axios
.post(
"https://xyz/abc",
data,
{
headers: headers,
}
)
.then(function (response) {
setres(response.data);
})
.catch(function (error) {
console.log(error);
});
}, []);
Webpack Config:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.(sass|css|scss)$/,
use: ["style-loader", "css-loader"],
},
],
},
};
I have encountered this problem before, and this is just what I did:
app.js (backend)
server.use(cors({
origin: '<YOUR_FRONTEND_URL_PATH>',
methods: 'GET,HEAD,POST,PUT,DELETE',
preflightContinue: false,
credentials: true
}));
axios request:
const resp = await axios.post(
apiUrl,
params,
{
withCredentials: true,
timeout: 10000
}
);
Related
I want to upload images to AWS S3 from my React app directly using aws-sdk.
I have setup my S3 bucket with the following policies -
Bucket Policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:DeleteObject",
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Resource": [
"arn:aws:s3:::<my-bucket-name>",
"arn:aws:s3:::<my-bucket-name>/*"
]
}
]
}
CORS Policy:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"HEAD",
"GET",
"PUT",
"POST",
"DELETE"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [
"ETag"
]
}
]
In my React app I'm using aws-sdk to upload images to S3. I have the following function -
export const uploadToS3 = (file: any) => {
AWS.config.update({
accessKeyId: S3_ACCESS_KEY,
secretAccessKey: S3_SECRET_KEY,
});
const bucket = new AWS.S3({
params: { Bucket: S3_BUCKET_NAME },
region: S3_REGION,
});
const params: any = {
ACL: "public-read",
Body: file,
Bucket: S3_BUCKET_NAME,
Key: file.name,
};
bucket
.putObject(params)
.on("httpUploadProgress", (e) => {
console.log(Math.round((e.loaded / e.total) * 100));
})
.send((error: any) => {
if (error) console.log(error);
});
};
I still get a CORS error -
Access to fetch at 'https://tribeone-nonceblox.s3-ap-south-1.amazonaws.com/' from origin 'http://localhost:3000' has been blocked by CORS policy: 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.
What should I do?
I've set up a Node Express application in Firebase Functions, and a React app in Firebase Hosting (similar to the template I built, with the exception that I've configured session cookies in express and I'm using Passport JS).
My firebase.json contains the following:
{
"hosting": {
"public": "build",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{
"source": "/api/**",
"function": "app"
}
]
}
}
If I make a direct fetch request from the React app to the API using the full absolute API url, everything works hunky dory:
try {
const url = 'https://us-central1-[my-app-name]-app.cloudfunctions.net/app/api/v1.0/auth/status';
const response = await fetch(url,
{
method: 'GET',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
}
);
json = await response.json();
console.log(json); // {"isAuthenticated":true}
} catch (error) {
throw error;
}
The API checks for the existence of a user in session and returns a response accordingly.
However, if I attempt to access the API through the rewrites proxy I've configured in the firebase.json file, using just the relative url /api/v1.0/auth/status then I still get a response (which confirms Firebase proxies the request appropriately), but the isAuthenticated flag is set to false, rather than true.
I assumed that this is because the proxied request is missing my valuable 'withCredentials' header, so I set this in the firebase.json file too:
{
"hosting": {
"public": "build",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{
"source": "/api/**",
"function": "app"
}
],
"headers": [
{
"source": "/api/**",
"headers": [
{
"key": "Access-Control-Allow-Credentials",
"value": "true"
},
{
"key": "Content-Type",
"value": "application/json"
}
]
}
]
}
}
However, this appears to have no effect. Is there something I'm missing?
Edit: On closer inspection I believe it's because the cookie header isn't being passed onto the functions app when Firebase proxies the request (the 'credentials' headers shouldn't be required as it's not cross-origin), so I believe there must be some way to tell Firebase to include cookies in the rewrite/proxied request?
You can include this code in your express configuration.
This would solve cors problem
// allow-cors
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
next();
});
I am running my application with grunt task runner, it throws me following error:
POST http://localhost:8080/stub/cms/myalerts2.json 405 (Method Not Allowed)
I have tried following things in my Gruntfile.js
connect: {
server: {
options: {
keepalive: true,
port: 8001,
protocol: 'http',
hostname: '*',
base: 'dis',
directory: 'dis',
open: {
target: 'http://localhost:8001/mydemo.html',
appname: 'open'
},
middleware: function(connect, options, middlewares) {
middlewares.unshift(function(req,res,next){
res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Methods', 'GET,HEAD,PUT,POST,DELETE');
res.setHeader('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
});
return middlewares;
}
}
}
},
Still its not allowing me to run. Any help or suggestion will me most welcome. Thanks in advance
So far i have tried following updation to my code, i am able to get rid of Method not Allowed 405 Error but currently i am getting "Failed to load resource: the server responded with a status of 404 (Not Found)"
i have modified my code as below:-
connect: {
server: {
options: {
keepalive: true,
port: 8001,
protocol: 'http',
hostname: '*',
base: 'dist',
directory: 'dist',
open: {
target: 'http://localhost:8001/myDemo.html',
appname: 'open'
},
middleware: function(connect, options, next) {
return [
function(req, res, next) {
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
next();
}];
}
}
}
},
Any suggestion will be appreciated.
After couple of irritating days finally my code works for me. Look into my code below:-
connect: {
server: {
options: {
keepalive: true,
port: 8001,
protocol: 'http',
hostname: '*',
directory: 'dist',
open: {
target: 'http://localhost:8001/myDemo.html',
},
middleware: function(connect, options, middlewares) {
middlewares.unshift(function(req, res, next) {
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
**if (req.method.toUpperCase() == 'POST') req.method='GET';**
return next();
});
return middlewares;
}
}
}
},
see the star marked line ie if (req.method.toUpperCase() == 'POST') req.method='GET'; i done this trick and its worked for me.
This aricle also helps to me https://github.com/gruntjs/grunt-contrib-connect#middleware
I am using webpack-dev-server v1.10.1 to boost up my Redux project and I have the options below:
contentBase: `http://${config.HOST}:${config.PORT}`,
quiet: false,
noInfo: true,
hot: true,
inline: true,
lazy: false,
publicPath: configWebpack.output.publicPath,
headers: {"Access-Control-Allow-Origin": "*"},
stats: {colors: true}
In the JS, I am using request from superagent to generate a HTTP GET call
request
.get(config.APIHost + apiUrl)
.set('Accept', 'application/json')
.withCredentials()
.end(function (err, res) {
if (!err && res.body) {
disptach(() => {
return {
type: actionType || GET_DATA,
payload: {
response: res.body
}
}
});
}
});
But I got the CORS error:
XMLHttpRequest cannot load http://localhost:8000/api/getContentByType?category=all. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:5050' is therefore not allowed access
Any suggestion to resolve this? Thanks a lot
Another way to work around it is to directly add the required CORS headers to the dev server:
devServer: {
...
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
}
}
Doc links
Webpack dev server
Access-Control-Allow-Headers
Access-Control-Allow-Methods
Access-Control-Allow-Origin
With webpack-dev-server 1.15.X you can use this configuration in your config file:
devServer: {
contentBase: DIST_FOLDER,
port: 8888,
// Send API requests on localhost to API server get around CORS.
proxy: {
'/api': {
target: {
host: "0.0.0.0",
protocol: 'http:',
port: 8080
},
pathRewrite: {
'^/api': ''
}
}
}
},
With this example you will redirect all calls from http://0.0.0.0:8888/api/* to http://0.0.0.0:8080/* and CORS solved
Had the same issue, but my api was on a https protocol (https://api....). Had to start the server with https and use https://localhost:8080
devServer: {
https: true,
headers: {
"Access-Control-Allow-Origin": "*",
},
// ....
}
You're running your JavaScript from localhost:5050 but your API server is localhost:8000. This violates the same origin policy, so the browser disallows it.
You can either modify your API server so that CORS is enabled, or follow the instructions on the webpack-dev-server page under "Combining with an existing server" to combine asset serving with webpack-dev-server and your own API server.
There are 2 solutions for this. first one is setting up proxy on the client side, second one is setting CORS on the server. CORS is server issue, server does not allow access from different source. Even using different ports is considered to be different source
First Solution
IN your backend code, you have to set this headers: this is example of in express node.js
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Methods",
"OPTIONS, GET, POST, PUT, PATCH, DELETE"
);
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
next();
});
Second Solution:
in webpack config.js, if you want to pass any variable, we export
module.exports=function(env){
return {}}
instead of
module.exports={}
we inject this env through the script.
"dev-server": "webpack-dev-server --env.api='https://jsonplaceholder.typicode.com/users'",
now webpack has access to this env. in webpack.config.js
module.exports = function ({
api = "https://jsonplaceholder.typicode.com/users",
}) {
return {
entry: { main: "./src/index.js" },
output: {
path: path.resolve(__dirname, "public"),
filename: "[name]-bundle.js",
publicPath: "/",
},
mode: "development",
module: {
rules: [
{
loader: "babel-loader",
test: /\.js$/,
exclude: [/node_modules/],
},
{
// Load other files, images etc
test: /\.(png|j?g|gif|ico)?$/,
use: "url-loader",
},
{
test: /\.s?css$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
],
},
//Some JavaScript bundlers may wrap the application code with eval statements in development.
//If you use Webpack, using the cheap-module-source-map setting in development to avoid this problem
devtool: "cheap-module-eval-source-map",
devServer: {
contentBase: path.join(__dirname, "public"),
historyApiFallback: true,
proxy: {
"/api": {
changeOrigin: true,
cookieDomainRewrite: "localhost",
target: api,
onProxyReq: (proxyReq) => {
if (proxyReq.getHeader("origin")) {
proxyReq.setHeader("origin", api);
}
},
},
},
},
};
};
I have an my app configured to use grunt-connect-proxy. Request reach the server and evverything is working fine apart from POST requests.
When running grunt with the verbose option set, I can see:
Proxied request: /api/data.json -> http://myProdutionDomain.com:80/beta/api/data.json
{
"host": "0.0.0.0:9000",
"connection": "keep-alive",
"content-length": "15",
"accept": "application/json, text/plain, */*",
"origin": "http://0.0.0.0:9000",
"user-agent": "Mozilla/5.0 (Macintosh; ...)",
"content-type": "application/json;charset=UTF-8",
"referer": "http://0.0.0.0:9000/",
"accept-encoding": "gzip,deflate,sdch",
"accept-language": "en",
"cookie": "some-cookie",
}
My proxies configuration is as follows:
proxies: [
{
context: '/api',
host: 'myProdutionDomain.com',
changeOrigin: true,
rewrite: {
'^/': '/beta/'
}
}
]
From Angular I just do:
$http.post(requestUrl, {'id': id});
Also tried:
request = $http.post(requestUrl, {'id': id}, {'headers': {'Content-Type': 'application/x-www-form-urlencoded'}});
Problem is the 'id' post param is never sent to the server.
Anyone has experience with this?