Skip to content

Conversation

@cuchaz
Copy link
Contributor

@cuchaz cuchaz commented May 26, 2025

One annoying web app (Mastodon, if you're curious) wants host headers instead of x-forwarded-host headers or it will plain refuse to work. So this patch hacks in support for generating a host header the same way the x-forwarded-host header is generated. But crucially, other apps behind the proxy fail if a host header is sent, so the configuration needs to support a per-host option to turn this on or off. This PR is my quick hack to get that working.

I wouldn't necessarily recommend merging this PR as-is, but I wanted to use the hack code to start a discussion about how to handle custom header needs in reverse proxy targets. This quick patch is enough to get my apps working, but might not be a good fit as a general contribution to Ferron the way it is now.

Maybe a better and more general way to solve this problem is to have some kind of configurable system for creating custom headers for proxy targets based on some kind of value templating using a collection of available variables. All the mainstream reverse proxy servers have something like this I think. For example, nginx has a configuration syntax like proxy_set_header Host $host;. What do you think?

in addition to x-forwarded-host headers
.headers
.insert("x-forwarded-host", original_host);
.insert("x-forwarded-host", original_host.clone());
if set_host_header {
Copy link

Choose a reason for hiding this comment

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

Duplicate Code - Priority: High

  • The logic for handling set_host_header appears to be duplicated within the file or across other files. Consider refactoring this logic into a reusable function to improve maintainability.

@hikaflow
Copy link

hikaflow bot commented May 26, 2025

PR Summary

Changes Overview

  • No changes were made in this PR.

Identified Issues

  • No issues identified.

Recommendations

  • None.

@DorianNiemiecSVRJS DorianNiemiecSVRJS added the rust Pull requests that update rust code label May 26, 2025
@DorianNiemiecSVRJS
Copy link
Member

This quick patch is enough to get my apps working, but might not be a good fit as a general contribution to Ferron the way it is now.

You don't need to worry about that - your patch would allow Ferron to work with Mastodon, as you mentioned in the pull request description.

The only thing missing is a validator for the new proxyHostHeader configuration property, but I can easily add the validator.

@DorianNiemiecSVRJS
Copy link
Member

Well, I have implemented setting request headers for sending to backend servers with support for placeholders in a development branch for Ferron 2.x beta ("develop-2.x").
For your use case, adding a directive inside of one of the host or location blocks would work in the future version of Ferron 2.x beta:

// This is just a configuration example
example.com {
  proxy "http://localhost:3000"
  proxy_request_header_replace "Host" "{header:Host}"
}

@cuchaz
Copy link
Contributor Author

cuchaz commented Jul 13, 2025

Nice. That certainly looks useful.

Is the config still in YAML language? The config you're showing above looks like it might be something new?

@DorianNiemiecSVRJS
Copy link
Member

Nice. That certainly looks useful.

Thank you!

Is the config still in YAML language? The config you're showing above looks like it might be something new?

The Ferron 2.x configuration I have shown is not YAML anymore; it's a different format.
Ferron 2.x can still be used with YAML configurations; the YAML configuration support is just for backwards compatiblity with Ferron 1.x.

@cuchaz
Copy link
Contributor Author

cuchaz commented Jul 13, 2025

Oh, I see. According to the newer v2 docs, the new format is KDL? Looks pretty great actually. YAML isn't my favorite format if we're being honest, so KDL looks like it could be an improvement.

Although, one particular YAML feature I was using to share config between multiple domains (eg example.com and www.example.com) was dereferencing * and label &. It wasn't a great solution really, since the YAML << : *label syntax didn't seem to be supported by the parser Ferron uses, but I could get by with dereferencing each key for a domain individually (eg, wwwroot: *label).

Here's a complete example, although a bit simplified from the config I'm actually using:

all: &all
  wwwroot: &all_root "/var/www/example.com"
  errorPages: &all_errors
    - scode: 404
      path: "/var/www/example.com/404.html"

hosts:
  - domain: "example.com"
    wwwroot: *all_root
    errorPages: *all_errors
  - domain: "www.example.com"
    wwwroot: *all_root
    errorPages: *all_errors

Does the new configuration format make sharing config between two domains any easier? Maybe this is a KDL feature for dereferencing like YAML has? Or maybe it's something Ferron's config system can do? Maybe something like example.com www.example.com { ... } ?

@DorianNiemiecSVRJS
Copy link
Member

Yes, the new format is KDL.

I was thinking about implementing the support for multi-host blocks in Ferron 2.x, like this:

example.com,www.example.com {
  // Configuration for "example.com" and "www.example.com"
}

I have just implemented the support in the 3d76bba commit. The support will be available in the next release of Ferron 2.x.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants