I have a simple FastAPI
that returns a string based on a query parameter at the endpoint /day
. Trying to deploy using Docker
and nginx
as a reverse proxy. In order to get http://localhost:3000/api/day?day_num=5
to work, I needed to explicitly add location /api/day
to my nginx-setup.conf
. I would receive an error if I only had location /api/
and tried to visit http:localhost:3000/api/day
.
How can I avoid having to explicitly add each endpoint? Is there a way to make /api/day
, /api/docs
and any other valid endpoints for localhost:8000
(port Docker exposes for the backend service) work when I visit http:localhost:3000/api/{valid endpoints}
?
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/day", tags=["Dates"])
async def get_day_of_week(day_num: int = 0):
"""
Get the current day of week
"""
days = ['Sun', 'M', 'T', 'W', 'Th', 'F', 'S']
return days[day_num]
I am trying to use nginx
as a reverse proxy.
nginx-setup.conf
upstream api {
server backend:8000;
}
server {
listen 8080;
location /api/ {
proxy_pass http://api;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
location /api/day {
proxy_pass http://api/day;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
}
docker-compose.yml
version: '3'
services:
backend:
build:
context: ./backend
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --root-path /api
ports:
- "8000:8000"
nginx:
image: nginx:latest
ports:
- 3000:8080
volumes:
- ./nginx/nginx-setup.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- backend
CodePudding user response:
If you don't have a trailing slash in the proxy_pass
entry, the path will be included verbatim. So:
location /api/ {
proxy_pass http://api;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
Will result in the backend seeing /api/day
as the request path. Since your application only expects /day
, you have to modify your proxy_pass
directive to include a trailing slash - this tells nginx to strip the matching part from the location /api/
entry (and you should have a trailing slash here as well).
location /api/ {
proxy_pass http://api/; # <- trailing slash
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
CodePudding user response:
You should remove the trailing slash in your location configuration:
server {
listen 8080;
location /api/ {
-----------------^ remove this one
proxy_pass http://api;
Nginx replaces the location with a non-trailing-slash uri. So, http://yourserver/api/something will become http://apisometing (note the concatenation).