Demystifying FastAPI's CORSMiddleware for Cross-Origin Requests
Tags: fastapi, backend, webdev, tutorial
Published: 2023-11-05 22:59:26

## Content

- [Introduction](#introduction)
- [What is CORS?](#what-is-cors)
  - [FastAPI's Definition](#fastapis-definition)
  - [Mozilla's Definition](#mozillas-definition)
  - [Technical Explanation](#technical-explanation)
- [CORS Basics](#cors-basics)
  - [How CORS Works](#how-cors-works)
  - [Handling Errors](#handling-errors)
- [Configuring FastAPI's CORSMiddleware](#configuring-fastapis-corsmiddleware)
  - [Requirements](#requirements)
  - [Step 1: Install FastAPI](#step-1-install-fastapi)
  - [Step 2: Necessary Imports](#step-2-necessary-imports)
  - [Step 3: Create an Instance of the FastAPI Framework](#step-3-create-an-instance-of-the-fastapi-framework)
  - [Step 4: Define Allowed Origins](#step-4-define-allowed-origins)
  - [Step 5: Configure CORSMiddleware](#step-5-configure-corsmiddleware)
  - [Step 6: Syntax for API Endpoint](#step-6-syntax-for-api-endpoint)
  - [Explanation of Supported Configuration Arguments](#explanation-of-supported-configuration-arguments)
- [Pre-Conclusion](#pre-conclusion)
- [Discovering Starlette Configuration and Code Underneath](#discovering-starlette-configuration-and-code-underneath)
- [Conclusion](#conclusion)


## Introduction

**Cross-Origin Resource Sharing (CORS)** is a critical mechanism that allows servers to control which origins (domains, schemes, or ports) can access their resources. In this article, we will delve into **FastAPI's CORSMiddleware**, understand its functionality, and learn how to configure it effectively.

## What is CORS?

![Meme of a duck acting as a sea border patrol](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87vclfaopzxdqes74egx.jpeg)

*Think of CORS as a border protocol setup between the server side and the client side intended to allow resource hosts (any service that makes its data available via HTTP) to restrict which websites may access that data.*

**According to the [FastAPI documentation](https://fastapi.tiangolo.com/tutorial/cors/)**, CORS or "Cross-Origin Resource Sharing" refers to the situations when a frontend running in a browser has JavaScript code that communicates with a backend, and the backend is in a different "origin" than the frontend.

**According to [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/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.

**In more technical terms, CORS, or Cross-Origin Resource Sharing, is an HTTP-header-based system that enables a server to specify which origins other than its own can access its resources, ensuring secure cross-origin data transfers while protecting against unauthorized requests.**

## CORS Basics

### How CORS works

The Cross-Origin Resource Sharing standard works by adding new HTTP headers that let servers describe which origins are permitted to read that information from a web browser. Additionally, for HTTP request methods that can cause side-effects on server data (in particular, HTTP methods other than GET, or POST with certain MIME types), the specification mandates that browsers "preflight" the request, soliciting supported methods from the server with the HTTP OPTIONS request method, and then, upon "approval" from the server, sending the actual request. Servers can also inform clients whether "credentials" (such as Cookies and HTTP Authentication) should be sent with requests.

To achieve this, the backend must have a list of "allowed origins." In this case, it would have to include `http://localhost:3000` or `*` for the frontend to work correctly.

### Handling errors

CORS failures result in errors but, for security reasons, specifics about the error are not available to JavaScript. The only way to determine what specifically went wrong is to look at the browser's console for details. For a deeper understanding of CORS, visit the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).

## Configuring FastAPI's CORSMiddleware

FastAPI provides its own middleware for handling CORS, offering granular control over cross-origin requests. We'll dive into the specifics of configuring FastAPI's CORSMiddleware step-by-step.

### Requirements:

- Python 3
- Updated pip (best practice)
- Code editor
- Basic knowledge of pip installation and using a code editor

### Step 1 (Should be done in the terminal):

Install FastAPI
```shell
pip install fastapi[all]
```

### Step 2 (All other steps from here should be done in the code editor environment):

Necessary imports

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

### Step 3:

Create an instance of the FastAPI framework and assign it to a variable named `app`

```python
app = FastAPI()
```

### Step 4:

A list of origins that you plan to be permitted to make cross-origin requests

```python
origins = [
    "http://localhost:3000",
]
```

### Step 5:

Pass parameter configurations to `app.add_middleware`

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

### Step 6:

Syntax for API endpoint

```python
@app.get("/")
async def main():
    return {"message": "Hello World"}
```
Here’s a link to a [sample project](https://github.com/Greyisheep/react-fastapi-app) on my [github](https://github.com/Greyisheep) that utilizes this CORS configuration in the main.py file of the FASTAPI folder. 

### What the supported configuration arguments mean:

- `allow_origins`: A list of origins that should be permitted to make cross-origin requests. For example, `['https://example.org', 'https://www.example.org']`. You can use `['*']` to allow any origin.

- `allow_origin_regex`: A regex string to match against origins that should be permitted to make cross-origin requests. For example, `'https://.*\.example\.org'`.

- `allow_methods`: A list of HTTP methods that should be allowed for cross-origin requests. Defaults to `['GET']`. You can use `['*']` to allow all standard methods.

- `allow_headers`: A list of HTTP request headers that should be supported for cross-origin requests. Defaults to an empty list. You can use `['*']` to allow all headers. The Accept, Accept-Language, Content-Language, and Content-Type headers are always allowed for CORS requests.

- `allow_credentials`: Indicate that cookies should be supported for cross-origin requests. Defaults to `False`.

- `expose_headers`: Indicate any response headers that should be made accessible to the browser. Defaults to an empty list.

- `max_age`: Sets a maximum time in seconds for browsers to cache CORS responses. Defaults to `600`.

**Important:** In our Demo we used "\*", so let’s talk about it. "\*" a "wildcard"  is used to say that all are allowed. But, like the joker it can get tricky.
![Picture of a wild card](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bptoloiy54erujy85kz3.jpeg)

If wildcards are used for `allow_origins`, it will only allow certain types of communication, excluding everything that involves credentials: Cookies, Authorization headers like those used with Bearer Tokens, etc.

So, for everything to work correctly, it's better to specify explicitly the allowed origins.



## Pre-Conclusion

FastAPI's CORSMiddleware empowers you to take control over cross-origin requests, securing your APIs while allowing legitimate access. With the knowledge gained from this article, you can confidently configure and utilize this middleware for your FastAPI projects, ensuring secure and efficient cross-origin data transfers.

Start building!

![Inception meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xj7i12ey23xc4kmriphz.jpeg)

*If you’re a nerd like me and curious about what code is down imports deeper in FastAPI CORSMiddleware, then it’s inception time.*

## Discovering Starlette Configuration and Code Underneath

So, I kept pressing ‘Go to definition’...

![Screenshot of my cursor on Go to definition](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dfus0e87hmz0h6e9h5ak.png)
...


![A few moments later](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5tz474lg626yx743qde.jpeg)

…and then I came across the ASGI gem Starlette

![Screenshot of a starlete cors.py page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/njgixvmubvdb4dz9ocj4.png)

*So, to keep the article length optimal, I’ll be writing about it in my next article.* **Keep checking my page, comment and like my posts.**

## Conclusion

Since this is not exactly where it ends (await the post conclusion :)), the conclusion will be in my next article.

***Thank you for reading up to this point. Did you enjoy this article? Leave comments, questions, or other suggestions. Follow my page, contact me for technical articles, or collaborations on my [LinkedIn](https://www.linkedin.com/in/claret-ibeawuchi/).***