Caddy: Client's POST request with http://,and the Caddy server auto become to GET request.

Created on 8 Aug 2016  ·  16Comments  ·  Source: caddyserver/caddy

Client's POST request with http://,and the Caddy server auto become to GET request.

Most helpful comment

@vchimishuk I was talking about Caddys auto redirect feature from http to https. The solution here is disable that feature. I ran a test to make sure it's what I thought. See attached file.

web.zip

Run caddy from web/backend directory with no params. Starts up fake backend service to receive the proxy requests on localhost:8000. On all requests it replies back with simple json test file.

Run caddy from web/ directory with -email and -agree and have it auto get certificate for your domain (alter it in Caddyfile).

# curl -X POST -i http://api.xxxx.com/api/v1/user/save
HTTP/1.1 301 Moved Permanently
Location: https://api.xxxx.com/api/v1/user/save
Server: Caddy
Date: Thu, 11 Aug 2016 18:57:23 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8
# curl -X GET -i http://api.xxxx.com/api/v1/user/save
HTTP/1.1 301 Moved Permanently
Location: https://api.xxxx.com/api/v1/user/save
Server: Caddy
Date: Thu, 11 Aug 2016 18:57:42 GMT
Content-Length: 75
Content-Type: text/html; charset=utf-8

<a href="https://api.xxxx.com/api/v1/user/save">Moved Permanently</a>.

# curl -X GET -i https://api.xxxx.com/api/v1/user/save
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 20
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Aug 2016 18:58:35 GMT
Etag: W/"57acbb44-14"
Last-Modified: Thu, 11 Aug 2016 17:52:04 GMT
Server: Caddy
Server: Caddy

{ "key" : "value" }

_Ignore the two Server headers (one is from Proxy response)_ Bug?

# curl -X POST -i https://api.xxxx.com/api/v1/user/save
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 20
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Aug 2016 18:59:49 GMT
Etag: W/"57acbb44-14"
Last-Modified: Thu, 11 Aug 2016 17:52:04 GMT
Server: Caddy
Server: Caddy

{ "key" : "value" }

Now changing Caddyfile to the following will disable the auto redirect

http://api.xxxx.com, https://api.xxxx.com {
    ...
}

Restart caddy in web/ and now notice no redirect.

# curl -X POST -i http://api.xxxx.com/api/v1/user/save
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 20
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Aug 2016 19:01:13 GMT
Etag: W/"57acbb44-14"
Last-Modified: Thu, 11 Aug 2016 17:52:04 GMT
Server: Caddy
Server: Caddy

{ "key" : "value" }
# curl -X GET -i http://api.xxxx.com/api/v1/user/save
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 20
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Aug 2016 19:01:19 GMT
Etag: W/"57acbb44-14"
Last-Modified: Thu, 11 Aug 2016 17:52:04 GMT
Server: Caddy
Server: Caddy

{ "key" : "value" }

So basically the difference here is simply the auto-redirect. Perhaps this feature should be better documented? Anyway after looking at the logs for these requests everything is working correctly. Caddy is not at fault. I think its its AFNetworking not handling the 301 response for the POST.

@arden So the fix is simply to use the above to disable the auto-redirect in the Caddyfile, and posts to both http and https should work fine.

All 16 comments

I'm not sure what you mean. Can you please use the issue template to fill out a bug report with details?

i'm use caddy and nodejs, caddy as proxy server, nodejs as backend server, this is my Caddyfile:

api.xxxx.com {
    root /alidata1/webapp/TuyaApiServer/static
    # 这里如果用压缩会对ios的AFNetworking不兼容,强制把POST请求变成了GET请求
    # gzip
    log /alidata1/log/access.log

    proxy / localhost:8000 {
        except /static /robots.txt
    }
}

Now i have a POST method API that:
http://api.xxxx.com/api/v1/user/save

and then, i'm call it in IOS use AFNetworking as POST method.

if i'm call https://api.xxxx.com/api/v1/user/save, could success

if i'm call http://api.xxxx.com/api/v1/user/save, couldn't success, 404 not found.

i'm found in Caddy's logs, the http POST request become to GET request.

"GET /api/v1/user/save HTTP/2.0" 404 33

but the success logs is:

"POST /api/v1/user/save HTTP/1.1" 200 483

I think http2 only support https

I still don't understand.

if i'm call https://api.xxxx.com/api/v1/user/save, could success

if i'm call http://api.xxxx.com/api/v1/user/save, couldn't success, 404 not found.

What are the methods on these requests? Why are you using HTTP?

i'm found in Caddy's logs, the http POST request become to GET request.

"GET /api/v1/user/save HTTP/2.0" 404 33

but the success logs is:

"POST /api/v1/user/save HTTP/1.1" 200 483

So the first one is in Caddy's log but what is the second one from?

And what are you expecting to see?

When i'm call http://api.xxxx.com/api/v1/user/save in ios with AFNetworking, there some errors: 404 Not found.

but i'm call https://api.xxxx.com/api/v1/user/save, that succes.

and they are both do the same some thing.

我用Nodejs实现了一个POST请求:/api/v1/user/save
当我在ios程序里用AFNetworking进行POST请求这个API接口的时候
如果直接请求: https://api.xxxx.com/api/v1/user/save 就可以正常请求成功。
但是如果我请求:http://api.xxxx.com/api/v1/user/save 的时候就会报:
404 not found 错误,说找不到这个URL请求。
也就是说当是POST请求的时候,如果用http协议就不能成功,直接用https协议就可以。

@mholt Is this simply the auto-redirect from http to https causing the issue? because he's not specified the server type in the host field of the Caddyfile.

@slightfoot can you tell me, how to specify the server type in the host field of the Caddyfile?

@arden, I think @slightfoot means tls off

api.xxxx.com {
    tls off
    ...
}

@slightfoot tls cannot be set to off.

I'm still confused. The issue originally mentioned that a POST request was being transformed into a GET request, but now it seems to be an issue with the scheme. Are there two different things going on?

Because the http request auto-redirect https request, this for GET request should be success, but for POST request (Nodejs backend API that only POST method) couldn't success. Caddy auto-redirect from http to https as the GET request, but nodejs API only allow POST, so the client request throws: 404 Not found.

Then you either set tls off as @arden suggested or use https:// instead.

@vchimishuk I was talking about Caddys auto redirect feature from http to https. The solution here is disable that feature. I ran a test to make sure it's what I thought. See attached file.

web.zip

Run caddy from web/backend directory with no params. Starts up fake backend service to receive the proxy requests on localhost:8000. On all requests it replies back with simple json test file.

Run caddy from web/ directory with -email and -agree and have it auto get certificate for your domain (alter it in Caddyfile).

# curl -X POST -i http://api.xxxx.com/api/v1/user/save
HTTP/1.1 301 Moved Permanently
Location: https://api.xxxx.com/api/v1/user/save
Server: Caddy
Date: Thu, 11 Aug 2016 18:57:23 GMT
Content-Length: 0
Content-Type: text/plain; charset=utf-8
# curl -X GET -i http://api.xxxx.com/api/v1/user/save
HTTP/1.1 301 Moved Permanently
Location: https://api.xxxx.com/api/v1/user/save
Server: Caddy
Date: Thu, 11 Aug 2016 18:57:42 GMT
Content-Length: 75
Content-Type: text/html; charset=utf-8

<a href="https://api.xxxx.com/api/v1/user/save">Moved Permanently</a>.

# curl -X GET -i https://api.xxxx.com/api/v1/user/save
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 20
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Aug 2016 18:58:35 GMT
Etag: W/"57acbb44-14"
Last-Modified: Thu, 11 Aug 2016 17:52:04 GMT
Server: Caddy
Server: Caddy

{ "key" : "value" }

_Ignore the two Server headers (one is from Proxy response)_ Bug?

# curl -X POST -i https://api.xxxx.com/api/v1/user/save
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 20
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Aug 2016 18:59:49 GMT
Etag: W/"57acbb44-14"
Last-Modified: Thu, 11 Aug 2016 17:52:04 GMT
Server: Caddy
Server: Caddy

{ "key" : "value" }

Now changing Caddyfile to the following will disable the auto redirect

http://api.xxxx.com, https://api.xxxx.com {
    ...
}

Restart caddy in web/ and now notice no redirect.

# curl -X POST -i http://api.xxxx.com/api/v1/user/save
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 20
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Aug 2016 19:01:13 GMT
Etag: W/"57acbb44-14"
Last-Modified: Thu, 11 Aug 2016 17:52:04 GMT
Server: Caddy
Server: Caddy

{ "key" : "value" }
# curl -X GET -i http://api.xxxx.com/api/v1/user/save
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 20
Content-Type: text/plain; charset=utf-8
Date: Thu, 11 Aug 2016 19:01:19 GMT
Etag: W/"57acbb44-14"
Last-Modified: Thu, 11 Aug 2016 17:52:04 GMT
Server: Caddy
Server: Caddy

{ "key" : "value" }

So basically the difference here is simply the auto-redirect. Perhaps this feature should be better documented? Anyway after looking at the logs for these requests everything is working correctly. Caddy is not at fault. I think its its AFNetworking not handling the 301 response for the POST.

@arden So the fix is simply to use the above to disable the auto-redirect in the Caddyfile, and posts to both http and https should work fine.

Okay, I think I'm starting to follow.

The redirect is documented:

Caddy will also redirect all HTTP requests to their HTTPS equivalent if the plaintext variant of the hostname is not defined in the Caddyfile.

Once a redirect has been issued, it's the client's responsibility to execute it properly with the correct method, body, etc.

Thanks for your question, and thank you especially @slightfoot for the explanation! Hope that was helpful.

thanks @slightfoot for the explanation.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SteffenDE picture SteffenDE  ·  3Comments

ericmdantas picture ericmdantas  ·  3Comments

whs picture whs  ·  3Comments

billop picture billop  ·  3Comments

klaasel picture klaasel  ·  3Comments