ashleysommer / sanic-cors

A Sanic extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible. Based on flask-cors by Cory Dolphin.
MIT License
160 stars 22 forks source link

Setting up CORS but still getting Cross Origin issue #59

Closed Theoooooo closed 1 year ago

Theoooooo commented 2 years ago

Hello,

As the title said, i've setuped CORS for my Sanic API application, but i'm still getting Cross Origin restriction from Sanic itself At first i though this was a connectivity issue, but after a quick tcpdump debug i can clearly see that my requests from my js script(or either manual request from the web dev tool console) that my requests are undeed received correctly.

Here is how i setuped my CORS. I've tried every different options that are available inside the README, but none solved my issue.

Here is the current CORS definition i have inside my script:

from project.tasks import create_id
import requests
from sanic import Sanic
from sanic import response
from sanic_cors import CORS, cross_origin
app = Sanic("sanic_ftm")
app.config['CORS_AUTOMATIC_OPTIONS'] = True
CORS(app, automatic_options=True, resources={r"/api/*": {"origins": "*"}})

@app.route('api/deploy_resource', methods={'GET','OPTIONS'})
async def api_deploy_resource(request):
    # check if result option is provided
    if not request.args['result'] :
        return response.json('{"state":"canceled", "reason": No result option provided"}')
    elif request.args.get('result') != 'terraform' and request.args.get('result') != 'command' :
        return response.json('{"state":"canceled","reason":"Result option invalid"}')
    # start the function create_id
    r = create_id.delay(request.args.get('result'))
    r_result = str(r.get())
    r_id = r.id
    s = '{"result":"%s"}' % (r_result)
    return response.json('{"result":"%s"}' % (r_result))

Here is the issue i'm getting from executing my script with Firefox image image

Here is the headers for both request image image

If you have any idea of why it's not working for me, i'm taking them in account 😅

I'm using the last Sanic version through Python3 PIP, as well as sanic-cors.

ashleysommer commented 2 years ago

Hi @Theoooooo I haven't looked too deeply into this yet, but at first glance, it should work. As a first test, can you change the @app.route path to:

@app.route('/api/deploy_resource', methods={'GET','OPTIONS'})
async def api_deploy_resource(request):

(You were missing a / on the front of it) Let me know if that fixes the problem.

Theoooooo commented 2 years ago

Hello,

I've added the "/" before all of my paths inside my script, but i'm still getting the same issue unfortunately ...

But, the request is not working from a distant linux with curl, but not still with a Firefox or Edge for exemple. I'm still getting the same issue with Cross-Origin.

For more informations about my network setup, both VMs are inside the same network with not restriction whatsoever, i'm inside a testing environnement with no purpose of going into production mode, so there is like no firewall restriction, and i've tested it with SELinux enabled and disabled without any success

ashleysommer commented 2 years ago

Hi @Theoooooo I've done some testing on the code snippet you supplied, and I cannot reproduce your problem. The CORS response works correctly for me: image

Are you still seeing this issue?

Note, unrelated to the CORS problem, I noticed in your snippet you are not using the response.json() helper correctly. It looks like you are building your own JSON strings using string substitution, but then passing that string into the response.json() helper. That is not how it works. You are supposed to pass a dict or object into response.json() and it will create the json string for you.

Eg, this is how that function should look:

@app.route('/api/deploy_resource', methods={'GET','OPTIONS'})
async def api_deploy_resource(request):
    # check if result option is provided
    if not request.args['result']:
        return response.json({"state":"canceled", "reason": "No result option provided"})
    elif request.args.get('result') != 'terraform' and request.args.get('result') != 'command':
        return response.json({"state":"canceled","reason":"Result option invalid"})
    # start the function create_id
    r = create_id.delay(request.args.get('result'))
    r_result = str(r.get())
    r_id = r.id
    return response.json({"result": r_result})
Theoooooo commented 2 years ago

Hello @ashleysommer To be fair i haven't got the time to check and fix this issue, i've been using local php script to call the API to be able to retreive informations through the webpage. But, it's working through another VM that is not inside the same network. I'm still not really understanding why it's not working from multiples different web browser but i guess it's working.

Thanks for the json tips also, i didn't knew you could give him array directly 👍