What is CORS?

  • Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources.
  • Its essentially a security feature

How it goes down:

  1. The browser(frontend) sends the GET request with an extra Origin HTTP header to service.example.com (deployed backend) containing the domain that served the parent page
    Origin: http://www.example.com // frontend url
  2. The server at service.example.com sends one of these responses:
    Access-Control-Allow-Origin: http://www.example.com //backend allows the frontend url to access its contents
    Access-Control-Allow-Origin: * //backend allows any site to access its contents

What is the Access-Control-Allow-Origin response header?

  • The Access-Control-Allow-Origin header is included in the response(response comes from backend) from site B to a request(fetch from frontend) site A, and identifies the permitted origin of the request. A web browser compares the Access-Control-Allow-Origin with the requesting website's origin and permits access to the response if they match.
  • Including the Access-Control-Allow-Origin header in the client-side request can be useful in some cases, such as when you are working with a third-party API and want to make sure that your requests are allowed by the server.
  • It can also be used during development or testing, when you may not have control over the server-side configuration sites A better model: system

Issues with CORS

  • When trying to start a local server and test your frontend and backend connection, cors is often something that gets in the way.
  • Unfortunately this error can prevent any sort of backend connection without proper code. Usually this error will appear when a header for cors is not specified or your backend url is not permitted by cors

error

I'm sure you've seen it... So here's a method to bypass CORS locally. Eventually, when both your frontend and backend are deployed, it's good practice to have CORS implemented since your site could have some security risk if you simply bypass it.

Local x Local

Setup local backend

How to bypass CORS with a local backend and frontend running

  1. Run your backend locally by running the main.py file on your flask repository in vscode
  2. Get the url of your backend server.

url

Setup local frontend

  • run the command bundle exec jekyll serve in terminal to start your frontend locally
  • Use the url from the picture above to write a 'fetch' statement (doesn't have to be like whats written below) to reference the local url and your api
fetch('http://127.0.0.1:8080/api/yourapi/').then(function(response) { 
    return response.json();
  });

Solution 1: Code in main.py

  • In the main.py file on your flask server, there should be a section of code at the bottom of the page that is already built in (by Mr. Mort) to aid in any cors errors.
  • It looks like this:
if __name__ == "__main__":
    # change name for testing
    from flask_cors import CORS
    cors = CORS(app)
    app.run(debug=True, host="0.0.0.0", port="8080")
  • Background info on flask_cors

    • flask_cors is a Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible. This package has a simple philosophy: when you want to enable CORS, you wish to enable it for all use cases on a domain. This means no mucking around with different allowed headers, methods, etc.
    • in simple terms, this extension allows you to avoid dealing with annoying headers and access the domains you need
  • Possible errors

    • "module cannot be resolved"
      • cd to your repository file path
      • make sure you have the prefix (base) (aka type wsl)
      • pip install -U flask-cors

Solution 2: Download google Extension

Now try interacting with your frontend site, and the fetch will work

Local x Deployed

  • It's worth noting that including the Access-Control-Allow-origin in the client-side(frontend repo) request does not actually enable cross-origin requests if the server(backend) is not configured to allow them. The server must still include the header in its response for the request to be allowed.

Local Frontend

  • same steps as described previously to setup the local frontend.
  • Instead of fetching from the local url, replace it with the domain url of your backend server.
fetch('https://finalssvgcars.duckdns.org/api/cars/').then(function(response) { 
    return response.json();
  });

Deployed Backend

  • In order to get the combination of local frontend and deployed backend to work, the Access-Control-Allow-origin must be configured on the server side. And it is
  • Setup AWS by following the deployment guide on the APCSP Website
  • When you set up the nginx configuration files, you'll notice: aws
  • As you can see the header "Access-Control-Allow-Origin" * is present in the nginx files in sites-available and sites-enabled
  • The line proxy_pass http://localhost:8777 is allowing the frontend local url to access the deployed backend site
  • Another thing to note however is that the "" allows any frontend site to access the backend. In order to secure this, you need to put something different in place of the . Will go over this in the next sections

Deployed x Local

  • This combination should work identical to the Local x Local combination. Thus any solutions for that combination also apply to this combination.

Deployed Frontend

  • Go to your repository on github
  • when you scroll down, under the section called "Environment", click the link that says "github pages"
  • Then click "view deployment"
  • Your frontend deployed url should follow this format: https://username.github.io/name_of_repository/
  • Your fetch statement should use the local url of the backend server (identical to that of the Local x Local combination)

Local Backend

  • run main.py

Deployed x Deployed

Deployed Frontend

  • Your fetch statement should use the deployed url of the backend server (identical to that of the Local x Deployed combination)

Deployed Backend

aws

  • In the Local x Deployed we talked about the the header "Access-Control-Allow-Origin" * that is present in the nginx files in sites-available and sites-enabled
  • Instead of using the "*", replace it with the url of your frontend site.
  • This secures you server and ensures that the only website that can access your backend server is the your frontend server! here is an example…
location / {
    proxy_pass http://localhost:8085;
    # Preflighted requests
    if ($request_method = OPTIONS ) {
            add_header Access-Control-Allow-Credentials  true;
            add_header Access-Control-Allow-Origin  https://nighthawkcoders.github.io;
            add_header Access-Control-Allow-Methods GET, POST, OPTIONS, HEAD;
            add_header Access-Control-Allow-MaxAge  600;
            add_header Access-Control-Allow-Headers Content-Type, Authorization, x-csrf-token;
            return 200;
    }
}