How to Extract and Use Path Segments in Nginx Location Blocks for Dynamic proxy_pass Routing


4 views

When configuring Nginx as an API gateway, we often need to capture specific path segments from the incoming request URI and dynamically insert them into the proxy_pass destination. This becomes particularly useful when routing requests to different backend services based on path patterns.

The solution lies in Nginx's powerful regex location matching and capture groups. Here's the basic syntax:

location ~ ^/([^/]+)/v2/(.*)$ {
    proxy_pass http://app.domain.com/api/$1/v2/$2;
}

Let's examine the key components of this approach:

1. ~ : Enables regex matching
2. ^ : Anchors the match at the start of the URI
3. ([^/]+) : Captures the first path segment (non-slash characters)
4. /v2/ : Matches the literal "/v2/" portion
5. (.*) : Captures the remaining path
6. $1 and $2 : Reference the captured groups

Basic API Version Routing

location ~ ^/([^/]+)/v([0-9]+)/(.*)$ {
    proxy_pass http://api-backend/$1/v$2/$3;
    proxy_set_header X-API-Version $2;
}

Multi-segment Capture

location ~ ^/([^/]+)/([^/]+)/(.*)$ {
    proxy_pass http://$1-service.domain.com/$2/$3;
    proxy_set_header X-Service-Name $1;
}

With Rewrite Rules

location ~ ^/api/([^/]+)/(.*)$ {
    rewrite ^/api/([^/]+)/(.*)$ /$2 break;
    proxy_pass http://$1.internal.domain.com;
}

For Microservices Architecture

location ~ ^/services/([^/]+)/(.*)$ {
    resolver kube-dns.kube-system.svc.cluster.local;
    proxy_pass http://$1-service.default.svc.cluster.local/$2;
}

Watch out for these issues when implementing path segment extraction:

  • Forgetting the 'break' flag in rewrite rules
  • Not accounting for trailing slashes
  • Overlooking URL encoding of captured segments
  • Missing resolver for internal DNS in containerized environments

When building API gateways with Nginx, we often need to capture specific path segments to construct dynamic upstream endpoints. This becomes crucial when routing requests to microservices or versioned APIs while maintaining clean URL structures.

Nginx provides a powerful way to capture path segments using named regular expression groups:


location ~ ^/(?<service>[^/]+)/v2/(.*)$ {
    proxy_pass http://app.domain.com/api/$service/v2/$1;
}

Let's examine three common use cases with increasing complexity:


# Basic capture for service name
location ~ ^/(?<api_module>[^/]+)/v1/ {
    proxy_pass http://backend/$api_module/v1/;
}

# Multi-segment version-aware routing
location ~ ^/(?<team>[^/]+)/(?<service>[^/]+)/v(?<version>\d+)/ {
    proxy_pass http://$team.services.domain.com/$service/api/v$version/;
}

# Full path reconstruction with query params
location ~ ^/gateway/(?<namespace>[^/]+)/(?<endpoint>.*)$ {
    proxy_pass http://$namespace.internal.domain.com/$endpoint$is_args$args;
}

While regex locations are powerful, they're slightly slower than prefix matches. For high-traffic endpoints, consider:

  • Using the most specific patterns first
  • Limiting capture groups to only what you need
  • Using ^~ modifier for priority prefixes

For more complex scenarios, combine map directives with captured variables:


map $service $backend_host {
    users      users-cluster.internal;
    products   catalog-service.internal;
    default    fallback.internal;
}

server {
    location ~ ^/(?<service>[^/]+)/ {
        proxy_pass http://$backend_host/api/$service;
    }
}

Watch out for these gotchas:

  • Trailing slashes in location and proxy_pass must match
  • URI segments are case-sensitive by default
  • Special characters in paths may require escaping
  • Variables in proxy_pass require Nginx 1.17+ for full support