Fetch Request in Jinjia Include getting CORS Error

Question:

So I have a site that is using Flask for the Front and Backend with Jinja templates. Currently testing with localhost (5000 is the backend and 8000 is for the frontend)

the page in question

main.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id='container'>
        {% include "user.html" %}
    </div>
</body>
</html>

user.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="user">
        <h3>User: <span id="username"></span></h3>
        <h4>Winnings: <span id="winnings"></span></h4>
        <h4>Plays: <span id="credits"></span></h4>
    </div>
    <script>
        var token = String(window.location).split('#')[1].split('&')[0].split('=')[1];
        fetch('http://localhost:5000/user',{
                method:'POST',
                headers:{
                    'Authorization':'bearer '+token,
                    'Content-Type':'application/json',
                    'Access-Control-Allow-Origin':'*'
                }
            }).then(function(r){
                return r.json();
            }).then(function(response){
                document.getElementById('username').innerHTML = response['username'];
                document.getElementById('winnings').innerHTML = response['winnings'];
                document.getElementById('credits').innerHTML = response['credits'];
            }).catch(function(error){
                console.log(error);
            });
    </script>
</body>
</html>

frontend.py

from flask import Flask, render_template, request, redirect, url_for, jsonify
from flask_cors import CORS
import requests

app = Flask(__name__)
cors = CORS(app)

@app.route('/main',methods=['GET'])
def main():
    return render_template('main.html')

backend.py

from flask import Flask, send_file, abort, jsonify, request
from flask_cors import CORS
from functools import wraps
from urllib.request import urlopen
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import func, Column, Integer, String, create_engine
from flask_migrate import Migrate
from dotenv import load_dotenv
import pandas as pd
import os, sys, json, jwt, requests

load_dotenv()

app = Flask(__name__)
cors = CORS(app, origins=['http://localhost:8000'])

app.config.from_object('config')

db = SQLAlchemy(app)

migrate = Migrate(app,db,compare_type=True)

def requires_auth():
    #auth code here to make sure the token in the header is valid
    #token includes the user name, which is passed to the database

@app.route('/user',methods=['POST'])
@requires_auth()
def getUser (p):
    try:
        user = User.query.filter_by(username=p['user']).first()
        return jsonify({
            'success':True,
            'username':username,
            'credits':user.credit,
            'winnings':user.score
        })
    except:
        print(sys.exc_info())
        abort(401) 

When this runs, I get this in the browser, and the user information does not update:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/user. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 200.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/user. (Reason: CORS request did not succeed). Status code: (null).

TypeError: NetworkError when attempting to fetch resource.

I checked the CORS, and the origin in the response matches the frontend port, as well as referer.

I expect the javascript in "user.html" to make the call to the backend. As it is part of "main.html" which is rendered when ‘http:localhost:8000/main’ is called.

Asked By: Miko

||

Answers:

enable Origin header and specify your server as origin. (don’t use the default *)

fetch('http://localhost:5000/user', {
    method:'POST',
    headers:{
        'Authorization':'bearer '+token,
        'Content-Type':'application/json',
        'Access-Control-Allow-Origin':'http://localhost:5000/user',
        'Access-Control-Allow-Headers': ['Origin']',
    }
})

looks like your using some custom auth decorator so you’ll want to enable credentials

CORS(app, supports_credentials=True)
Answered By: None

I got around the CORS issues by creating an endpoint on the frontend that forwards the request to the backend and returns a json object.

frontend.py

@app.route('/user',methods=['POST'])
def getUser():
    r = requests.post(
        'http://localhost:5000/user',
        headers=request.headers,
    )
    return r.json()

user.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="user">
        <h3>User: <span id="username"></span></h3>
        <h4>Winnings: <span id="winnings"></span></h4>
        <h4>Plays: <span id="credits"></span></h4>
    </div>
    <script>
        var token = String(window.location).split('#')[1].split('&')[0].split('=')[1];
        fetch('http://localhost:8000/user',{
                method:'POST',
                headers:{
                    'Authorization':'bearer '+token,
                    'Content-Type':'application/json',
                    'Access-Control-Allow-Origin':'http://localhost:8000/user',
                    'Access-Control-Allow-Headers': ['Origin']
                }
            }).then(function(r){
                return r.json();
            }).then(function(response){
                document.getElementById('username').innerHTML = response['username'];
                document.getElementById('winnings').innerHTML = response['winnings'];
                document.getElementById('credits').innerHTML = response['credits'];
            }).catch(function(error){
                console.log(error);
            });
    </script>
</body>
</html>

Good tries all around.

Answered By: Miko