<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>LICENSE</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,35 @@
+/* ---------------------------------------------------------------------------
+ * mod_reproxy
+ *
+ * An Apache2 module that implements support for the X-Reproxy-Url header, as
+ * originally implemented in Danga Interactive's &quot;perlbal&quot; load balancer
+ * (http://www.danga.com/perlbal/).
+ *
+ * If reproxying is enabled for a particular request (see the AllowReproxy
+ * configuration setting), mod_reproxy will set X-Proxy-Capabilities to
+ * &quot;reproxy-file&quot;. A backend seeing that may respond with an X-Reproxy-Url
+ * header that contains a space-delimited list of one or more URL's.
+ *
+ * On receiving the response from the backend, mod_reproxy will parse the
+ * X-Reproxy-Url and will sequentially try each provided URL until one is
+ * successful.
+ *
+ * The backend may include the following response headers, which will be
+ * explicitly preserved in the reproxied response:
+ *
+ * - Content-Type
+ *
+ * The latest version of this module will be found here:
+ *
+ *   http://github.com/jamis/mod_reproxy
+ *
+ * ---------------------------------------------------------------------------
+ * This file is distributed under the terms of the MIT license by Jamis Buck,
+ * and is copyright (c) 2009 by the same. See the LICENSE file distributed
+ * with this file for the complete text of the license.
+ * ---------------------------------------------------------------------------
+ */
+
 #include &lt;apr_strings.h&gt;
 #include &lt;httpd.h&gt;
 #include &lt;http_log.h&gt;
@@ -6,25 +38,30 @@
 #include &lt;http_request.h&gt;
 #include &lt;mod_proxy.h&gt;
 
+/* The configuration data for this module */
 typedef struct reproxy_cfg {
-  int enabled;
+  int enabled; /* 0 if reproxying is disabled, non-zero otherwise */
 } reproxy_cfg;
 
+/* Container describing headers that should be copied into the reproxied
+ * response */
 typedef struct header_fixups {
-  char *content_type;
+  char *content_type; /* the content-type from the original response should
+                       * be preserved */
 } header_fixups;
 
+/* Information regarding the current status of the reproxy filter */
 typedef struct reproxy_filter_info {
-  int state;
+  int state; /* either FIRST_CALL, NO_REPROXY, or REPROXIED */
 } reproxy_filter_info;
 
 #define FIRST_CALL 0
 #define NO_REPROXY 1
 #define REPROXIED  2
 
-static const char* reproxy_name  = &quot;reproxy-filter&quot;;
-static const char* unset_filter  = &quot;reproxy-unset-headers-filter&quot;;
-static const char* headers_fixed = &quot;reproxy-headers-fixed&quot;;
+static const char* reproxy_name       = &quot;reproxy-filter&quot;;
+static const char* fix_headers_filter = &quot;reproxy-fix-headers-filter&quot;;
+static const char* headers_fixed      = &quot;reproxy-headers-fixed&quot;;
 
 static const char* reproxy_capabilities_header = &quot;X-Proxy-Capabilities&quot;;
 static const char* reproxy_file_value = &quot;reproxy-file&quot;;
@@ -46,7 +83,7 @@ static apr_status_t  reproxy_request_to(request_rec *r, const char *url);
 static const char*   get_reproxy_url(request_rec *r);
 static int           reproxy_request(request_rec *r, const char *url_list);
 static apr_status_t  reproxy_output_filter(ap_filter_t *f, apr_bucket_brigade *b);
-static apr_status_t  reproxy_unset_headers_filter(ap_filter_t *f, apr_bucket_brigade *b);
+static apr_status_t  reproxy_fix_headers_filter(ap_filter_t *f, apr_bucket_brigade *b);
 static void          reproxy_hooks(apr_pool_t *pool);
 
 module AP_MODULE_DECLARE_DATA reproxy_module = {
@@ -63,6 +100,8 @@ static void*
 reproxy_config_init(apr_pool_t* pool, char *x)
 {
   reproxy_cfg *cfg = apr_pcalloc(pool, sizeof(reproxy_cfg));
+  cfg-&gt;enabled = 0;
+
   return cfg;
 }
 
@@ -94,6 +133,10 @@ reproxy_insert_filter(request_rec *r)
 {
   reproxy_cfg *cfg = ap_get_module_config(r-&gt;per_dir_config, &amp;reproxy_module);
 
+  /* if reproxying is enabled for this request, add the reproxy filter to the
+   * output filters. We set state to FIRST_CALL, so that the output headers
+   * will be parsed (looking for X-Reproxy-Url) the time the filter is invoked. */
+
   if(cfg-&gt;enabled) {
     reproxy_filter_info* info = apr_pcalloc(r-&gt;pool, sizeof(reproxy_filter_info));
     info-&gt;state = FIRST_CALL;
@@ -102,8 +145,15 @@ reproxy_insert_filter(request_rec *r)
   }
 }
 
+/* Creates and initializes a new proxy_worker instance. Much of this is lifted
+ * from different static functions in mod_proxy, so there is definitely some
+ * cargo-culting going on here. I'm not sure, for instance, whether it is
+ * safe (in the long run) to create and initialize workers this way, since
+ * mod_proxy itself seems to assume workers are cached in a worker pool,
+ * rather than created on-demand and discarded when the request finishes. */
 static proxy_worker*
-reproxy_initialize_worker(apr_pool_t *pool, proxy_server_conf *conf, server_rec *server, const char *url)
+reproxy_initialize_worker(apr_pool_t *pool, proxy_server_conf *conf,
+  server_rec *server, const char *url)
 {
   proxy_worker *worker;
   apr_status_t status;
@@ -151,7 +201,6 @@ reproxy_request_to(request_rec *r, const char *url)
   proxy_worker *worker = NULL;
   int status;
 
-  /* should probably do this during module init, so it is only done once */
   mod_proxy = ap_find_linked_module(&quot;mod_proxy.c&quot;);
   if(!mod_proxy) {
     ap_log_rerror(__FILE__, __LINE__, APLOG_ERR, 0, r, &quot;mod_proxy not loaded&quot;);
@@ -197,11 +246,21 @@ reproxy_request(request_rec *r, const char *url_list)
   int handled = 0;
   header_fixups *fixups = apr_pcalloc(r-&gt;pool, sizeof(header_fixups));
 
+  /* remember the original declared content-type of the response, so we
+   * can restore it in the reproxied response */
   fixups-&gt;content_type = apr_pstrdup(r-&gt;pool, r-&gt;content_type);
 
+  /* remove the reproxy capabilities header, so that we don't need
+   * to worry about infinite reproxy loops */
   apr_table_unset(r-&gt;headers_in, reproxy_capabilities_header);
-  ap_add_output_filter(unset_filter, fixups, r, r-&gt;connection);
 
+  /* add the fix headers filter to the output filter list, so that we
+   * can restore the original content_type (and, potentially, other
+   * headers) to the response. */
+  ap_add_output_filter(fix_headers_filter, fixups, r, r-&gt;connection);
+
+  /* parse the url_list, which is a space-delimited list of potential
+   * urls that the response may be reproxied to. */
   while(url = apr_strtok(list, &quot; &quot;, &amp;state)) {
     list = NULL;
     if(reproxy_request_to(r, url) == APR_SUCCESS) {
@@ -223,6 +282,11 @@ static apr_status_t
 reproxy_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
 {
   reproxy_filter_info* info = (reproxy_filter_info*)f-&gt;ctx;
+
+  /* if this is the first time this filter has been called for this response,
+   * look for the reproxy url header and act on it, if it exists. otherwise,
+   * just pass the brigade to the next filter. */
+
   if(info-&gt;state == FIRST_CALL) {
     const char *reproxy_url = get_reproxy_url(f-&gt;r);
 
@@ -238,10 +302,13 @@ reproxy_output_filter(ap_filter_t *f, apr_bucket_brigade *b)
 }
 
 static apr_status_t
-reproxy_unset_headers_filter(ap_filter_t *f, apr_bucket_brigade *b)
+reproxy_fix_headers_filter(ap_filter_t *f, apr_bucket_brigade *b)
 {
   header_fixups *fixups = (header_fixups*)f-&gt;ctx;
 
+  /* if the headers have not yet been fixed for this response, then
+   * put each saved header back into the response */
+
   if(!apr_table_get(f-&gt;r-&gt;notes, headers_fixed)) {
     ap_set_content_type(f-&gt;r, fixups-&gt;content_type);
     apr_table_set(f-&gt;r-&gt;notes, headers_fixed, &quot;yes&quot;);
@@ -254,7 +321,7 @@ static void
 reproxy_hooks(apr_pool_t *pool)
 {
   ap_register_output_filter(reproxy_name, reproxy_output_filter, NULL, AP_FTYPE_RESOURCE);
-  ap_register_output_filter(unset_filter, reproxy_unset_headers_filter, NULL, AP_FTYPE_RESOURCE);
+  ap_register_output_filter(fix_headers_filter, reproxy_fix_headers_filter, NULL, AP_FTYPE_RESOURCE);
   ap_hook_fixups(reproxy_fixups, NULL, NULL, APR_HOOK_LAST);
   ap_hook_insert_filter(reproxy_insert_filter, NULL, NULL, APR_HOOK_LAST);
 }</diff>
      <filename>mod_reproxy.c</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>34cd30123e18aa088e56ffd33faf2e68c8251b9d</id>
    </parent>
  </parents>
  <author>
    <name>Jamis Buck</name>
    <email>jamis@37signals.com</email>
  </author>
  <url>http://github.com/jamis/mod_reproxy/commit/2f4e258777d32939f52bf1a9a074fba3ece27144</url>
  <id>2f4e258777d32939f52bf1a9a074fba3ece27144</id>
  <committed-date>2009-11-06T09:20:01-08:00</committed-date>
  <authored-date>2009-11-06T09:20:01-08:00</authored-date>
  <message>license info, and minimal documentation</message>
  <tree>f076a5214eb390909bb845284eb0f499fb7c79d7</tree>
  <committer>
    <name>Jamis Buck</name>
    <email>jamis@37signals.com</email>
  </committer>
</commit>
