2

I have an apache2 web server that handles reverse proxy for Rails3 app running on another machine.

The setup works except URLs generated within the webapp aren't getting rewritten by my configuration for mod_proxy_html.

The "Reverse Proxy Scenario" is exactly what I'm trying to do, so I've followed the tutorial as completely as I know how.

I've applied or tried answers supplied here on stackoverflow, to no effect.

According to the "Reverse Proxy Scenario" you want a number of modules loaded. All those instructions are in my httpd.conf file and when I examine the output from

apactectl -t -D DUMP_MODULES

all the expected modules show in amongst the listing.

My external web server doing the reverse proxy is at www.ourdomain.org and the Rails app is internally available at apphost.local (the server is Mac OS X Server 10.6, the rails app server is Mac OS X 10.6).

What's working right now is access to the webapp via the reverse proxy as:

http://www.ourdomain.org/apphost/railsappname/controllername/action 

But none of the javascript files, css files or other assets get loaded, and links internal to the web app come out missing the apphost portion of the URL, as if my rewrite rule is configured incorrectly (so of course I've focused on that and can't seem to get anything to be added or deleted in the process of passing the html in from the apphost and out through the Apache server).

For instance, hovering over an action link in the html returned by the web app you'll get:

http://www.ourdomain.org/railsappname/controllername/action

Here's what my Apache directives look like:

LoadModule proxy_html_module /usr/libexec/apache2/mod_proxy_html.so
LoadModule xml2enc_module /usr/libexec/apache2/mod_xml2enc.so
    ProxyHTMLLogVerbose On
    LogLevel Debug
    ProxyPass /apphost/  http://apphost.local/
    <Location /apphost/>
            SetOutputFilter INFLATE;proxy-html;DEFLATE
            ProxyPassReverse /
            ProxyHTMLExtended On
            ProxyHTMLURLMap railsappname/ apphost/railsappname/
            RequestHeader unset Accept-Encoding
    </Location>

After every change I make to httpd.conf I religiously check apachectl -t just to be sane.

I'm definitely not an Apache expert, but all the directives that follow mine seem to not overrule what I'm doing here. But then nothing that I try seems to alter the URLs I see in my browser after hitting the Apache server with a request for my web app.

Even if you can't tell what I've done incorrectly, I'd welcome ideas on how to get Apache to help see what it's working on and doing to the html coming from my web app. That's what I understood the ProxyHTMLLogVerbose On and LogLevel Debug to be setting up, but I'm not seeing anything in the log files.

tobinjim
  • 135
  • 1
  • 1
  • 6
  • What path are the resources loading from in the application's HTML? Can you alter those paths to be relative so that they'll function regardless of the apparent path? – Shane Madden Aug 27 '12 at 02:54
  • Looked into that already, and they are relative. When you access the web app at the web app host (like on a client within the org network) it all loads fine, and it's all relative. But relative to the reverse proxy URL will not work since there's nothing there to tell the reverse proxy to add the apphost back into the URL. – tobinjim Aug 27 '12 at 03:07
  • That means it's not relative, then - you have a leading slash in your resource URLs. The client constructs the request, not the proxy - the proxy is not capable of "adding back" to the URL in any way; mod_proxy_html is a workaround to transform the HTML response. The client needs to request `/apphost/path/to/resource.css` instead of `/path/to/resource.css`, which means that instead of `` you should have `href="path/to/resource.css"` relative to the location of the page that's loading the CSS. – Shane Madden Aug 27 '12 at 04:27
  • Thanks, Shane. So I used curl to see what HTML was coming back from the app server to the web server. The links are starting with a slash, "/app/controller/action" -- I'll read more on mod_proxy_html, but it sure reads as though it can pick up on the presence of /app/ in returned HTML and rewrite it as /apphost/app/ – tobinjim Aug 27 '12 at 16:48
  • Yes, it's capable of doing that, but a more reliable and portable solution would be to have the application not care what directory it's in. For instance, if CSS or javascript are involved in populating resource URLs, mod_proxy_html isn't capable of helping. – Shane Madden Aug 27 '12 at 22:25
  • Hmm. From http://www.apachetutor.org/admin/reverseproxies "mod_proxy_html doesn't parse Javascript or CSS, so dealing with URLs in them requires text-based search-and-replace. This is enabled by the directive ProxyHTMLExtended On." I read that to mean that if you need to get rewritten as "/apphost/webapp/..." that extended mode would help there. – tobinjim Aug 27 '12 at 23:25
  • Shane, it turns out that mod_proxy_html needs to be told explicitly which attributes you want it to work on (not sure when that started but definitely true in my version, 3.1.2). And it can be told to look inside javascripts to rewrite URLs -- see the SVN link brain99 provided. Good stuff! – tobinjim Aug 29 '12 at 16:08

1 Answers1

1

Maybe a bit of a simplistic answer, but most (if not all) ProxyHTMLURLMap directives I've seen so far have a / at the beginning of the match/replace pattern. Have you tried this variant of your configuration?

ProxyHTMLURLMap /railsappname/ /apphost/railsappname/

If that does not help, what version of apache are you running? And if applicable, which version of the module? It only comes bundled with apache since apache 2.4, so for older versions of apache you must have installed (some version of) this module yourself.

As an alternative you can also switch to mod_substitute, although that requires more configuration than mod_proxy_html.

At some point, they removed some built-in configuration, which requires you to add it yourself. See http://apache.webthing.com/svn/apache/filters/proxy_html/proxy_html.conf, the ProxyHTMLLinks and ProxyHTMLEvents directives are the ones you need to add to your config.

brain99
  • 1,772
  • 11
  • 18
  • I'm up for any simplistic answers! I was not preceding the paths with a slash, so at your suggestion, I just tried. It didn't change anything. It really feels like mod_proxy_html isn't activated. Apache 2.2.21 -- I downloaded mod_proxy_html just about a week ago when I started all this, so I believe it's the current version. Thanks for your response! – tobinjim Aug 27 '12 at 16:26
  • All right, up to some other things to check then. Are you sure that your `` block is being used? How about placing something trivial to check (using firebug or similar) in there, like adding an extra HTTP response header? `Header add Server foo` This will also allow you to make 100% sure that your responses are not being cached somewhere, which could also explain why they are not being processed properly. Also, you say you're not seeing anything in the log files, but with LogLevel Debug, your error.log should have loads of entries. Are you checking the correct log? – brain99 Aug 27 '12 at 17:10
  • I'm not sure any of it is working ;-) However, after a graceful restart, Apache does report "[Mon Aug 27 12:16:31 2012] [notice] Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r PHP/5.3.8 proxy_html/3.1.2 configured -- resuming normal operations" so I believe proxy_html to be configured... I added your header suggestion *outside* of the location block to see if I could get *something* showing up. In Firebug there is a Server annotation, but it's what I expect from the apphost anyway. – tobinjim Aug 27 '12 at 19:26
  • I just moved my additions to httpd.conf to the very end to ensure that nothing else was unsetting my directives. I am now getting [debug] messages in error_log, so that's an apparent improvement. They don't seem related to what I'm working on though, as they are notes about /server-status and caching of store_headers... – tobinjim Aug 27 '12 at 19:34
  • (trimmed date/time to fit) proxy_util.c(1818): proxy: grabbed scoreboard slot 34 in child 54100 for worker http://apphost.ourdomain.org/ proxy_util.c(1837): proxy: worker http://apphost.ourdomain.org/ already initialized proxy_util.c(1934): proxy: initialized single connection worker 34 in child 54100 for (apphost.ourdomain.org) proxy_util.c(1818): proxy: grabbed scoreboard slot 35 in child 54100 for worker proxy:reverse proxy_util.c(1837): proxy: worker proxy:reverse already initialized proxy_util.c(1934): proxy: initialized single connection worker 35 in child 54100 for (*) – tobinjim Aug 27 '12 at 19:40
  • Also, according to Firebug, the GET tasks has a status of 304 Not Modified. I added, inside the block, a Header add Warning="testing underway" directive since a) there was already a Server entry in the headers, and b) there was no Warning entry in the headers. Does this sound like a valid test? No warning entry is present in the headers after a graceful restart of my Apache server and a request to the proxiedapp host. – tobinjim Aug 27 '12 at 19:53
  • A status of 304 Not Modified means the response was cached. Did you try to force a full refresh with ctrl+f5? Also, from your comment ("I am now getting [debug] messages") it seems that your first additions were not being loaded at all. In which file did you put them at first? – brain99 Aug 27 '12 at 20:06
  • Okay, I figured out a way to get Firefox (Mac OS X) to refresh, such that I got a 200 OK status, but that hasn't changed any of the response headers to include my "Header add Server foo" or 'Header add Warning="testing underway"' directives. – tobinjim Aug 27 '12 at 20:21
  • The exact location of my block in httpd.conf was immediately following the MaxRequestsPerChild directive and before the Dynamic Shared Object (DSO) Support section (which precedes the LoadModule entries). I have now removed my work from httpd.conf and added an Include directive at the end of httpd.conf to pull in a new include file containing just my directives. – tobinjim Aug 27 '12 at 20:21
  • I simplified things trying to get to the smallest case I could verify and ensure I understood. Header add X-Test Testing works as expected: only requests that include /apphost/ get the test header. – tobinjim Aug 28 '12 at 06:11
  • What's still not working is any sort of reverse html adjusting. So here's a basic question: Should the ProxyHTMlURLMap be a part of the Apache configuration on the public web server or on the internal app server? I set ProxyHTMLExtended On and then I ask for ProxyHTMLURLMap /appname/ /apphost/appname/ -- but nothing ever happens. And no log entries. Frustrating! – tobinjim Aug 28 '12 at 06:16
  • Did you compile the module yourself, or did you download a binary? If you simply downloaded a binary, it may be that not all dependencies for the module are met. Is there any kind of error logged upon (re)starting apache? – brain99 Aug 29 '12 at 07:01
  • Compiled from source. No errors or warnings in error_log after an apachectl graceful – tobinjim Aug 29 '12 at 14:40
  • let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/4669/discussion-between-brain99-and-tobinjim) – brain99 Aug 29 '12 at 14:55
  • For folks who come along afterwards, the key was that in my version of mod_proxy_html, 3.1.2: "All knowledge of HTML links has been removed from the mod_proxy_html # code itself, and is instead read from httpd.conf (or included file) # at server startup. So you MUST declare it. This will normally be # at top level, but can also be used in a ." So the first step in having anything be altered by mod_proxy_html was to add "ProxyHTMLLinks a href" as a directive inside my Many thanks to brain99 for seeing that. – tobinjim Aug 29 '12 at 15:41
  • Please add this as an answer ! I missed this comment the first time I came here :( – sashok_bg Jun 06 '16 at 10:28