This is the configuration.
http://localhost:3120 {
header {
Access-Control-Allow-Origin *
Access-Control-Allow-Headers authorization
}
@option {
method OPTIONS
}
handle @option {
respond 200 {
close
}
}
handle /api/* {
respond "xx" 201
}
}
I used curl to test this.
$ caddy version
v2.0.0 h1:pQSaIJGFluFvu8KDGDODV8u4/QRED/OPyIR+MWYYse8=
$ curl -s -v 'http://localhost:3120/api/xx' -X OPTIONS 2>&1 | grep '< HTTP'
< HTTP/1.1 201 Created
The status code returned should be 200.
I tried using the beta version, and it returned the expected results.
$caddy version
v2.0.0-beta.15 h1:Td1esMk7bebftnoBuT3gOqUGxew5HqdIKw3s36S8tNw=
$ curl -s -v 'http://localhost:3120/api/xx' -X OPTIONS 2>&1 | grep '< HTTP'
< HTTP/1.1 200 OK
I did the same test on Windows 10 and Ubuntu with the same results.
Caddy v2.0.0 behaves weirdly.
If you adapt your config to JSON, you'll notice that Caddy sorts the handlers are sorted in the opposite order than you expect:
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [
":3120"
],
"routes": [
{
"match": [
{
"host": [
"localhost"
]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "headers",
"response": {
"set": {
"Access-Control-Allow-Headers": [
"authorization"
],
"Access-Control-Allow-Origin": [
"*"
]
}
}
}
]
},
{
"group": "group3",
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"body": "xx",
"handler": "static_response",
"status_code": 201
}
]
}
]
}
],
"match": [
{
"path": [
"/api/*"
]
}
]
},
{
"group": "group3",
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"close": true,
"handler": "static_response",
"status_code": 200
}
]
}
]
}
],
"match": [
{
"method": [
"OPTIONS"
]
}
]
}
]
}
],
"terminal": true
}
],
"automatic_https": {
"skip": [
"localhost"
]
}
}
}
}
}
}
Specifically, Caddy sorts handlers by the length of their path matchers. This is usually the right thing to do for most usecases because by far the most commonly used request matcher is the path matcher. Your case is a pretty representative example where that doesn't have the expected effect.
To fix this, I'd recommend wrapping your handle blocks in a route block which tells the Caddyfile parser to preserve the order as written in the Caddyfile.
http://localhost:3120 {
header {
Access-Control-Allow-Origin *
Access-Control-Allow-Headers authorization
}
@option {
method OPTIONS
}
route {
handle @option {
respond 200 {
close
}
}
handle /api/* {
respond "xx" 201
}
}
}
For next time, please ask your usage questions on the Caddy community forums. We prefer to keep the GitHub issue board for bugs and feature requests. Don't forget to fill out the thread template so we can help you!
To add more explanation, handle blocks are kept in their written order except when sorted by length of path matcher. Length, or "specificity", of other matchers (like method matchers) are not defined. Which is more specific (or "longer"): a path of /api/foo or any OPTIONS request? It doesn't even make sense. Hence, the written order is preserved for handle blocks without a path matcher.
@francislavoie @mholt Thanks
Most helpful comment
If you adapt your config to JSON, you'll notice that Caddy sorts the handlers are sorted in the opposite order than you expect:
Specifically, Caddy sorts handlers by the length of their path matchers. This is usually the right thing to do for most usecases because by far the most commonly used request matcher is the path matcher. Your case is a pretty representative example where that doesn't have the expected effect.
To fix this, I'd recommend wrapping your
handleblocks in arouteblock which tells the Caddyfile parser to preserve the order as written in the Caddyfile.For next time, please ask your usage questions on the Caddy community forums. We prefer to keep the GitHub issue board for bugs and feature requests. Don't forget to fill out the thread template so we can help you!