caddyserver / caddy

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
https://caddyserver.com
Apache License 2.0
55.71k stars 3.92k forks source link

v2: add one server route config will effect all server route #2938

Closed shynome closed 4 years ago

shynome commented 4 years ago

I use reverse_proxy and rewrite handle to proxy admin rest api endpoint localhost:2019 as path localhost:2020/caddy2-api, then I use the endpoint 'localhost:2020/caddy2-api to add route for other server and will wait the connection reply forover

the step to report save the below content to caddy.json, and caddy2 run -config caddy.json, then use the last section curl code check this problem

{
"admin": {
  "disabled": false,
  "listen": "localhost:2019",
  "enforce_origin": false,
  "origins": []
},
"apps": { "http": { "servers": {
    "caddy2-admin-webui": {
      "listen": ["localhost:2020"],
      "routes": [
        {
          "match": [{ "path": ["/caddy-api"] }],
          "handle": [
            { "handler": "rewrite", "strip_path_prefix": "/caddy-api" },
            { "handler": "reverse_proxy", "upstreams": [{ "dial": "localhost:2019" }] }
          ],
          "terminal": true
        }
      ],
      "automatic_https": { "disable": true }
    },
    "example-server": {
      "listen": ["localhost:2021"],
      "routes": [
        {
          "handle": [
            { "handler": "static_response", "body": "response" }
          ]
        }
      ],
      "automatic_https": { "disable": true }
    }
  }
} } 
}

Get the first route from example-sever

curl -i -X GET http://localhost:2019/config/apps/http/servers/example-server/routes

Add Route to example-sever

# Add Route through reverse proxy api. if without -m timeout param the connection will wait for forever
curl -i -m 5 -H "Content-Type: application/json" -d '{"handle": [{ "handler": "static_response", "body": "response" }]}' -X POST http://localhost:2020/caddy-api/config/apps/http/servers/example-server/routes
# Check routes and found the route had been added
curl -i -X GET http://localhost:2020/caddy-api/config/apps/http/servers/example-server/routes
# Add Route through api, this is fine
curl -i -H "Content-Type: application/json" -d '{"handle": [{ "handler": "static_response", "body": "response" }]}' -X POST http://localhost:2019/config/apps/http/servers/example-server/routes
# cehck routes and this is fine
curl -i -X GET http://localhost:2019/config/apps/http/servers/example-server/routes

Del Route from example-sever

# Delete Route through reverse proxy api. if without -m timeout param the connection will wait for forever
curl -i -m 5 -X DELETE http://localhost:2020/caddy-api/config/apps/http/servers/example-server/routes/2
# Check routes and found the route had been deleted
curl -i -X GET http://localhost:2020/caddy-api/config/apps/http/servers/example-server/routes
# Delete Route through api, this is fine
curl -i -X DELETE http://localhost:2019/config/apps/http/servers/example-server/routes/1
# cehck routes and this is fine
curl -i -X GET http://localhost:2019/config/apps/http/servers/example-server/routes
shynome commented 4 years ago

Today I use two caddy server to resolve this problem, one reverse proxy another caddy amin api and manager that, one do the normal caddy server work

shynome commented 4 years ago

caddy2 beta11 still have this problem

mholt commented 4 years ago

Thanks for the issue! I was able to follow your instructions so I think I understand what is happening.

But can you explain what the problem is? I don't understand.

Although, you do mention that -m 5 is required. Is that the problem? (It is a problem, let me explain why.)

I haven't looked in too much detail yet but my guess is that the admin endpoint (2019) is trying to close the config which runs the proxy endpoint (2020), but the proxy endpoint is waiting for the admin endpoint (2019) to close so that it can write the response back to the client. It's a standoff: one cannot gracefully close without forcefully closing the other.

So your config appears to create a contradiction. A graceful shutdown is impossible.

Can I ask... why are you doing this? Or better yet, why do you need to do this?

shynome commented 4 years ago

I try to write a web ui to manager caddy2 server, use reverse_proxy admin api the web ui can manager caddy2 server , but it can not manager itself because this problem will make proxy api request connection reset and browser return a error for this api request

mholt commented 4 years ago

So, as I said before, I think the crux of this issue is that the admin endpoint, when instigating a config reload, has to wait for the http app, which contains the HTTP server with all your custom routes and stuff, to finish shutting down. If the http app is itself serving the admin endpoint, both are waiting for the other to finish before returning, so you have a deadlock.

I am not convinced this kind of configuration is necessary/useful either. There is almost surely another way to do what you're trying to do (which still isn't clear to me).