CORS demo

Table of Contents

1. Cross Origin Resourse Sharing

This button makes a request to Phil's echo-server running on the same machine:

 Echo server response 
req.open('POST', '/echo-server');
req.setRequestHeader("Content-type", "Application/json");
obj = {"hello": "world"}
console.log("Sending object: ", obj)
req.send(JSON.stringify(obj, null, 2));

On my home machine, I have nginx running with this configuration:

server {
    server_name philippe-carphin.ca;
    listen 443 ssl;
    # <other SSL stuff, certificates...>

    # Handle philippe-carphin.ca/~USERNAME
    location ~ ^/~(.+?)(/.*)?$ {
        disable_symlinks off;
        alias /Users/$1/public_html$2;
        # try_files $2 = 405;
    }

    # Proxy requests philippe-carphin.ca/echo-server to
    # localhost:5447 as unwrapped HTTP
    location /echo-server {
        proxy_pass http://localhost:5447;
    }
}

CORS is explained at https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests

And an example is given in the section Simple Requests where they show that the user visits https://website.com and in the javascript of the web page makes a request

const fetchPromise = fetch("https://service.com");
fetchPromise
  .then((response) => response.json())
  .then((data) => {
    console.log(data);
  });

This creates a request with headers that include

Origin: https://website.com

The server running at service.com inspects the headers of the request and if it accepts to share with this origin, then it makes its response and includes

Access-Control-Allow-Origin: *

In my echo server, I check if the origin is one that I agree to share with:

if origin and args.allowed_origins and origin in args.allowed_origins:
    origin_allowed = True
    response_dict['info'].append(f"Origin {allowed_origin} is in allowed hosts")
# else:
#     send_response(403)
#     return

and normally, if I don't agree to share with that origin, then I can send back a 403 and abort early rather than doing wasted work.

But if I do accept to share, then I do the work and tell the client inform the client by doing

self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.send_header("Access-Control-Allow-Origin", origin)
self.end_headers()
self.wfile.write(bytes(json.dumps(response_dict, indent='    ') + '\n', 'utf-8'))

In this case, I am being more precise by sending back the exact value that I got in the Origin header.

1.1. On Monday

Depending on the origin, we will get 3 behaviors

  • emmy: The echo server sees origin that is not part of the allowed origins. Since it doesn't abort the request, it just sends the normal response but without Access-Control-Allow-Origin in the headers.

    Since this is not a Cross Origin request, the client is OK with the fact that the response headers don't contain Access-Control-Allow-Origin.

  • iweb: The server sees iweb.cmc.ec.gc.ca as the origin, it sends the response back with Access-Control-Allow-Origin with a value equal to the origin it got in the request header.

    Since this request is a Cross Origin request, the client checks that the value of the response header Access-Control-Allow-Origin matches is either * or matches the value of the request header Origin. In this case, it is a match, the client processes the response.

  • ada: The request is a Cross Origin request. In this case my server accepts to process it for demonstration and does not set an Access-Control-Allow-Origin response header.

    The client made a cross origin request that came back with a response lacking the proper CORS header. It refuses to process the response.

Author: Philippe Carphin

Created: 2025-02-23 Sun 21:28

Validate