Skip to content

Conversation

amirdaraby
Copy link

Description

This PR fixes #7246
where the Admin API /load endpoint returned 200 OK instead of 400 Bad Request when an invalid Caddyfile also produced adapter warnings.

The problem happened because the warnings were written to the response first, which made http.ResponseWriter default to 200 OK. As a result, the response contained two separate JSON objects (warnings + error) stuck together, which was invalid JSON.

Changes

  • add "warnings" as valid JSON structure alongside to "errors" in JSON response.
  • Make sure the correct status code (400 Bad Request) is returned for invalid configs.

Behavior Before

curl -v --unix-socket /run/uncloud/caddy/admin.sock \
  -H "Content-Type: text/caddyfile" \
  --data-binary @Caddyfile \
  http://localhost/load
*   Trying /run/uncloud/caddy/admin.sock:0...
* Connected to localhost (/run/uncloud/caddy/admin.sock) port 0
* using HTTP/1.x
> POST /load HTTP/1.1
> Host: localhost
> User-Agent: curl/8.14.1
> Accept: */*
> Content-Type: text/caddyfile
> Content-Length: 81
> 
* upload completely sent off: 81 bytes
< HTTP/1.1 200 OK
< Date: Fri, 19 Sep 2025 15:21:18 GMT
< Content-Length: 336
< Content-Type: text/plain; charset=utf-8
< Connection: close
< 
[{"file":"Caddyfile","line":2,"message":"Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies"}]{"error":"loading config: loading new config: loading http app module: provision http: getting tls app: loading tls app module: provision tls: loading certificates: open cert.pem: no such file or directory"}
* shutting down connection #0

Behavior After

curl -v --unix-socket /run/uncloud/caddy/admin.sock \
  -H "Content-Type: text/caddyfile" \
  --data-binary @Caddyfile \
  http://localhost/load
*   Trying /run/uncloud/caddy/admin.sock:0...
* Connected to localhost (/run/uncloud/caddy/admin.sock) port 0
* using HTTP/1.x
> POST /load HTTP/1.1
> Host: localhost
> User-Agent: curl/8.14.1
> Accept: */*
> Content-Type: text/caddyfile
> Content-Length: 81
> 
* upload completely sent off: 81 bytes
< HTTP/1.1 400 Bad Request
< Date: Fri, 19 Sep 2025 15:26:41 GMT
< Content-Length: 348
< Content-Type: text/plain; charset=utf-8
< Connection: close
< 
{"error":"loading config: loading new config: loading http app module: provision http: getting tls app: loading tls app module: provision tls: loading certificates: open cert.pem: no such file or directory","warnings":[{"file":"Caddyfile","line":2,"message":"Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies"}]}
* shutting down connection #0

@CLAassistant
Copy link

CLAassistant commented Sep 19, 2025

CLA assistant check
All committers have signed the CLA.

Copy link
Member

@mholt mholt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, thank you. Although, we should still probably return caddy.APIError if possible?

@amirdaraby
Copy link
Author

I agree. I'll update it so warnings also return caddy.APIError, to make sure error responses follow the same format.

@amirdaraby
Copy link
Author

I moved Warning into a separate package so it can be reused in caddy.APIError without causing import cycles. Now /load returns a proper APIError with both error and warnings fields.

@mohammed90
Copy link
Member

mohammed90 commented Oct 4, 2025

I moved Warning into a separate package so it can be reused in caddy.APIError without causing import cycles. Now /load returns a proper APIError with both error and warnings fields.

This breaks every single config adapter in the ecosystem. That's more than 1. We can't break that many.

I wonder if Go type aliases may be helpful in this instance though.

@amirdaraby amirdaraby force-pushed the fix/admin-warnings-in-response branch from b7f1368 to 106f1ec Compare October 4, 2025 17:02
@amirdaraby amirdaraby closed this Oct 4, 2025
@amirdaraby amirdaraby force-pushed the fix/admin-warnings-in-response branch from 04ac46e to 39ace45 Compare October 4, 2025 17:04
@mohammed90
Copy link
Member

Did you mean to do that??

@amirdaraby amirdaraby reopened this Oct 4, 2025
@amirdaraby
Copy link
Author

@mohammed90 Thanks for the suggestion, it was really helpful. I updated the code accordingly.

@amirdaraby
Copy link
Author

amirdaraby commented Oct 4, 2025

I think it would make sense to have another response type for success responses with warnings.

check these lines:
https://github.com/caddyserver/caddy/blob/master/caddyconfig/load.go#L165

https://github.com/caddyserver/caddy/pull/7267/files#diff-0c8bfec4802d5d401d81e1e2e4867055a211b8cf5a404c7ae16ef2e8419cb98fR132

I can add this as well if that’s okay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Admin API /load returns 200 OK for invalid Caddyfile when it's not formatted with 'caddy fmt'
4 participants