URL path matching
How a request finds its channel - path parameters, methods, Accept headers and match priorities.
A request is routed to a channel by three things - its URL path, its HTTP method and its Accept header. This page covers how each is matched, what happens when several channels match one request, and every option that shapes the outcome.
Before matching starts
The server accepts these HTTP methods: GET, POST, DELETE, PUT, PATCH, HEAD, OPTIONS. A request with any other method is answered 405 before URL matching runs.
Path parameters
Curly braces in a channel's URL path capture parameters:
Each parameter matches one or more characters from this set: letters, digits and underscore, plus $ . - : | = ~ ^ % @ + , ; ! ( ) and space. The captured values reach your service as self.request.http.params:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class GetOrder(Service):
name = 'demo.rest.get-order'
def handle(self) -> 'None':
customer_id = self.request.http.params['customer_id']
order_id = self.request.http.params['order_id']
self.request.http.params holds path parameters only. Query string values are in self.request.http.GET - a single-valued key points at its value directly and a repeated key at a list of values.
The match_slash option
By default a path parameter can also match slashes, so {path} in /files/{path} matches reports/2026/summary.csv in one parameter. Turning match_slash off on the channel makes each parameter stop at the next slash, so one parameter is one path segment.
Method and Accept matching
A channel may name one HTTP method, in which case only that method reaches it, or leave the method empty to accept any method the server allows. Likewise a channel may name an Accept value through its http_accept option - a channel configured with */* or nothing accepts any Accept header.
When several channels match
Two channels may share a URL path as long as they differ in HTTP method or in their http_accept value. Creating a channel whose path, method and Accept value all equal an existing channel's fails with an error naming that other channel.
A create also fails when two channels would match the same requests with equal specificity but different security - the error names both channels and states that they secure the same requests differently.
When several channels legitimately match one request, the most specific one wins. Specificity is decided in order by the longest literal path prefix, the total literal length of the path, whether the channel names an Accept value, and whether it names a method.
Parameter priorities
Two settings on the channel decide how parameters merge:
url_params_pri- when one name appears both in the path and in the query string,qs-over-path(the default) lets the query string win andpath-over-qslets the path parameter win.merge_url_params_req- on by default. When on, path and query parameters are merged intoself.request.inputfor keys the payload does not already contain, andself.request.http.GETandself.request.http.POSTare populated. When off, none of that happens and only the payload reaches the service.
When self.request.http.POST is populated
self.request.http.POST is filled in two cases, both requiring merge_url_params_req to be on:
- The channel's data format is
formand the request's content type isapplication/x-www-form-urlencodedormultipart/form-data- the parsed form is bothPOSTand the service's payload - The channel has no data format at all, in which case the raw body is parsed as a query string into
POST
A channel with any other data format, JSON included, leaves POST empty.
Data format
A new channel has no default data format - a channel that should parse JSON bodies into self.request.payload must set its data format to JSON explicitly, in the Dashboard or in enmasse YAML. Without it, the service receives the raw request bytes.
The match cache
Resolved matches are kept in a least-recently-used cache of 10,000 entries, with a second cache of the same size for paths that matched nothing. Both are transparent - any channel create, edit or delete evicts the affected entries. The bound matters only for channels with high-cardinality dynamic paths, where more than 10,000 distinct URLs rotate through the cache.
An inactive channel
An inactive channel stays in the routing table but answers every request with 404, the same status a caller sees when no channel exists at all - deactivation is indistinguishable from absence on purpose.
See also
| Page | What it covers |
|---|---|
| REST channels | Creating channels and reading parameters in services |
| HTTP verbs | One service responding differently to GET, POST, PUT, PATCH and DELETE |
| Error catalog | Every status code a channel returns, including 404 and 405 |
| Enmasse reference | match_slash, http_accept and every other channel_rest key in YAML |