Match path with at least one character after prefix? i.e. /path/*

1. Caddy version (caddy version):

v2.2.1

2. How I run Caddy:

a. System environment:

Ubuntu 18.04.5, created with DigitalOcean Caddy plugin

b. Command:

caddy run

or

caddy start

c. Service/unit/compose file:

N/A

d. My complete Caddyfile or JSON config:

www.mywebsite.com {
	redir https://mywebsite.com{uri} 301
}

mywebsite.com {
	tls me@email.com
	uri strip_suffix /

	handle_path /js_requests/* {
		rewrite * /path/to/js{uri}
		reverse_proxy https://my.otherserver.com
	}

	handle_path /dynamic_content/* {
		rewrite * /path/to/content{uri}
		reverse_proxy https://my.otherserver.com
	}

	handle {
		reverse_proxy http://mywebsite.com.s3-website-us-east-1.amazonaws.com
	}
}

3. The problem I’m having:

TL;DR

How can I write a handle_path directive with a prefix like /dynamic_content/* that only matches requests with at least one character after the prefix portion of the path?

Using the above Caddyfile, requests to mywebsite.com/dynamic_content are matching the handle_path /dynamic_content/* directive. The desired behavior is:

  • mywebsite.com/dynamic_content matches the last handle, and is sent to S3
  • mywebsite.com/dynamic_content/ also matches the last handle and is sent to S3
  • mywebsite.com/dynamic_content/something matches the handle_path /dynamic_content/* and is sent to my.otherserver.com/path/to/content/*

Further explanation:

I have a website hosted in S3. Most content is served from S3, but certain paths (/js_requests and /dynamic_content in my sample Caddyfile) serve content from another server (my.otherserver.com).

The first path, /js_requests, isn’t super relevant. But for the sake of being thorough:

/js_requests:
  • Requests to this path might looks like /js_requests/do_something.js
  • These requests hit my server, my.otherserver.com, via reverse proxy and return the appropriate JS file
/dynamic_content:
  • Requests to this path return HTML files to be rendered in the browser.
  • Think of these like blog posts, or products in a shop. You might request /dynamic_content/skydiving-101 – this request gets sent to our server that looks up the article called skydiving-101, renders the full HTML page for that article, and serves it.

This is all working fine given the above Caddyfile. The first two handle_path directives do exactly what they’re supposed to do for any paths /dynamic_content/some-article.

The actual problem:

Requests made to the “root” of these paths, i.e. mywebsite.com/dynamic_content, are matched here.

Our websites have a “landing page” for the dynamic content that displays a list of recent entries. Visiting mywebsite.com/dynamic_content should render this landing page. This landing page exists in S3 as a file called landing_page. Any requests to mywebsite.com/dynamic_content/*, where * is at least one character, should be sent to the server for content lookup.

Currently, if I visit mywebsite.com/dynamic_content, provided the example Caddyfile, my.otherserver.com would see a request for /path/to/content/. It’s expecting something else at the end of the path, e.g. some-article, but nothing exists, so it returns a 404. This is expected behavior on the server side, but that particular request should never hit the server in the first place.

I noticed this behavior early on when requesting mywebsite.com/dynamic_content/ (with a trailing slash), so I added the uri strip_suffix / directive to just remove all trailing slashes and avoid it. However, for some reason now it seems the /dynamic_content/* path is being matched even for requests directly to mywebsite.com/dynamic_content.

4. Error messages and/or full log output:

N/A

5. What I already tried:

As mentioned previously, I thought adding the uri strip_suffix / directive would solve the issue, but it does not.

6. Links to relevant resources:

N/A

That’s a very old version! Please upgrade to v2.4.5.

This is not a good idea, because it’s generally useful to request a directory by using a trailing slash. Things might break unexpectedly with this.

You can use the path_regexp matcher instead for this

@js path_regexp js /js_requests/(.*)+
handle @js {
	uri strip_prefix /js_requests
	reverse_proxy https://my.otherserver.com
}

@dynamic path_regexp dynamic /dynamic_content/(.*)+
handle @dynamic {
	uri strip_prefix /dynamic_content
	reverse_proxy https://my.otherserver.com
}

handle {
	reverse_proxy http://mywebsite.com.s3-website-us-east-1.amazonaws.com
}

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