How to properly use Regex in CORS Middleware for FastAPI?

Question:

I have an app that uses a FastAPI backend and a Next.js frontend. In development and on production with stable origins, I am able to use the CORSMiddleware with no issues. However, I have deployed the Next.js frontend with Vercel, and want to take advantage of the automatic Preview deployments that Vercel makes with each git commit to allow for staging-type qualitative testing and sanity checks.

I’m running into CORS issues on the Preview deployments: since each Preview deployment uses an auto-generated URL of the pattern: <project-name>-<unique-hash>-<scope-slug>.vercel.app, I can’t add them directly to the allow_origins argument of the CORSMiddleware. Instead I am trying to add the pattern to the allow_origin_regex argument.

I am very new to regex, but was able to figure out a pattern that I’ve tested to work in REPL. However, because I’m having issues, I’ve switched to use an ultra-permissive regex of ‘.*’ just to get anything to work but that has failed also.

main.py (relevant portions)

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
    "http://localhost",
    "http://localhost:8080",
    "http://localhost:3000",
    "https://my-project-name.vercel.app"
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_origin_regex=".*",
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

I’ve looked at the FastAPI/Starlette cors.py file to see how it ingests and uses the origin regex and don’t see where the problem would be. I’ve tested the same methods in REPL with no issues. I’m at a loss as to the next avenue to investigate in order to resolve this issue. Any assistance or pointers or "hey dummy you forgot this" comments are welcome.

Asked By: DWaldie

||

Answers:

Whenever a new deployment is created, Vercel will automatically generate a unique URL that is publicly available, and which is composed of the following pieces:

<project-name>-<unique-hash>-<scope-slug>.vercel.app

To allow requests from any Vercel deployment, use:

allow_origin_regex='https://.*.vercel.app'

To allow requests from a specific Vercel project, use:

allow_origin_regex='https://<project-name>-.*.vercel.app'

for instance:

allow_origin_regex = 'https://my-site-.*.vercel.app'

The example below is based on how FastAPI/Starlette’s CORSMiddleware works internally (see implementation here). The example shows that using the above regex, a match for an origin such as https://my-site-xadvghg2z-acme.vercel.app is found.

import re

origin = 'https://my-site-xadvghg2z-acme.vercel.app'
allow_origin_regex = 'https://my-site-.*.vercel.app'
compiled_allow_origin_regex = re.compile(allow_origin_regex)

if (compiled_allow_origin_regex is not None
        and compiled_allow_origin_regex.fullmatch(origin)):
    print('Math found')
else:
    print('No match found')

Please make sure to specify the correct protocol (e.g., http, https) and port(80, 8000, 3000) in allow_origin_regex.

Answered By: Chris

I hesitate to admit how stupid the answer to this actually was once I realized my mistake, but wanted to be intellectually honest and provide an update just in case anyone else has a similar blank and runs into this down the line.

I’m new to anything frontend and development in general for the most part, and had never really dealt with CORS before. I was so concerned with getting the Preview deployments going on the frontend, and checking the auto-built Preview deployments on Vercel, that I forgot where I was actually making changes. I have the frontend and backend of my project as subdirectories within the same repo, so each git push of the backend code causes an automatic Vercel deployment, and I just blanked that it wouldn’t cause an update of the actual FastAPI code.

As soon as I realized and pushed the changes to my backend, everything started working as it should.

I marked the other answer as correct because it was 100% correct in answering the question I asked, but providing this as it’s the answer to the problem of where I made the real mistake.

Answered By: DWaldie

This answer worked for me. But the problem with that answer is that FASTAPI will accept any response request from any Vercel deployment. If you want FASTAPI to enable only requests from your Vercel account, then you could modify allow_origin_regex variable to,

allow_origin_regex = 'https://<YOUR_VERCEL-PROJECT-NAME>-*.vercel.app'
Answered By: akilesh raj