惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
WordPress大学
WordPress大学
Google DeepMind News
Google DeepMind News
美团技术团队
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
M
MIT News - Artificial intelligence
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - Franky
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
F
Fortinet All Blogs
A
About on SuperTechFans
Recent Announcements
Recent Announcements
D
Docker
Vercel News
Vercel News
Engineering at Meta
Engineering at Meta
腾讯CDC
Martin Fowler
Martin Fowler
阮一峰的网络日志
阮一峰的网络日志

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Trailing and Non Trailing Slash in Nginx
Rohit Sharma · 2026-06-23 · via DEV Community
Cover image for Trailing and Non Trailing Slash in Nginx

Rohit Sharma

Most tricky part of Nginx: The trailing slash behavior in proxy_pass is one of the most confusing parts of Nginx. Once you understand one rule, it becomes easy

There are 2 Cases:

CASE 1: proxy_pass WITHOUT trailing slash

location /api/ {
    proxy_pass http://localhost:3000;
}

notice

http://localhost:3000
                     ↑
                 no slash

request

http://localhost/api/users

What Nginx sends to backend

http://localhost:3000/api/users

The entire original URI is preserved.

CASE 2: proxy_pass WITH trailing slash

location /api/ {
    proxy_pass http://localhost:3000/;
}

notice

http://localhost:3000/
                     ↑
                  slash

request

http://localhost/api/users

what backend receives

http://localhost:3000/users

Nginx removes the matched location (/api/) and replaces it with /

VISUAL REPRESENTATION (Without Slash)

Client:
    /api/users

location:
    /api/

proxy_pass:
    http://localhost:3000

Result:
    http://localhost:3000/api/users

VISUAL REPRESENTATION (With Slash)

Client:
    /api/users

location:
    /api/

proxy_pass:
    http://localhost:3000/

Result:
    http://localhost:3000/users

Why? Because internally Nginx does:

NO SLASH

backend_url + original_uri

http://localhost:3000
+
/api/users

=
http://localhost:3000/api/users

WITH SLASH

replace(location_prefix, proxy_pass_uri)

/api/users
↓ remove /api/
/users

prepend /
↓

http://localhost:3000/users

In simpler words, think of it as:

No slash (Keep the original URI)
Slash (Replace the matched prefix)

Nginx does NOT look at whether /api/ exists in the request and remove it automatically.

It only removes the matched location prefix when proxy_pass contains a URI part (a trailing slash or some path).

Understanding the both cases carefully
Case 1: No trailing slash

location /api/ {
    proxy_pass http://localhost:3000;
}

notice

proxy_pass = http://localhost:3000

There is:

scheme → http
host → localhost
port → 3000
URI part → ❌ NONE

Because there is no URI part, Nginx simply forwards the entire original URI.

Request : /api/users

Nginx does

http://localhost:3000
+
/api/users
=
http://localhost:3000/api/users

No replacement happens.

CASE 2: TRAILING SLASH

location /api/ {
    proxy_pass http://localhost:3000/;
}

Now

proxy_pass = http://localhost:3000/

This is a URI part

/

Now Nginx switches to replacement mode.

Request: /api/users
Matched location: /api/
Remaining: users
Result: http://localhost:3000/users

Why does / count as a URI?

Because internally Nginx parses:

http://localhost:3000

as:

host = localhost
port = 3000
uri = NULL

but

http://localhost:3000/

as:

host = localhost
port = 3000
uri = /

That tiny / changes the algorithm completely.

Internal logic (simplified). Nginx does something like:

if (proxy_pass_contains_uri) {
    replace_location_prefix();
}
else {
    append_original_uri();
}

OR IN SOME SIMPLE WORDS, How Nginx actually thinks

Did proxy_pass contain a URI part?
            |
      +-----+-----+
      |           |
     NO          YES
      |           |
Keep URI      Replace matched location prefix
as-is         with proxy_pass URI