Flask API with CORS error in delete method - javascript

I have developed a rest api in Flask. All my api endpoints work fine when I test them with postman.
Now, I am developing an application with Javascript that consumes the resources of my api.
I'm having trouble consuming an endpoint that works with the delete method. Endpoints with get and post work fine, but not the delete method. I get the next CORS error:
Access to fetch at 'http://localhost:5000/contacto' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
This is my Javascript code:
let data ={id: id};
let url = "http://localhost:5000/contacto";
fetch(url, {
credentials: 'include',
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(res => res.json())
.then(res => {
alert(res.result);
});
On the server side, I use flask_cors. I configure the app with this code:
from flask import Flask, jsonify, request
from flask_cors import CORS
import controllers.userController as userController
app = Flask(__name__)
app.config['CORS_HEADERS'] = 'Content-Type'
#CORS(app)
#CORS(app, resources={r"/*": {"origins": "*"}}, send_wildcard=True)
CORS(app, resources={r"/*": {"origins": "http://127.0.0.1:5500"}})
The path of my service with delete method is this:
#app.route('/contacto', methods = ['DELETE'])
def deleteContacto():
parametros = request.args
id = parametros['id']
result = contactController.eliminar_contacto(id)
response = None
if result == True:
response = jsonify({'result':'Contacto eliminado con éxito'})
else:
response = jsonify({'result':'Error al eliminar el contacto'})
response.headers.add('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS')
return response
I need some help. I have searched and tried many possible solutions but they do not work for me. I'm a bit desperate.
Thanks in advance and regards.

I do this a bit different, but make sure you have this option set to allow delete and options methods:
'Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS'
I add them manually to the response object in flask
resp.headers.add('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS')
CORS should be setting this as a default, but maybe something is misconfigured?
see the docs:
https://flask-cors.readthedocs.io/en/latest/configuration.html

Related

Access to fetch has been blocked by CORS policy No 'Access-Control-Allow-Origin' header is present

Frontend API Code (fetch async JS):
export async function auth(username, password){
const constUSER = username
const constPASS = password
const api_url_auth = "http://127.0.0.1:5000/login/" + constUSER + "/" + constPASS
const response = await fetch(api_url_auth,{
method: "POST",
headers:{
'Access-Control-Allow-Origin':'*'
}
});
const data = await response.json();
return data
}
Backend API Code (flask Python):
#beapi.route("/login/<username>/<password>", methods = ['POST'])
#cross_origin(supports_credentials=True)
def login (username, password):
global userdetails
global account_id
#Find The Data inside the Collection Check's if the username is available
userdetails = database.get_Account_LogIn_Details(username)
databasepwr = userdetails[2] #password Database
account_id = userdetails[0] #Account Id
pwr = password
dict_true = {"response": "True"}
dict_false = {"response": "False"}
dict_NF = {"response" : "NF"}
#Returns True or False Verification Process
if userdetails != "e0101db":
if pwr == databasepwr:
database.update_Time_In(account_id= account_id, date=date, time=time )
return jsonify(dict_true)
else:
return jsonify(dict_false)
else:
return jsonify(dict_NF)
The Error:
What I did so far:
added CORS(myAPI) on the backend and added mode:"no-cors"on the frontend. None work so far and what I added in my question so far is the closest (I think) I've gotten to solving this problem
You need to add the allow origin header in the response headers,
the server supposes to add the CORS header
In your code it's in the request header instead.
The flow will look like this:
You have HTTP POST request with JSON content type
that's means you need
Access-Control-Allow-Origin header - your client origin
Access-Control-Allow-Methods header - POST
When you use the Access-Control-Allow-Credentials the origin cannot be *
You can read more about CORS mechanism here - https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
To enable CORS for your website in your flask server you can use the Flask CORS lib - https://flask-cors.readthedocs.io/en/latest/
If you don't use HTTP auth credentials (doesn't seem like you do), you don't need the support_credentials=True in your CORS configuration on the server (line 2 of the code you showed).
This will result in no origins being returned at all if you didn't specify origins because of the invalidity of * together with credentials.
If you set this to False or remove it, a header with origin * should be returned.

React node express app - Heroku CORS error

I have an express project set up on Heroku and a react front end set up on vercel.
When I make a request from the front end, I get the following error:
Access to fetch at 'https://helpr-dev.herokuapp.com/users/register' from origin 'https://helpr-front.vercel.app' 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 have CORS implemented on the Express app:
const cors = require('cors')
app.use(cors())
And I've also tried passing it a config like:
const whitelist = ['http://localhost:3000', 'https://helpr-front.vercel.app/']
const corsOptions = {
origin: function (origin, callback) {
if (!origin || whitelist.indexOf(origin) !== -1) callback(null, true)
else callback(new Error('Not allowed by CORS'))
},
credentials: true,
}
app.use(cors(corsOptions))
This is how a request looks like in the react app:
const submitRegisterForm = async e => {
e.preventDefault()
const response = await fetch(`${serverUrl}/users/register`, {
method: 'POST',
mode: 'cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: name,
email: email,
password: password,
accountType: accountType
})
})
const data = await response.json()
}
I've tried removing the mode: 'cors' part but it doesn't make a difference.
Can someone tell me what I'm missing here?
Front end app is hosted here: https://helpr-front.vercel.app/
Back end app is hosted here: https://helpr-dev.herokuapp.com/
Front end full code can be found here: https://github.com/coccagerman/helpr-front
Back end full code can be found here: https://github.com/coccagerman/helpr-back
Thank you!
So this was caused mainly by a problem with the connection to mongoDb atlas.
First, the Heroku IP adress wasn't whitelisted on the the database network connection. Fixed it like mentioned here: Connecting Heroku App to Atlas MongoDB Cloud service
Then I had an error on the mongo atlas connection URI I was using.
And lastly, It seems necessary to add the mode: 'cors', config on every request I make.
On express, no cors config is needed. I just use app.use(cors())

How do I Submit data from a vuejs form to zapier webhook using axios?

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.

AJAX Request CORS Policy error with Flask

I'm using Flask to build a simple backoffice.
I'm trying to make some requests on client-side using AJAX, but it is always throwing me the following error:
access to XMLHttpRequest at 'http://10.11.0.123/...' from origin 'http://localhost:5000' 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've already tried several solutions but none of them worked. I'm also using CORS package from flask_cors, in the following way:
CORS(app, resources={r"/hardware/control/1": {"origins": "http://localhost:5000"}})
app.run(host="0.0.0.0", port=5000, threaded=True)
However, I think that have no impact on AJAX requests since Flask app runs on server side. So here it is my ajax request:
$.ajax({
url: 'http://10.11.0.123/...',
type: "GET",
contentType: 'text/plain',
headers: {
'Access-Control-Allow-Origin': '*',
},
withCredentials: true,
crossDomain: true,
success: function (result) {
console.log(result)
},
});
I know that the destination sever is receiving the request, however I can not receive any response from the server.
Analysing the network requests, from chrome console, the request returns status: failed and Type: xhr.
My endpoint in flask is:
#system.route('/hardware/control/<int:device_id>')
def hardware_control(device_id):
device = Device.query.get(device_id)
return render_template('hardware_interaction/camera_preview.html',device=device)
I'm creating the app like this:
def create_app():
app = Flask(__name__, instance_relative_config=False)
app.config.from_object('config.DevelopmentConfig')
CORS(app, resources={r"/hardware/control/*": {"origins": "*"}})
with app.app_context():
return app
app = create_app()
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, threaded=True)
You can use this to test that it's actually a CORS issue. This worked for me.
#app.after_request
def after_request(response):
header = response.headers
header['Access-Control-Allow-Origin'] = '*'
header['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
header['Access-Control-Allow-Methods'] = 'OPTIONS, HEAD, GET, POST, DELETE, PUT'
return response
The header Access-Control-Allow-Origin must be returned from Flask, not requested by AJAX. So it would be something like this:
def get_content():
return "It works!", 200
#app.route('/')
def home():
content, status_code = get_content()
headers = {'Access-Control-Allow-Origin': '*'}
return content, status_code, headers
Thank you all for the help. I already solved the problem. I was making requests to HTTP PTZ Camera which don't let me make requests from client side (I've no idea why). So I hack the problem, and now I'm making requests to my server, and my server make the request to the camera. Here you've what I'm doing:
$.ajax({url: 'http://127.0.0.1:5000/teste00',
type: "GET",
success: function (result) {},
});
On server side:
#system.route('/teste00')
def teste():
response = requests.get('camera_url')
return response.content
There are a time from question, but i use flask-cors
To install using pip:
pip install flask flask-cors
See documentation in https://flask-cors.readthedocs.io/en/latest/
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app, support_credentials=True)
#app.route('/ajaxcomp')
#cross_origin(supports_credentials=True)
def ajaxcomp():
if request.is_json:
component = request.args.get('component')
comp_list = components.query.filter_by(SIGLA=componente).all()
results = components_schema.dump(comp_list)
return jsonify(results)
For me works fine.

Axios call api with GET become OPTIONS

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))
}

Categories

Resources