Reputation: 8002
The Access-Control-Allow-Origin
of the response header matches the request Origin
header but I'm still getting the error
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://myappname.herokuapp.com/api/v1/products. (Reason: CORS request did not succeed).[Learn More]
Response Header
HTTP/1.1 308 PERMANENT REDIRECT
Connection: keep-alive
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: authorization, content-type
Access-Control-Allow-Methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT
Access-Control-Allow-Origin: http://localhost
Content-Length: 311
Content-Type: text/html; charset=utf-8
Date: Thu, 04 Apr 2019 10:03:39 GMT
Location: http://mpappname.herokuapp.com/api/v1/products/
Server: waitress
Via: 1.1 vegur
Request Header
Host: mpappname.herokuapp.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
Referer: http://localhost/admin/main/products/create
Origin: http://localhost
DNT: 1
Connection: keep-alive
The code that generates the headers is below but I'm more concerned with understanding why CORS preflight is rejecting this. This is for a flask api with a products CRUD design and token based authentication.
Cut version
from flask_cors import CORS
def create_app(config_name):
...
CORS(app, origins="http://localhost",
allow_headers=["Content-Type", "Authorization", "Access-Control-Allow-Credentials"],
supports_credentials=True)
...
return app
Full version
from flask import Flask
from config import config
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
db.init_app(app)
CORS(app, origins="http://localhost",
allow_headers=["Content-Type", "Authorization", "Access-Control-Allow-Credentials"],
supports_credentials=True)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from .api import api as api_blueprint
app.register_blueprint(api_blueprint, url_prefix='/api/v1')
return app
Upvotes: 4
Views: 7467
Reputation: 8002
I was requesting
http://mpappname.herokuapp.com/api/v1/products
instead of
http://mpappname.herokuapp.com/api/v1/products/
Maybe obvious to some but I needed to read this blog post explicitly to understand this:
https://airbrake.io/blog/http-errors/308-permanent-redirect
The appearance of a 308 Permanent Redirect is usually not something that requires much user intervention. All modern browsers will automatically detect the 308 Permanent Redirect response code and process the redirection action to the new URI automatically. The server sending a 308 code will also include a special Location header as part of the response it sends to the client. This Location header indicates the new URI where the requested resource can be found. For example, if an HTTP POST method request is sent by the client as an attempt to login at the https://airbrake.io URL, the web server may be configured to redirect this POST request to a different URI, such as https://airbrake.io/login. In this scenario, the server may respond with a 308 Permanent Redirect code and include the Location: https://airbrake.io/login header in the response. This informs the user agent (browser) that the POST request data (login info) was received by the server, but the resource has been permanently moved to the Location header URI of https://airbrake.io/login.
Upvotes: 15