Mark,

On 6/6/23 06:42, Mark Thomas wrote:
devOn 02/06/2023 18:55, Christopher Schultz wrote:
Mark,

On 6/2/23 11:00, Mark Thomas wrote:
On 02/06/2023 15:35, Christopher Schultz wrote:
All,

I've built a Filter for use with a client who has many environments, many reverse proxies, and many application servers and were getting confused about what was what.

Basically, it just adds a "Via" header as appropriate and has some configurability to choose the header name, override the protocol and server-name if requested, and to limit the number of IP-segments reported in the value.

Would this be something useful to add to Tomcat?

That implies that Tomcat is acting as a reverse proxy. Given that functionality isn't built into Tomcat, I'd expect whatever component is providing the reverse proxy functionality to provide the Via header and any other appropriate debug tools. It seems a little odd to provide a debug tool with Tomcat for a feature that Tomcat doesn't implement.

I was thinking that Tomcat here was an origin server and reporting its own identity, etc. to the reverse-proxy, which would then add its own "Via" header.

I'm a little confused about how this all works.

Sorry, I think I didn't give enough explanation.

Shouldn't the reverse proxy add the Via header before forwarding the request?

Is the Filter adding a Via header? I read the original post as it was. But Via headers are for proxy's not origin servers.

Maybe an example would help. Or a link to the Filter's source.

It's possible that I may be abusing the HTTP Via header, but I don't think so.

The idea was to provide information to the *client* about which servers are handling the request. The HTTP Via header seems to fit the billing, as a response-header and not a request-header. I'm not worried about request-headers at all, here.

My Filter basically says 'add "Via: protocol/version myself" header to the response' and that's it. The reverse-proxy can augment the Via response header with its own. So for a simple setup where we have two web servers and two Tomcat servers cross-linked, the client might see a response header looking like this:

Via: HTTP/1.1 web1, HTTP/1.1 tomcat2

I am generally in favour of adding Filters that are generally useful but wary of things that appear to behave in unexpected ways.

As you should be.

I created this Filter to be used in a situation with multiple environments and where there are multiple reverse proxies between the client and the Tomcat server. We were tracking-down what we believed was a misconfiguration of one or more of the reverse-proxies that cross-linked environments and we needed to figure out which pair of reverse-proxy servers were being used in a simple way e.g. using curl. (Automation wasn't going to solve this one, unfortunately, given the way things had been deployed).

So we configured the Tomcat servers to announce themselves and the httpd servers to do the same, using the Via header in this way.

I suppose the httpd instance could set the header to include BOTH servers, since it really ought to know its own identity as well as the identity of the origin server it's connecting to, but ... I chose this way instead since upstream could be more complicated than httpd knows.

Here is the code of the doFilter function without the source of the supporting functions:

StringBuilder serverIdentifier = new StringBuilder(64); // 64 characters ought to be enough for anybody

        String protocol = getProtocol();
        if(null == protocol) {
            protocol = httpRequest.getProtocol();

            if(null != protocol) {
                if(!getIncludeProtocolName()) {
                    int pos = protocol.indexOf('/');
                    if(0 <= pos) {
                        protocol = protocol.substring(pos + 1);
                    }
                }
                serverIdentifier.append(protocol);
            }
        } else {
            serverIdentifier.append(protocol);
        }

        String serverName = getServerName();
        if(null == serverName) {
            serverName = getTrimmedIPAddress(httpRequest.getLocalAddr());
        }

        serverIdentifier.append(' ').append(serverName);

        if(getIncludePort()) {

serverIdentifier.append(':').append(httpRequest.getLocalPort());
        }

httpResponse.addHeader(getHeaderName(), serverIdentifier.toString());

Most of the stuff has reasonable defaults. If you installed this on localhost IPv4 and didn't override anything, you'd get "Via: HTTP/1.1 1" i the response header because the IP address 127.0.0.1 would have all but the last octet of the address removed, leaving just the "1". This is pretty useless for localhost, but in a subnet with multiple backends, you'd get e.g. "Via: HTTP/1.1 42" and "Via HTTP/1.1 43" for servers on x.x.x.42 and x.x.x.43 respectively.

You can override everything, including which header to use, the "name" of the server (to get "Via: HTTP/1.1 gandalf" if that's what you want it to say) and the protocol (including the version number).

Let me know if you have any more questions. I'm happy to share full source if it would be helpful.

Re-reading the code (after already providing for some caching of certain things), I can see that it could benefit from even more caching. The common case will be that the Via header will always be set to the same thing for every single request. Sure, it's possible that some requests are served via HTTP and some via AJP, but I think usually the response header will always be the same, so it's probably worth adding a little bit of "quick checking" to avoid StringBuilder churn. Using shared structures e.g. ConcurrentHashMap may be a wash, though, so I'd be happy to get some feedback on whether this optimization won't really be effective.

-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to