Send request different port and path

1. Caddy version (caddy version):

Caddy v2.2.1

2. How I run Caddy:

Running Caddy as a service with caddy.service and systemctl.

a. System environment:

Ubuntu 20.04 (LTS) x64

b. Command:

sudo systemctl start caddy

c. Service/unit/compose file:

n/a

d. My complete Caddyfile or JSON config:

example.com {
  root * /var/www/html
  try_files {path} /index.html
  file_server
}

localhost:3000 {
  #respond "Hello world 3000!"
  reverse_proxy /api localhost:3005
}

3. The problem I’m having:

I want to route all requests into localhost:3000/api to localhost:3005. So localhost:3000/api/user/login would route to localhost:3005/user/login.

4. Error messages and/or full log output:

In my network tab the request is red and under “Transferred”, it says NS_ERROR_DOM_BAD_URI.

5. What I already tried:

I’ve seen examples of “proxy” and “reverse_proxy” and have tried both.

6. Links to relevant resources:

I wish there were more and better examples on that page. It’s not terribly helpful for figuring out how to do this.

You can use handle_path for this:

localhost:3000 {
	handle_path /api* {
		reverse_proxy localhost:3005
	}
}

The handle_path directive will strip the given path prefix from the request first before handling the rest of its contents.

Thank you for that. handle_path looks like exactly what I need. So I’ve been playing around more with this. And I think this more closely resembles what I want.

example.com {
  root * /var/www/html

  handle_path /api/* {
    reverse_proxy localhost:3005
    #respond "Hello World API"
  }

  try_files {path} /index.html
  file_server
}

Any requests to /api/* will get reverse proxied over to localhost:3005 because that is where my node server is running and the /api will get chopped off as well. And then all other requests will get handled as a file_server at /var/www/html. That’s what I want to happen and what I think that CaddyFile should be doing. But when I click the login button, it fails. In the Headers tab I can see the login button is hitting https://example.com/api/users/login. And getting a status of 200 OK back. But in the response I see You need to enable JavaScript to run this app. which tells me it is hitting my React app at /var/www/html.

The try_files directive is being sorted before handle_path, so the rewrites are always happening, instead of only when the path is not /api/*.

This is what you want:

example.com {
	handle_path /api/* {
		reverse_proxy localhost:3005
	}

	handle {
		root * /var/www/html
		try_files {path} /index.html
		file_server
	}
}

The handle directives are mutually exclusive from eachother, and are sorted using their matchers. So writing it this way, the handle without a matcher will always run last, making sure that rewrites do not happen when the path has /api/*.

Thank you again @francislavoie ! That worked perfectly!

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.