aah Routing
aah supports domains and subdomains seamlessly. It provides route URL lookup by route name effectively.
The router is optimized for high performance and a small memory footprint. It scales well with very long paths and a large number of routes. Radix tree structure is used for efficient matching.
aah internally uses customized version of httprouter, developed by @julienschmidt.
Table of Contents
Highlights
- URI Parameters - Give path segment a name and access it as action method parameters.
- Perfect for RESTful APIs - Build sensible, hierarchical RESTful APIs. Router has builtin native support for OPTIONS requests and
405 Method Not Allowed
replies. - Only explicit matches - a request can only match exactly one or no route. As a result, there are also no unintended matches, which makes it great for SEO and improves the user experience.
- Stop caring about trailing slashes - Choose the URL style you like, the router automatically redirects the client if a trailing slash is missing or if there is one extra. Of course, it does only if the new path has a controller action. Behavior could be disabled at domain level using
redirect_trailing_slash = false
in the routes config. - Path auto-correction - Besides detecting the missing or additional trailing slash at no extra cost, the router can also fix wrong cases and remove superfluous path elements (like
../
or//
). Is CAPTAIN CAPS LOCK one of your users? Router can help user by making a case-insensitive look-up and by redirecting to the correct URL. - Zero Garbage - The matching and dispatching process generates zero bytes of garbage. In fact, the only heap allocations that are made, is by building the slice of the key-value pairs for path parameters. If the request path contains no parameters, not even a single heap allocation is necessary.
Route Definitions
aah routes.conf
is composed of four major config sections, such as domains
, domain
, static routes
and application routes
.
Learn routes configuration attributes and its purpose.
# -----------------------------------------------------------------------------
# app name - Application Routes Configuration
#
# Refer documentation to explore and configure routes.
# Doc: https://docs.aahframework.org/routing.html
# -----------------------------------------------------------------------------
domains {
# Choose a `unique keyname` to define domain section and its configuration.
# Tip: Use app name, domain name address, port no values to create a domain key.
#
# Examples: aahframework { ... }, docs_aahframework { ... }
domain_key_name {
#
# Domain configurations - host, port and CORS, for example.
#
# Static files Routes Configuration
# Optional section- API and WebSocket apps, as examples
static {
# ...
}
# Routes Configuration
routes {
# domain routes comes here
} # end - routes
} # end - domain configurations
# Choose a `unique keyname` to define domain section and its configuration.
# Tip: Use app name, domain name address, port no values to create a domain key.
#
# Examples: aahframework { ... }, docs_aahframework { ... }
domain_key_name {
#
# Domain configurations - host, port and CORS, for example.
#
# Static files Routes Configuration
# Optional section- API and WebSocket apps, as examples
static {
# ...
}
# Routes Configuration
routes {
# domain routes comes here
} # end - routes
} # end - domain configurations
} # end - all application domains
Route Constraints
Route constraints give the capability to restrict/validate route parameters (aka URI parameters) before the request sent to controller action.
# Syntax
:parameterName[constraints]
Note:
- Constraint failure would result in 400 BadRequest via aah error handling flow.
- Supports multiple constraints on parameter, separated by a
,
. For instance::paramName[gte=10,lte=50]
- Data type constraints are implicit in aah
Examples
# Examples of route path parameters with constraints
#------------------------------------------------------------------------------
# Example - Data type constraints are implicit in aah
# Path : /v1/users/:id
# Controller Action : func (u *UserController) Info(id int) { .. }
# Requests
/v1/users/10001 => pass, would reach controller action
/v1/users/myname => fail, 400 BadRequest
#------------------------------------------------------------------------------
# Example - ISBN 13 route parameter constraint
# Path : /v1/books/:isbn[isbn13]/excerpt
# Controller Action : func (b *BookController) Excerpt(isbn string) { .. }
# Requests - ISBN numbers taken from https://www.isbn-13.info/example
/v1/books/978-1-56619-909-4/excerpt => pass, would reach controller action
/v1/books/9781566199094/excerpt => pass, would reach controller action
/v1/books/1-56619-909-3/excerpt => fail, 400 BadRequest
/v1/books/1566199093/excerpt => fail, 400 BadRequest
/v1/books/dshgdshgdsjhgdshg/excerpt => fail, 400 BadRequest
#------------------------------------------------------------------------------
# Example - oneof and alpha route parameter constraints
# Path : /v1/temperature/:scale[oneof=celsius fahrenheit,alpha]
# Controller Action : func (w *WeatherController) Temperature(scale string) { .. }
# Requests
/v1/temperature/fahrenheit => pass, would reach controller action
/v1/temperature/celsius => pass, would reach controller action
/v1/temperature/3463543 => fail, 400 BadRequest
/v1/temperature/blabla => fail, 400 BadRequest
#------------------------------------------------------------------------------
Supported Constraints
Constraint | Description | Example |
---|---|---|
alpha | Validates a string contains only ASCII alpha characters | :paramName[alpha] |
alphanum | Validates a string contains only ASCII alphanumeric characters | :paramName[alphanum] |
ascii | Validates a string contains only ASCII characters | :paramName[ascii] |
numeric | Validates a string contains a basic numeric value. basic excludes exponents etc. | :paramName[numeric] |
Validates a string contains a valid email. NOTE: This may not conform to all possibilities of any rfc standard, but neither does any email provider accept all possibilities | :paramName[email] | |
len | Validates - for numbers: the value is equal to the parameter given. For strings: the value length is exactly that number of characters | :paramName[len=10] |
max | Validates - for numbers: the value is less than or equal to the parameter given. For strings: the value length is at most that number of characters | :paramName[max=10] |
min | Validates - for numbers: the value is greater or equal to the parameter given. For strings: the value length is at least that number of characters | :paramName[min=10] |
eq | Validates - for strings & numbers, the value is equal to the parameter given | :paramName[eq=10] |
ne | Validates - for strings & numbers, the value is not equal to the parameter given | :paramName[ne=10] |
gt | Validates - for numbers: the value is greater than the parameter given. For strings: the value length is greater than that number of characters | :paramName[gt=10] |
gte | Same as ‘min’ above. Kept both to make terminology with len easier | :paramName[gte=10] |
lt | Validates - for numbers: the value is less than the parameter given. For strings: the value length is less than that number of characters | :paramName[lt=10] |
lte | Same as ‘max’ above. Kept both to make terminology with len easier | :paramName[lte=10] |
oneof | Validates - for strings, ints, and uints; the value is one of the values in the parameter. The parameter should be a list of values separated by whitespace. Values may be strings or numbers | :paramName[oneof=red green] |
base64 | Validates a string value contains a valid base64 value | :paramName[base64] |
btc_addr | Validates a string value contains a valid bitcoin address. The format of the string is checked to ensure it matches one of the three formats P2PKH, P2SH and performs checksum validation | :paramName[btc_addr] |
isbn | Validates a string value contains a valid isbn10 or isbn13 value | :paramName[isbn] |
isbn10 | Validates a string value contains a valid isbn10 value | :paramName[isbn10] |
isbn13 | Validates a string value contains a valid isbn13 value | :paramName[isbn13] |
uuid | Validates a string value contains a valid UUID | :paramName[uuid] |
uuid3 | Validates a string value contains a valid version 3 UUID | :paramName[uuid3] |
uuid4 | Validates a string value contains a valid version 4 UUID | :paramName[uuid4] |
uuid5 | Validates a string value contains a valid version 5 UUID | :paramName[uuid5] |
latitude | Validates a string value contains a valid latitude | :paramName[latitude] |
longitude | Validates a string value contains a valid longitude | :paramName[longitude] |
ssn | Validates a string value contains a valid U.S. Social Security Number | :paramName[ssn] |
ip | Validates a string value contains a valid IP Address | :paramName[ip] |
ipv4 | Validates a string value contains a valid v4 IP Address | :paramName[ipv4] |
ipv6 | Validates a string value contains a valid v6 IP Address | :paramName[ipv6] |
cidr | Validates a string value contains a valid CIDR Address | :paramName[cidr] |
cidrv4 | Validates a string value contains a valid v4 CIDR Address | :paramName[cidrv4] |
cidrv6 | Validates a string value contains a valid v6 CIDR Address | :paramName[cidrv6] |
tcp_addr | Validates a string value contains a valid resolvable TCP Address | :paramName[tcp_addr] |
tcp4_addr | Validates a string value contains a valid resolvable v4 TCP Address | :paramName[tcp4_addr] |
tcp6_addr | Validates a string value contains a valid resolvable v6 TCP Address | :paramName[tcp6_addr] |
udp_addr | Validates a string value contains a valid resolvable UDP Address | :paramName[udp_addr] |
udp4_addr | Validates a string value contains a valid resolvable v4 UDP Address | :paramName[udp4_addr] |
udp6_addr | Validates a string value contains a valid resolvable v6 UDP Address | :paramName[udp6_addr] |
ip_addr | Validates a string value contains a valid resolvable IP Address | :paramName[ip_addr] |
ip4_addr | Validates a string value contains a valid resolvable v4 IP Address | :paramName[ip4_addr] |
ip6_addr | Validates a string value contains a valid resolvable v6 IP Address | :paramName[ip6_addr] |
unix_addr | Validates a string value contains a valid Unix Address | :paramName[unix_addr] |
mac | Validates a string value contains a valid MAC Address | :paramName[mac] |
hostname | Validates a string value is a valid Hostname according to RFC 952, RFC 1123 | :paramName[hostname] |
fqdn | Validates a string value contains a valid FQDN | :paramName[fqdn] |