Hey I was working with fetch a normal fetch to request my API in my server, and It was working, but I found out that Axios is easier, so I tried to replace every fetch, but it looks like xhr doesn't work because of cors,
I already allowed cors when I was working with fetch, but for some reason cors is not allowed for xhr (Axios) requests
here is Axios defaults:
import axios from "axios"
import store from "#/store"
import { getLocalStorage } from "#/services/functions.services.js"
axios.defaults.baseURL = store.getters.getData("serverLink")
axios.defaults.withCredentials = true
axios.defaults.headers.common["Authorization"] = `Bearer ${getLocalStorage("access_token")} ${getLocalStorage("refresh_token")}`
and here is how I use Axios:
function fetchF(link, body, method) {
return new Promise(async (resolve, reject) => {
axios[method.toLowerCase()](link, body)
.then(rsp => {
setLocalStorage("access_token", rsp.access_token);
setLocalStorage("refresh_token", rsp.refresh_token);
resolve(rsp);
}).catch(error => {
setLocalStorage("access_token", "");
setLocalStorage("refresh_token", "");
store.dispatch("changeData", {
option: "alertEl",
value: "Please log in, and try again",
});
return resolve({ isSuccess: false, err: "Please log in, and try again" });
})
});
}
and here is how I enabled cors on the server-side:
app.use(cors({
credentials: true,
}));
here is the error:
error in the network page
If a browser sends a CORS request with credentials: true, the browser will not accept a response with 'Access-Control-Allow-Origin:*. You must sepecify Access-Control-Allow-Origin to one domain. Such as Access-Control-Allow-Origin:example.com.
Ref. https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#requests_with_credentials
This is an error with your server, because for every request, a preflight request is sent before the actual one..
And from the error 'PreflightWildcardOriginNotAllowed' basically means that in your server configurations you have the list of domains set to the wildcard '*'
So just change your cors options in the server for 'Access-Control-Allow-Origin' to your domain instead of '*'
And if your server has it's own way of handling preflight requests, which are basically requests sent with 'OPTIONS', you can set the domains handled by that to your domain
Just to clarify how to change the Access-Control-Allow-Origin to a specific domain (#Cypherjac)
here is how:
app.use(cors({
origin: "http://localhost:8080",
credentials: true,
}));
Related
I am using vuejs / axios and I want to post data to a zapier webhook.
I've tried a number of things. However I continually get the following error:
Access to XMLHttpRequest at 'https://hooks.zapier.com/hooks/catch/7349379/owviy9/' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
Here is my code:
submit(){
axios
.post(
'https://hooks.zapier.com/hooks/catch/7349379/owviy9j/',
this.formData,
{headers: {"Accept": "application/json"}}
)
.then(function(response) {
console.log(response);
});
}
I've also tried this but can't seem to get it to work:
var data = this.formData
axios.create({ transformRequest: [(data, _headers) => JSON.stringify(data)] })
.post('https://hooks.zapier.com/hooks/catch/7349379/owviy9j/', data)
}
How do I resolve this CORS issue?
From your first example just remove:
{headers: {"Accept": "application/json"}}
Zapier dosn`t allow headers to be sent.
Complete example:
const res = await this.$axios.post('https://hooks.zapier.com/hooks/catch/xxx/xxx/',
JSON.stringify(data)
)
When you try to make requests from the same machine but with different ports. Example: Your front end is running on port 3000, while your nodejs app is running on port: 8080. For security concerns the browser doesn't let you make the api requests.
Solution: Add Cors to your NodeJs App.
npm install cors
const cors = require('cors')
const app = express();
just add a line below this: app.use(cors()); //use it as a middleware and this will resolve your issue.
I am trying to set up an AWS lambda function, however when I call the endpoint, I am getting this error message back in the console.
Access to fetch at 'https://*.execute-api.eu-west-1.amazonaws.com/default/' 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.
I have set the CORS policy on the AWS Gateway
Here is my request code... I am just trying to print out the body of the response for testing purposes.
const response = await fetch(
'https://**********.execute-api.eu-west-1.amazonaws.com/default/**************',
{
method: 'POST',
body: "{'test': 'test'}",
headers: {
'X-Api-Key': '*****************************',
},
}
);
const text: any = await response.text();
console.log(text);
Weirdly when I look in fiddler, it is sending the OPTIONS and also returning a correct response, which is currently just printing out the different headers passed to the function.
If you've lambda proxy integration enabled you'll have to add headers from lambda.
From AWS documentation CORS section
For a Lambda proxy integration or HTTP proxy integration, you can still set up the required OPTIONS response headers in API Gateway. However, your backend is responsible for returning the Access-Control-Allow-Origin and Access-Control-Allow-Headers headers, because a proxy integration doesn't return an integration response.
exports.handler = async (event) => {
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "https://www.example.com",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
you can read more here
I have created CORS middleware using CORS package. This middleware will be called before each call. Here is my implementation.
const corsMiddleware = async (req, callback) => {
const { userid } = req.headers|| req.cookies {};
let whiteList = await getWhiteListDomains(userid)
return callback(null, {
origin: whiteList,
credentials: true,
allowedHeaders: ["userid", "authorization", "content-type"]
});
};
And added this middleware before route initialization as
app.use(cors(corsMiddleware));
app.options("*", cors(corsMiddleware));
app.get("/user", (req, res, next)=>{
// code
})
From Browser I am trying to call the API as
axios({ method: "get", url: "http://localhost:3000/user", headers: {userId:"1234"} });
While debugging on the server I see
access-control-request-headers:"userid"
in the headers of the request object.
I am not able to read the custom header. This might be happening because I am trying to read the custom header before CORS initialization. But still, I want to read that custom header.
You have mainly two problems in your code.
First one, and easier to solve is that you are missing access-control-allow-origin in the option that sets the Access-Control-Allow-Headers:
return callback(null, {
origin: whiteList,
credentials: true,
allowedHeaders: [
"access-control-allow-origin",
"authorization",
"content-type",
"userid"
]
});
The second one is the most important because it is related to how CORS works.
This problem you are having is that CORS is already rejecting the petition in the pre-flight OPTIONS request. It never allows the browser to execute the GET request.
You say that you want to read the custom header userId in the pre-flight OPTIONS request but you can't. The reason is because the pre-flight OPTIONS request is created by the browser automatically and it won't use the custom headers you are setting up in the Axios call. It will only send these headers for the CORS:
Origin // URL that makes the request
Access-Control-Request-Method // Method of the request is going to be executed
Access-Control-Request-Headers // Headers allowed in the request to be executed
Because your custom header is not being sent so in the pre-flight OPTIONS when you try to access the value of userId, you get an undefined value:
const { userid } = req.headers|| req.cookies;
console.log(userid); // undefined
And because you are using that value that is not matching in your async function getWhiteListDomains probably getting another undefined, the value set up in the origin option of the CORS middleware is undefined that provokes the CORS middleware rejects the pre-flight OPTIONS request.
let whiteList = await getWhiteListDomains(userid); // userid === undefined
console.log(whitelist); // undefined
return callback(null, {
origin: whiteList, // undefined
credentials: true,
allowedHeaders: ["userid", "authorization", "content-type"]
});
I am not totally sure which is your goal trying to use your custom header as CORS check, but my advise would be when dealing with customised CORS configuration to only check the Origin header because that's its purpose: to limit and control which URLs can access to your server and resources.
If you are interested in creating any kind of authorisation or limited by user implementation in the requests received by your server, I suggest you to use a different custom middleware and not involve CORS at all like you are trying now.
you must parse your request
try this
npm i body-parser
and
const bodyParser = require('body-parser');
app.use(bodyParser.json())
I am building a simple REST API using ktor and used cors but when i send a simple get request with no headers data the server works fine but if i want the client to have say key:1 the server doesn`t respond me correctly, it says the problem is
Failed to load http://127.0.0.1:8080/test: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 403.
so here is my ktor code
install(ContentNegotiation) {
gson {
}
}
install(ForwardedHeaderSupport)
install(DefaultHeaders)
install(CORS)
{
method(HttpMethod.Options)
method(HttpMethod.Get)
method(HttpMethod.Post)
method(HttpMethod.Put)
method(HttpMethod.Delete)
method(HttpMethod.Patch)
header(HttpHeaders.AccessControlAllowHeaders)
header(HttpHeaders.ContentType)
header(HttpHeaders.AccessControlAllowOrigin)
allowCredentials = true
anyHost()
maxAge = Duration.ofDays(1)
}
...
get("test"){
val a = call.request.headers["key"]
println(a)
call.respond(Product(name = a))
}
and my javascript code looks like this....
fetch('http://shop-ix.uz:8080/test', {
headers: {
"key": "1"
})
.then(response => response.json())
.then(json => {
console.log(json);
})
please help me
You need to whitelist your headers like this:
install(CORS) {
header("key")
}
This needs to be done with every custom HTTP header you intend to use.
Make sure all the headers and required methods should be allowed during Ktor CORS installation. I was facing the same issue, then I realized that I didn't add allowHeader(HttpHeaders.AccessControlAllowOrigin)
Although in the request header it was present. Because of that I am getting forbidden error (403)!
My Request Header!
Axios({
method: 'GET',
url: 'http://127.0.0.1:8080/connect',
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
},
params: {
...
}
})
Allowing CORS
install(CORS) {
allowMethod(HttpMethod.Options)
allowMethod(HttpMethod.Post)
allowMethod(HttpMethod.Get)
allowHeader(HttpHeaders.AccessControlAllowOrigin)
allowHeader(HttpHeaders.ContentType)
anyHost()
}
Check that what your request header wants is allowed on the server during CORS.
install(CORS) {
exposeHeader("key")
}
difference between header and exposeHeader - first allow to make call with this header, but second allow to use it on client side
I use axios for calling API (in front-end).
I use the method "GET" :
import axios from 'axios';
import querystring from 'querystring';
var url = "mydomain.local",
token = "blablabla...blabla";
var configs = {
headers: {
'Authorization': 'Bearer ' + token,
'Agency': 'demo0'
}
};
var testapi = axios.create({
baseURL: 'http://api.' + url
});
testapi.get( '/relativeUrl', configs
).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});
I got a 405 Method Not Allowed. The method is "OPTIONS" but I use the method ".get()".
405 Method Not Allowed. Method OPTIONS
I test call api with postman and I get 200 OK :
postman 200 OK screenshot
Anyone has an idea ?
Like #Shilly says, OPTIONS method is pre-flight on modern browsers when Preflighted requests conditions (MDN) :
In the response header I had Allow:"GET, HEAD, POST, PUT, DELETE".
So OPTIONS method is not available and need to configure it on in the server (Apache).
I do the change on apache (/etc/apache2/sites-available/000-default.conf) :
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "*"
Header set Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
In Request headers I have :
Origin: "null" is a problem. The cause is :
file:// URLs produce a null Origin which can't be authorized via
echo-back. Don't trying to perform a CORS request from a file:// URL (see this post for more details)
After put my javascript file on a apache server, the Origin was not null but I need to add NelmioCorsBundle to my Symfony project to allow preflight
So the way to solve this npm install qs.
Then:
import qs from 'qs'
function send(params) {
return axios.post('/api/create/', qs.stringify(params))
}