Redir sends empty HTTP body

1. Caddy version (caddy version):

v2.5.2

2. How I run Caddy:

I’m running Postman and calling a HTTP POST on:

http://vm.covergre.local:4905/api/login

vm.covergre.local is the host for a virtual machine, where Caddy Server is configured.

a. System environment:

Ubuntu 20.04

b. Command:

caddy fmt --overwrite /etc/caddy/Caddyfile
cd /etc/caddy
caddy reload

c. Service/unit/compose file:

d. My complete Caddyfile or JSON config:

handle :4905 {
	handle_path /api/* {
		redir http://cover-applqlt.covergre.local:8020/sysctl/zmpis{uri}?client=200
	}
	handle * {
		reverse_proxy localhost:4903
	}
}

3. The problem I’m having:

The problem I’m having is that the redir is sending the HTTP request without a payload/body.
The purpose of this Caddy file is to send anything starting with /api/* to cover-applqlt.covergre.local and all other request to a different port on the same machine.

4. Error messages and/or full log output:

5. What I already tried:

I’ve tried changing the redir to a reverse_proxy like this:

{
	debug
}
handle :4905 {
	handle_path /api/* {
		reverse_proxy cover-applqlt.covergre.local:8020/sysctl/zmpis{uri}?client=200 {
			transport http {
				tls_insecure_skip_verify
			}
		}
	}
	handle * {
		reverse_proxy localhost:4903
	}
}

But I’m getting 502 Bad Gateway with error ‘missing port in address’. This is the log:

2022/07/15 14:19:50.289 
DEBUG   
http.handlers.rewrite   
rewrote request 
{
    "request": {
        "remote_ip": "172.16.222.141",
        "remote_port": "58982",
        "proto": "HTTP/1.1",
        "method": "POST",
        "host": "vm.covergre.local:4905",
        "uri": "/api/login",
        "headers": {
            "Content-Length": [
                "61"
            ],
            "Content-Type": [
                "application/json"
            ],
            "User-Agent": [
                "PostmanRuntime/7.29.0"
            ],
            "Accept-Encoding": [
                "gzip, deflate, br"
            ],
            "Connection": [
                "keep-alive"
            ],
            "X-Authorization": [
                "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IkFETUlOIiwiaWF0IjoxNjU3MTE5MTgxLCJleHAiOjE2NTcxMTkyNDF9.k182k94KD2k1mukWDAC2xHQGhJxHiQZ9A43UTH388Fzy3xYCxFhemGAOOnHgmvgQbs5FnWibIF7O7tbjh4MK7Q"
            ],
            "Accept": [
                "*/*"
            ],
            "Postman-Token": [
                "7d2fbdeb-6109-4899-9777-6b79450dbdf8"
            ]
        }
    },
    "method": "POST",
    "uri": "/login"
}


2022/07/15 14:19:50.289 
ERROR   
http.log.error.log0     
making dial info: 
upstream cover-applqlt.covergre.local:8020/sysctl/zmpis{http.request.uri}?client=200: 
invalid dial address cover-applqlt.covergre.local:8020/sysctl/zmpis/login?client=200: 
address sysctl/zmpis/login?client=200: missing port in address
{
    "request": {
        "remote_ip": "172.16.222.141",
        "remote_port": "58982",
        "proto": "HTTP/1.1",
        "method": "POST",
        "host": "vm.covergre.local:4905",
        "uri": "/api/login",
        "headers": {
            "Content-Length": [
                "61"
            ],
            "Content-Type": [
                "application/json"
            ],
            "User-Agent": [
                "PostmanRuntime/7.29.0"
            ],
            "Accept-Encoding": [
                "gzip, deflate, br"
            ],
            "Connection": [
                "keep-alive"
            ],
            "X-Authorization": [
                "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IkFETUlOIiwiaWF0IjoxNjU3MTE5MTgxLCJleHAiOjE2NTcxMTkyNDF9.k182k94KD2k1mukWDAC2xHQGhJxHiQZ9A43UTH388Fzy3xYCxFhemGAOOnHgmvgQbs5FnWibIF7O7tbjh4MK7Q"
            ],
            "Accept": [
                "*/*"
            ],
            "Postman-Token": [
                "7d2fbdeb-6109-4899-9777-6b79450dbdf8"
            ]
        }
    },
    "duration": 0.000159699,
    "status": 502,
    "err_id": "6uwx1v698",
    "err_trace": "reverseproxy.statusError (reverseproxy.go:1184)"
} 

Any help will be greatly appreciated.
Thank you!

6. Links to relevant resources:

To clarify, Caddy sends HTTP responses to clients, not HTTP requests.

And sending an HTTP response without a body is perfectly normal, and is quite common with HTTP 3xx redirects.

The problem is the structure of your Caddyfile:

handle :4905 {

Since this is the first line (after global options), you’re telling Caddy to serve sites at handle and :4905. I presume you meant to omit handle from that line.

Hello Matt,

Thank you for taking the time.
I’ve tried without the handle like so:

:4905 {
	handle_path /api/* {
		redir http://cover-applqlt.covergre.local:8020/sysctl/zmpis{uri}?client=200
	}
	handle * {
		reverse_proxy localhost:4903
	}
}

But I’m still missing the payload.

If anybody has this issue. I’ve solved it by changing from redir to reverse_proxy and added a rewrite before it like so:

:4905 {
	handle_path /api/* {
        rewrite * /sysctl/zmpis{uri}?client=200
		reverse_proxy cover-applqlt.covergre.local:8020
	}
	handle * {
		reverse_proxy localhost:4903
	}
}