{"id":628,"date":"2013-05-23T16:27:15","date_gmt":"2013-05-23T20:27:15","guid":{"rendered":"https:\/\/risacher.org\/jfdi\/?p=628"},"modified":"2017-02-21T12:15:43","modified_gmt":"2017-02-21T17:15:43","slug":"reverse-proxy-friendly","status":"publish","type":"post","link":"https:\/\/risacher.org\/jfdi\/2013\/05\/reverse-proxy-friendly\/","title":{"rendered":"&#8216;Reverse-Proxy Friendly&#8217;"},"content":{"rendered":"<p><strong><em>tl;dr<\/em><\/strong>: Web apps should work behind reverse-proxy servers out of the box.\u00a0 Use relative URLs.<\/p>\n<hr \/>\n<p>As a digression from my usual policy-wonk fare, I&#8217;d like to take a short moment to coin a term: &#8220;reverse-proxy friendly&#8221;.\u00a0 This is a property of web-applications such that they can be used behind a reverse-proxy server without the need for the proxy server to re-write URLs in HTML.\u00a0 (And without the for the operator of said application to modify anything about the app.)\u00a0 The main thing that a web app needs to do (in order to be reverse-proxy friendly) is to use relative URLs, but sometimes there are other changes as well, such as changes to Javascript that computes AJAX or WebSocket endpoints.<\/p>\n<p>Here&#8217;s my issue:\u00a0 <!--more-->I run both personal and public web sites, each of which has multiple web applications unified into a single namespace.\u00a0 Often these applications use completely different technology stacks.\u00a0 For example, on risacher.org, I&#8217;m running <a href=\"http:\/\/wordpress.org\/\">WordPress<\/a> &amp; <a href=\"http:\/\/galleryproject.org\/\">Gallery<\/a> (mod_php), occasionally <a href=\"http:\/\/antony.lesuisse.org\/software\/ajaxterm\/\">Ajaxterm<\/a> (python stand-alone server), <a href=\"http:\/\/etherpad.org\/\">Etherpad<\/a> and <a href=\"https:\/\/github.com\/chjj\/tty.js\/\">tty.js<\/a> (Node.js), a file-uploader app (<a href=\"http:\/\/perl.apache.org\/\">mod_perl<\/a>), and static &amp; CGI content through <a href=\"http:\/\/httpd.apache.org\/\">Apache httpd<\/a>. I unify all these apps into a single namespace through the use of a reverse proxy server.\u00a0 For years, I did this with <a href=\"https:\/\/github.com\/perlbal\/Perlbal\">perlbal<\/a>, but I now I use a 50-line custom proxy based on <a href=\"https:\/\/github.com\/nodejitsu\/node-http-proxy\">node-http-proxy<\/a>.\u00a0 (Other common solutions are <a href=\"http:\/\/nginx.org\/\">nginx<\/a>, <a href=\"https:\/\/www.varnish-cache.org\/\">Varnish<\/a>, <a href=\"http:\/\/httpd.apache.org\/docs\/2.2\/mod\/mod_proxy.html\">mod_proxy<\/a>, <a href=\"http:\/\/www.squid-cache.org\/\">Squid<\/a>, or <a href=\"http:\/\/www.apsis.ch\/pound\/\">Pound<\/a>.) (UPDATE: my reverse proxy server code is now at\u00a0<a title=\"https:\/\/github.com\/risacher\/yxorp-edon\" href=\"https:\/\/github.com\/risacher\/yxorp-edon\">https:\/\/github.com\/risacher\/yxorp-edon<\/a>)<\/p>\n<p>For any of my applications, I generally want to map this application&#8217;s URL namespace into the overall namespace of the server.\u00a0 So, for example, even though tty.js normally serves files from &#8216;\/&#8217;, my instance is at &#8220;<code>https:\/\/risacher.org\/<span style=\"text-decoration: underline;\">term\/<\/span><\/code>&#8220;.\u00a0 Applications that only use relative paths for URLs do this easily. \u00a0 Both Etherpad and tty.js use <a href=\"http:\/\/socket.io\/\">Socket.IO<\/a>, to manage AJAX connections, and Etherpad computes the right socket.io endpoint URL automagically.\u00a0 Alas, tty.js isn&#8217;t quite so smart, and requires a 1-line change to support a remapped socket.io endpoint and 7 URLs need fixing in &#8220;static\/index.html&#8221;.\u00a0 As a node.js guy, this was pretty easy to do.\u00a0 (I will submit a <a title=\"pull request\" href=\"https:\/\/github.com\/chjj\/tty.js\/pull\/88\">pull request to tty.js <\/a>soon.)<\/p>\n<p>Recently I tried to stand up a <a href=\"http:\/\/www.wavemaker.com\/\">WaveMaker<\/a> (java\/tomcat) instance (on my <a href=\"http:\/\/www.amazon.com\/ec2\/\">EC2<\/a> server) to evaluate its suitability for a project at work.\u00a0 WaveMaker abjectly fails to be reverse-proxy friendly.\u00a0 I can&#8217;t unify WaveMaker with my existing web applications (it&#8217;s not reverse-proxy friendly), and I cannot access the non-standard port directly (employer&#8217;s firewalls do not permit it) and I cannot install WaveMaker at the office (employer&#8217;s policies do not permit me to install unapproved software).\u00a0\u00a0 If I knew I really wanted WaveMaker, I might hack the code to make it reverse-proxy friendly.\u00a0 Alas, I don&#8217;t know yet if it&#8217;s worth using, and I dislike using Java, so it&#8217;s hard to get up the motivation to move forward.<\/p>\n<p>It should be noted that there are proxy servers that will re-write an applications HTML code to fix the absolute link problems (q.v. <a href=\"http:\/\/httpd.apache.org\/docs\/2.4\/mod\/mod_proxy_html.html\">mod_proxy_html<\/a>), but they are not general-purpose solutions because they will not address URLs generated in Javascript, which is an important issue for modern web applications.<\/p>\n<p>A better (but less expedient) solution is for web applications to support reverse-proxy out-of-the-box.\u00a0 Alas, it was difficult to articulate this requirement until right <strong>now<\/strong>, because the term &#8220;reverse-proxy friendly&#8221; hadn&#8217;t been defined.\u00a0 Now that I&#8217;ve coined this term, you should bother authors of web-applications to implement this &#8220;feature&#8221;.<\/p>\n<p>Go!\u00a0 Go now!\u00a0 Commence bothering!<\/p>\n<p>(p.s. start with WaveMaker)<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>tl;dr: Web apps should work behind reverse-proxy servers out of the box.\u00a0 Use relative URLs. As a digression from my usual policy-wonk fare, I&#8217;d like to take a short moment to coin a term: &#8220;reverse-proxy friendly&#8221;.\u00a0 This is a property of web-applications such that they can be used behind a reverse-proxy server without the need [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-628","post","type-post","status-publish","format-standard","hentry","category-it"],"_links":{"self":[{"href":"https:\/\/risacher.org\/jfdi\/wp-json\/wp\/v2\/posts\/628","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/risacher.org\/jfdi\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/risacher.org\/jfdi\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/risacher.org\/jfdi\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/risacher.org\/jfdi\/wp-json\/wp\/v2\/comments?post=628"}],"version-history":[{"count":26,"href":"https:\/\/risacher.org\/jfdi\/wp-json\/wp\/v2\/posts\/628\/revisions"}],"predecessor-version":[{"id":1552,"href":"https:\/\/risacher.org\/jfdi\/wp-json\/wp\/v2\/posts\/628\/revisions\/1552"}],"wp:attachment":[{"href":"https:\/\/risacher.org\/jfdi\/wp-json\/wp\/v2\/media?parent=628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/risacher.org\/jfdi\/wp-json\/wp\/v2\/categories?post=628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/risacher.org\/jfdi\/wp-json\/wp\/v2\/tags?post=628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}