Re: [mod_backhand-devel] mod_proxy

Scott Beck <[email protected]> Tue, 02 Nov 2004 08:50:01 -0800
Newsgroups gmane.comp.apache.mod-backhand.devel
Organization Gossamer Threads
Message-ID <[email protected]>
--=-f4CaSez20BXY6alUgGYy
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

On Tue, 2004-11-02 at 08:32 -0500, Theo Schlossnagle wrote:
> >  
> >
> Patches are always welcome, but I can't guarantee that I can include 
> them right now.
> 
> There shouldn't be a license issue from mod_rewrite.  The copyright 
> statement will need to be preserved from that code of course and the 
> license itself will need to be augmented to reflect the demands of that 
> license.  They are more or less compatible.
> 
> I have some backhand rewrite stuff here in another branch, though it 
> isn't my call to release it.  It does the proxying through EAPI, right?
> 

It just sets up r->filename and sets r->handler to "proxy-server". I'll
go ahead and attach what I have. This is not against CVS mainly because
I can't access your CVS server. It's against the last release.

The main reason for this patch is I needed something like
ProxyPassReverse and I also needed SSI to work for our setup.

NB: Still need to add checks in that mod_proxy is loaded.

Cheers,

Scott

-- 
-------------------- Gossamer Threads Inc. ----------------------
Scott Beck                      Email: [email protected]
Lead Software Developer         Phone: (604) 687-5804
http://www.gossamer-threads.com Fax:   (604) 687-5806


--=-f4CaSez20BXY6alUgGYy
Content-Disposition: attachment; filename=1.2.2-use-mod_proxy.patch
Content-Type: text/x-patch; name=1.2.2-use-mod_proxy.patch; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

diff -Bbur ../mod_backhand-1.2.2.old/mod_backhand.c ./mod_backhand.c
--- ../mod_backhand-1.2.2.old/mod_backhand.c	2002-11-16 18:41:54.000000000 -0800
+++ ./mod_backhand.c	2004-10-27 19:02:08.415177018 -0700
@@ -466,466 +467,6 @@
   return 1;
 }
 
-static ServerSlot makedecision(request_rec *r) {
-  struct cpd *aCPD;
-  mbcfg *cfg;
-  mbcfg *scfg;
-  int j=0, i=0, loglevel;
-  int ncand;
-  ServerSlot candidates[MAXSERVERS];
-  /* Veto forwarding if we are receiving a proxied session! */
-  /* This should technically never happen because we have checked this
-     before we call this function */
-  if(ap_table_get(r->notes, "ProxiedFrom") ||
-     ap_table_get(r->headers_in, "BackhandProxied")) {
-    return invalid_machine;
-  }
-  cfg = our_dconfig(r);
-  scfg = our_sconfig(r->server);
-  loglevel = ((cfg)?(cfg->loglevel):0)|((scfg)?(scfg->loglevel):0);
-  for(j=0;j<MAXSERVERS;j++) {
-    if(serverstats[j].hostname[0]) {
-      candidates[i].redirect = MB_HTTP_PROXY;
-      candidates[i].hosttype = MB_HOSTTYPE_NAME;
-      candidates[i++].id=j;
-    }
-  }
-  if((aCPD = cfg->dfunc)==NULL)
-    return invalid_machine;
-  ncand=i;
-  for(;aCPD!=NULL;aCPD=aCPD->next) {
-    /* Send in some candidates and augment it */
-    int oc=ncand;
-    char buffer[MAXSERVERS*4];
-    aCPD->aFunc(r, candidates, &ncand, aCPD->aString);
-    if (loglevel & MBLL_DCSN3) {
-      ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
-		   "Func executed for %s [%s(%s)] (%d -> %d)", 
-		   cfg->loc, aCPD->aName,
-		   aCPD->aString?aCPD->aString:"NULL",
-		   oc, ncand);
-      ap_snprintf(buffer, sizeof buffer, "New server list: [ ");
-      for(oc=0;oc<ncand;oc++)
-        ap_snprintf(buffer+strlen(buffer), sizeof buffer-strlen(buffer),
-		    "%d ", candidates[oc].id);
-      ap_snprintf(buffer+strlen(buffer), sizeof buffer-strlen(buffer), "]");
-      ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL, buffer);
-    }
-  }
-  if(loglevel & MBLL_DCSN3) {
-    ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
-		 "All funcs executed -> %s", 
-		 (ncand>0)?serverstats[candidates[0].id].hostname:"local");
-  }
-  /* Make our important decisions here... */
-  return (ncand>0)?candidates[0]:invalid_machine;
-}
-
-static JMP_BUF passfdbuf;
-
-static void recv_fd_timeout(int sig) {
-  ap_longjmp(passfdbuf, sig);
-}
-
-static int backhand_redirection(request_rec *r) {
-  int rv, clientka;
-  static char buffer[RBUFLEN], *tmp;
-  static char header[20000];
-  const char *nowarn;
-  long tatime;
-  struct timeval start, end;
-  mbcfg *cfg;
-  mbcfg *scfg;
-  int loglevel;
-  int usepool = MBSR_INHERIT;
-
-  if(remote_machine.id>=0) {
-    int mbcs, size, ssize, tsize, remaining, cl, keepalive, ntries, chunked;
-    int clr=-1;
-    BUFF *myconn;
-    table *myconn_headers_rcvd;
-    table *cookies_rcvd;
-    char mbcsp_request[MBCSP_REQ_SIZE], *content=(char *)NULL;
-    struct in_addr tempaddr;
-    int recvfd_failed;
-    int umbilical_consecutive_attempts;
-
-    cfg = our_dconfig(r);
-    scfg = our_sconfig(r->server);
-    loglevel = ((cfg)?(cfg->loglevel):0)|((scfg)?(scfg->loglevel):0);
-
-    if(remote_machine.redirect) {
-      char portstring[6] = "\0";
-      char protocol[6] = "\0";
-      unsigned short port;
-      int n;
-      if(loglevel & MBLL_DCSN3)
-        ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
-		     "HTTP Redirection %s [%d]",
-		     (remote_machine.hosttype)?"by IP":"by name",
-		     remote_machine.id);
-
-      if (ap_is_HTTP_REDIRECT(r->status)) {
-	n = r->status;
-	r->status = HTTP_OK; /* make Apache kernel happy */
-      }
-      else {
-	n = REDIRECT;
-      }
-      /* now do the redirection */
-      port = ntohs(serverstats[remote_machine.id].contact.sin_port);
-      if(port!=80 && port!=443) ap_snprintf(portstring, 6, ":%d", port);
-      if(port==443) strcpy(protocol, "https");
-      else strcpy(protocol, "http");
-      if(remote_machine.hosttype == MB_HOSTTYPE_IP) {
-	ap_snprintf(buffer, RBUFLEN, "%s://%s%s%s", protocol,
-		    inet_ntoa(serverstats[remote_machine.id].contact.sin_addr),
-		    portstring, r->uri);
-      } else {
-      	const char *rhost = ap_table_get(r->notes, "Backhand-Redirect-Host");
-	if(!rhost) rhost=serverstats[remote_machine.id].hostname;
-	ap_snprintf(buffer, RBUFLEN, "%s://%s%s%s", protocol, rhost, portstring,
-		    r->uri);	
-      }
-      if ( r->args != NULL ) { /* If we've get a Query String */
-        ap_snprintf(buffer, RBUFLEN, "%s?%s", buffer, r->args);
-      }
-      ap_table_setn(r->headers_out, "Location", buffer);
-      return n;
-    }
-
-    if(cfg->connectionpools == MBCP_INHERIT) {
-      usepool = scfg->connectionpools;
-    } else {
-      usepool = cfg->connectionpools;
-    }
-    /* If it isn't explicitly off, then we assume it is on */
-    if(usepool != MBCP_OFF) {
-      usepool = MBCP_ON;
-    }
-
-    /* Make our decision */
-    gettimeofday(&start, NULL);
-
-    /* Build our request */
-    tempaddr = r->connection->remote_addr.sin_addr;
-    ap_snprintf(header, sizeof header, "%s" CRLF, r->the_request);
-    clientka = ap_find_token(r->pool,
-			     ap_table_get(r->headers_in, "Connection"),
-			     "Keep-Alive");
-    if(r->proto_num >= HTTP_VERSION(1,1))
-      clientka = 1;
-    ap_table_setn(r->headers_in, "Connection", "Keep-Alive");
-    ap_table_setn(r->headers_in, "BackhandProxied", inet_ntoa(tempaddr));
-    ap_table_do(build_request_headers, header, r->headers_in, NULL);
-    ap_table_unset(r->headers_in, "BackhandProxied");
-    strcat(header, CRLF);
-    
-    /* Get our socket */
-    /* We only try once if we are not using connection pooling */
-    if(usepool == MBCP_OFF)
-      ntries=1;
-    else
-      ntries=10;
-    do {
-      ntries--;
-      if(ntries<0) {
-	if(content) free(content);
-	if(loglevel & MBLL_MBCS4) {
-	  ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		       "mod_backhand: Tried... failed");
-	}
-	goto local_handle;
-      }
-      if(usepool == MBCP_OFF) {
-	mbcs = new_session(serverstats[remote_machine.id].contact.sin_addr.s_addr,
-			   serverstats[remote_machine.id].contact.sin_port);
-      } else {
-	memcpy(mbcsp_request+1,
-	       &serverstats[remote_machine.id].contact.sin_addr,
-	       sizeof(struct in_addr));
-	memcpy(mbcsp_request+1+sizeof(struct in_addr),
-	       &serverstats[remote_machine.id].contact.sin_port,
-	       sizeof(unsigned short));
-	mbcsp_request[0] = MBCSP_GET;
-	/* Apparently this next stanza can hang on BSD?! */
-	recvfd_failed = 1;
-	umbilical_consecutive_attempts = 0;
-	while(recvfd_failed) {
-	  if(write(umbilical, mbcsp_request, MBCSP_REQ_SIZE) != MBCSP_REQ_SIZE) {
-	    if(loglevel & MBLL_MBCS3) {
-	      ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
-			   "mod_backhand: MBCSP error (making request)");
-	    }
-	    goto local_handle;
-	  }
-	  if(ap_setjmp(passfdbuf) == 0) {
-	    recvfd_failed = 1;
-	    umbilical_consecutive_attempts++;
-	    ap_set_callback_and_alarm(recv_fd_timeout, 5);
-	    if((mbcs = recv_fd(umbilical))<0) {
-	      if(loglevel & MBLL_MBCS3) {
-		ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
-			     "mod_backhand: MBCSP error (recv file descriptor)");
-	      }
-	      ap_set_callback_and_alarm(NULL, 0);
-	      goto local_handle;
-	    }
-	    recvfd_failed = 0;
-	  }
-	  ap_set_callback_and_alarm(NULL, 0);
-	  if(recvfd_failed) {
-	    if(umbilical_consecutive_attempts > 1) {
-	      ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-			   "mod_backhand: child %d hung talking to moderator. Die!", getpid());
-	      exit(0);
-	    }
-	    close_umbilical();
-	    establish_umbilical(NULL);
-	  }
-	}
-	if(loglevel & MBLL_MBCS2) {
-	  ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		       "mod_backhand: Received fd(%d).",
-		       mbcs);
-	}
-	/* End fetching file descriptors from moderator */
-      }
-      if(loglevel & MBLL_MBCS1) {
-	ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		     "mod_backhand: Check 1");
-      }
-      myconn = ap_bcreate(r->pool, B_RDWR | B_SOCKET);
-      ap_bpushfd(myconn, mbcs, mbcs);
-      
-      /* Set a failsafe timeout */
-      ap_hard_timeout("backhand proxying ", r);
-
-      /* Submit request our request */
-      if(loglevel & MBLL_MBCS1) {
-	ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		     "mod_backhand: Check 2");
-      }
-      tmp = header;
-      tsize = strlen(header);
-      ssize=0;
-      while((ssize<tsize) &&
-	    (size=ap_bwrite(myconn, tmp+ssize, tsize-ssize))>0)
-	ssize+=size;
-      if(loglevel & MBLL_MBCS1) {
-	ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		     "mod_backhand: Check 3 --\n\n%s", header);
-      }
-      /* Now read content length from request if it is there (for POST etc.)
-	 and send any submission down the pipe to the other server as well */
-      if(clr<0) {
-	nowarn = ap_table_get(r->headers_in, "Content-length");
-	if(nowarn) cl=atoi(nowarn); else cl=-1;
-	if(cl>0) {
-	  if(loglevel & MBLL_MBCS1) {
-	    ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-			 "mod_backhand: Check 4 -- reading %d more bytes", cl);
-	  }
-	  if((content = (char *)malloc(cl+1))==NULL) {
-	    ap_bclose(myconn);
-	    ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-			 "Failed malloc");
-	    goto local_handle;
-	  }
-	  content[cl] = '\0';
-	  remaining=cl;
-	  ssize=0;
-	  tmp=content;
-	  while(remaining>0 && (size=ap_bread(r->connection->client, tmp,
-					      remaining))>0) {
-	    tmp+=size;
-	    remaining-=size;
-	  }
-	}
-	clr=1;
-      }
-      if(cl>0 && clr>=0) {
-	tmp = content;
-	tsize=cl;
-	ssize=0;
-	if(loglevel & MBLL_MBCS1) {
-	  ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		       "mod_backhand: Check 5 -- writing %d more bytes: [%s]",
-		       cl, content);
-	}
-	while((ssize<tsize) &&
-	      (size=ap_bwrite(myconn, tmp+ssize, tsize-ssize))>0)
-	  ssize+=size;
-      }
-      /* Flush everything and wait for a response from the other server */
-      ap_bflush(myconn);
-      
-      /* Got a connection, let's read the mime headers they are sending
-	 in front of it (we need Content-length and Keepalive info */
-      ap_clear_table(r->headers_out);
-      rv = b_get_mime_headers_out(myconn, r,
-                                  &myconn_headers_rcvd, &cookies_rcvd);
-      if(r->status == 100)
-        rv = b_get_mime_headers_out(myconn, r,
-                                    &myconn_headers_rcvd, &cookies_rcvd);
-      ap_overlap_tables(r->headers_out, myconn_headers_rcvd,
-      			AP_OVERLAP_TABLES_SET);
-      if(!ap_is_empty_table(cookies_rcvd)) {
-        ap_table_unset(r->headers_out, "Set-Cookie");
-        r->headers_out =
-          ap_overlay_tables(r->pool, r->headers_out, cookies_rcvd);
-      }
-      if(rv<0) {
-	ap_bclose(myconn);
-	close(mbcs);
-	mbcs=-1;
-      }
-      if(loglevel & MBLL_MBCS1) {
-	ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		     "mod_backhand: Check 6 -- headers(%d)", rv);
-      }
-    } while(mbcs==-1);
-    /* We have sent it successfully */
-    if(content) free(content);
-    if((nowarn = ap_table_get(r->headers_out, "Content-type")) != NULL) {
-      r->content_type = ap_pstrdup(r->pool, nowarn);
-      ap_table_unset(r->headers_out, "Content-type");
-    }
-    keepalive = ap_find_token(r->pool,
-			      ap_table_get(r->headers_out,
-					   "Connection"), "Keep-Alive");
-    nowarn = ap_table_get(r->headers_out, "Content-length");
-    chunked = ap_find_token(r->pool,
-			      ap_table_get(r->headers_out,
-					   "Transfer-Encoding"), "chunked");
-    if(nowarn) cl=atoi(nowarn); else cl=-1;
-    
-    /* Special cases defined by RFC */
-    if((r->status == 304) || (r->status == 204) || (r->status < 200))
-      cl = 0;
-    
-    if(loglevel & MBLL_MBCS1) {
-      if(cl>0)
-	ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		     "mod_backhand: Check 7 (Content-length: %d) (%s)",
-		     cl, keepalive?"Keep-Alive":"wimpy");
-      else if(chunked)
-	ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		     "mod_backhand: Check 7 (Chunked) (%s)",
-		     keepalive?"Keep-Alive":"wimpy");      
-    }
-    if(clientka) {
-      ap_table_unset(r->headers_out, "Connection");
-      r->connection->keepalive = 1;
-    } else {
-      ap_table_setn(r->headers_out, "Connection", "close");
-    }
-    
-    ap_send_http_header(r);
-    
-    /* Now we read from the other server until done */
-    if(cl>0) {
-      remaining=cl;
-      while(remaining>0 && (size=ap_bread(myconn, buffer,
-					  MIN(RBUFLEN,remaining)))>0) {
-	tsize=size;
-	ssize=0;
-	while((ssize<tsize) && 
-	      (size=ap_rwrite(buffer+ssize, tsize-ssize, r))>0)
-	  ssize+=size;
-	remaining-=tsize;
-      }
-    } else if(chunked) {
-      remaining=0;
-      tsize=0;
-      while((size = get_response_block(myconn, r, &remaining, buffer, RBUFLEN))>0) {
-	tsize=size;
-	ssize=0;
-	while((ssize<tsize) && 
-	      (size=ap_rwrite(buffer+ssize, tsize-ssize, r))>0)
-	  ssize+=size;	
-      }
-      if(size<0) {
-	keepalive = 0;
-      }
-    } else if(cl==-1 && !keepalive) {
-      while((size=ap_bread(myconn, buffer, RBUFLEN))>0) {
-	tsize=size;
-	ssize=0;
-	while((ssize<tsize) && 
-	      (size=ap_rwrite(buffer+ssize, tsize-ssize, r))>0)
-	  ssize+=size;
-	remaining-=tsize;
-      }
-    }
-    if(loglevel & MBLL_MBCS1) {
-      ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		   "mod_backhand: Check 8");
-    }
-    ap_bflush(myconn);
-    if(usepool == MBCP_OFF) {
-    } else {
-      if(keepalive) {
-	/* Give the socket back */
-	mbcsp_request[0] = MBCSP_PUT;
-	if(loglevel & MBLL_MBCS2) {
-	  ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		       "mod_backhand: (%d) Sending back fd(%d).",
-		       getpid(), mbcs);
-	}
-	if(write(umbilical, mbcsp_request, MBCSP_REQ_SIZE) != MBCSP_REQ_SIZE) {
-	  if(loglevel & MBLL_MBCS3) {
-	    ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-			 "mod_backhand: MBCSP error (making request)");
-	  }
-	} else {
-	  if(send_fd(umbilical,mbcs)!=0) {
-	    if(loglevel & MBLL_MBCS3) {
-	      ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-			   "mod_backhand: MBCSP error (send file descriptor)");
-	    }
-	  }
-	}
-      }
-    }
-    ap_kill_timeout(r);
-    ap_bclose(myconn);
-    gettimeofday(&end, NULL);
-    end.tv_sec -= start.tv_sec;
-    start.tv_sec = 0L;
-    end.tv_sec *= 1000L;
-    tatime = (end.tv_sec + end.tv_usec/1000 - start.tv_usec/1000);
-    serverstats[0].tatime = ((serverstats[0].numbacked*serverstats[0].tatime)+
-			     tatime)/(serverstats[0].numbacked+1);
-    serverstats[0].numbacked++;
-    if(serverstats[0].numbacked>1000) serverstats[0].numbacked=10;
-    if(loglevel & MBLL_MBCS2) {
-      ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		   "mod_backhand: Request tally %d [%d]",
-		   serverstats[0].tatime, serverstats[0].numbacked);
-    }
-    return OK;
-  }
- local_handle:
-  ap_kill_timeout(r);
-  if(!ap_table_get((r->main)?r->main->notes:r->notes,
-     "BackhandHandlerExecuted")) {
-    ap_table_setn((r->main)?r->main->notes:r->notes,
-                  "BackhandHandlerExecuted", "Done");
-    ap_internal_redirect(r->uri, r);
-  } else {
-    ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		 "mod_backhand: "
-		 "attempted mod_backhand redirection twice. BUG.");
-    return DECLINED;
-  }
-  if(loglevel & MBLL_MBCS3) {
-    ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, NULL,
-		 "mod_backhand: "
-		 "could not get valid connection -- forced local");
-  }
-  return OK;
-}
 static int backhand_handler(request_rec *r)
 {
   mbcfg *dcfg;
@@ -1329,32 +871,6 @@
 					      r->main->connection->remote_ip);
       }
     }
-  } else {
-      request_rec *subr;
-      mbcfg *tmpcfg;
-      ap_table_setn(r->notes, "BackhandProxyRequest", "YES");
-      subr = ap_sub_req_lookup_uri(r->uri, r);
-      tmpcfg = (mbcfg *)our_dconfig(subr);
-      if(strncmp(subr->uri, "backhand:", 9)==0 &&
-	 tmpcfg->local && tmpcfg->congenital) {
-	const char *rhost = ap_table_get(subr->notes, "Backhand-Redirect-Host");
-	if(rhost) ap_table_set(r->notes, "Backhand-Redirect-Host", rhost);
-        if(r->uri && strncmp(r->uri, "backhand:", 9))
-	  r->uri = ap_pstrcat(r->pool, "backhand:", r->uri, NULL);
-        if(r->filename && strncmp(r->filename, "backhand:", 9))
-	  r->filename = ap_pstrcat(r->pool, "backhand:", r->filename, NULL);
-	r->handler = "backhand-redirection";
-	if(loglevel & MBLL_DCSN1) {
-	  ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
-		       "(Postread =>) = { Backhanding to %d }", 
-		       remote_machine.id);
-	  ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
-		       "(Postread =>) = { %s, %s, %s }", 
-		       r->uri, r->handler, r->content_type);
-	}
-	ap_destroy_sub_req(subr);
-	return OK;
-    }
   }
   if(loglevel & MBLL_DCSN1) {
     ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
@@ -1363,81 +879,163 @@
   return DECLINED;
 }
 
-static int backhand_translate_handler(request_rec *r) {
+static int backhand_fixups_hander(request_rec *r) {
   mbcfg *cfg;
   mbcfg *scfg;
+  const char *bhpr;
   int loglevel;
+  int sredir = MBSR_INHERIT;
+  char buf[512];
+  unsigned int port;
+  struct cpd *aCPD;
+  int j=0, i=0;
+  int ncand;
 
   cfg = our_dconfig(r);
   scfg = our_sconfig(r->server);
   loglevel = ((cfg)?(cfg->loglevel):0)|((scfg)?(scfg->loglevel):0);
 
-  if(loglevel & MBLL_DCSN1) {
-    ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
-		 "(Translate <=) = { %s, %s, %s }", 
-		 r->uri, r->handler, r->content_type);
+  if (!cfg->local || !cfg->congenital)
+    goto declined;
+
+  if(cfg->selfredirect == MBSR_INHERIT) {
+    sredir = scfg->selfredirect;    
+  } else {
+    sredir = cfg->selfredirect;
   }
-  if(strncmp(r->uri, "backhand:", 9)!=0) {
+
+  /* if it's a subrequest we need to unset this because it could have been
+   * set in previous subrequests
+   */
+  if (r->main)
+    ap_table_unset(r->headers_in, "BackhandProxied");
+
     if(loglevel & MBLL_DCSN1) {
       ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
-		   "(Translate =>) = { %s, %s, %s }", 
+        "(Request <=) = { %s, %s, %s }",
 		   r->uri, r->handler, r->content_type);
     }
-    return DECLINED;
-  }
-  memmove(r->uri, &r->uri[9], strlen(&r->uri[9])+1);
-  if(r->filename && strncmp(r->filename, "backhand:", 9)==0)
-    memmove(r->filename, &r->filename[9], strlen(&r->filename[9])+1);
-  return OK;
-}
 
-static int backhand_type_checker(request_rec *r) {
-  mbcfg *cfg;
-  mbcfg *scfg;
-  const char *bhpr;
-  int loglevel;
-  int sredir = MBSR_INHERIT;
+  /* if filename was not initially set,
+   * we start with the requested URI
+   */
+  if (r->filename == NULL)
+    r->filename = ap_pstrdup(r->pool, r->uri);
 
-  cfg = our_dconfig(r);
-  scfg = our_sconfig(r->server);
-  loglevel = ((cfg)?(cfg->loglevel):0)|((scfg)?(scfg->loglevel):0);
-  if(cfg->selfredirect == MBSR_INHERIT) {
-    sredir = scfg->selfredirect;    
-  } else {
-    sredir = cfg->selfredirect;
+  ServerSlot candidates[MAXSERVERS];
+  /* Veto forwarding if we are receiving a proxied session! */
+  /* This should technically never happen because we have checked this
+     before we call this function */
+  if(ap_table_get(r->notes, "ProxiedFrom") ||
+      ap_table_get(r->headers_in, "BackhandProxied"))
+    goto declined;
+  for(j=0;j<MAXSERVERS;j++) {
+    if(serverstats[j].hostname[0]) {
+      candidates[i].redirect = MB_HTTP_PROXY;
+      candidates[i].hosttype = MB_HOSTTYPE_NAME;
+      candidates[i++].id=j;
   }
-  if(loglevel & MBLL_DCSN1) {
+  }
+  if((aCPD = cfg->dfunc)==NULL)
+    goto declined;
+  ncand=i;
+  for(;aCPD!=NULL;aCPD=aCPD->next) {
+    /* Send in some candidates and augment it */
+    int oc=ncand;
+    char buffer[MAXSERVERS*4];
+    aCPD->aFunc(r, candidates, &ncand, aCPD->aString);
+    if (loglevel & MBLL_DCSN3) {
     ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
-		 "(Type <=) = { %s, %s, %s }", 
-		 r->handler, r->uri, r->content_type);
+          "Func executed for %s [%s(%s)] (%d -> %d)", 
+          cfg->loc, aCPD->aName,
+          aCPD->aString?aCPD->aString:"NULL",
+          oc, ncand);
+      ap_snprintf(buffer, sizeof buffer, "New server list: [ ");
+      for(oc=0;oc<ncand;oc++)
+        ap_snprintf(buffer+strlen(buffer), sizeof buffer-strlen(buffer),
+            "%d ", candidates[oc].id);
+      ap_snprintf(buffer+strlen(buffer), sizeof buffer-strlen(buffer), "]");
+      ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL, buffer);
   }
-  /* Reset this to local for last minute remote redirection */
-  if(!ap_is_initial_req(r) && cfg->local && cfg->congenital &&
-     (bhpr = ap_table_get((r->main)?r->main->notes:r->notes,
-			  "BackhandProxyRequest")) &&
-     strncmp(bhpr, "YES", 3)==0) {
-    remote_machine = makedecision(r);
+  }
+  if(loglevel & MBLL_DCSN3) {
+    ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
+        "All funcs executed -> %s", 
+        (ncand>0)?serverstats[candidates[0].id].hostname:"local");
+  }
+  /* Make our important decisions here... */
+  remote_machine = (ncand>0)?candidates[0]:invalid_machine;
+
     if(remote_machine.id>=0 &&
        ((sredir==MBSR_ON) || (remote_machine.id>0))) {
-      r->content_type = "backhand/redirect";
-      if(r->uri && strncmp(r->uri, "backhand:", 9))
-        r->uri = ap_pstrcat(r->pool, "backhand:", r->uri, NULL);
-      if(r->filename && strncmp(r->filename, "backhand:", 9))
-        r->filename = ap_pstrcat(r->pool, "backhand:", r->filename, NULL);
-      r->handler = "backhand-redirection";
+    char portstring[6] = "\0";
+    char protocol[6] = "\0";
+    unsigned short port;
+    char *host;
+    int n;
+
+    port = ntohs(serverstats[remote_machine.id].contact.sin_port);
+    if(port != 80 && port != 443) ap_snprintf(portstring, 6, ":%d", port);
+    if(port == 443) strcpy(protocol, "https");
+    else strcpy(protocol, "http");
+    if(remote_machine.hosttype == MB_HOSTTYPE_IP) {
+      host = inet_ntoa(serverstats[remote_machine.id].contact.sin_addr);
+    }
+    else {
+      host = (char *)ap_table_get(r->notes, "Backhand-Redirect-Host");
+      if(!host) host = serverstats[remote_machine.id].hostname;
     }
+
+
+    r->filename = ap_pstrcat(r->pool, protocol, "://", 
+        host, portstring, r->uri, NULL);
+
+    /* make sure the QUERY_STRING and
+     * PATH_INFO parts get incorporated
+     */
+    if (r->path_info != NULL) {
+      r->filename = ap_pstrcat(r->pool, r->filename,
+          r->path_info, NULL);
+    }
+    if (r->args != NULL &&
+        r->uri == r->unparsed_uri) {
+      /* see proxy_http:proxy_http_canon() */
+      r->filename = ap_pstrcat(r->pool, r->filename,
+          "?", r->args, NULL);
   }
-  if(r->handler && !strcmp(r->handler, "backhand-redirection")) {
+    if(remote_machine.redirect) {
+      if(loglevel & MBLL_DCSN3)
+        ap_log_error(APLOG_MARK, APLOG_ERR, NULL,
+            "HTTP Redirection %s [%d]",
+            (remote_machine.hosttype)?"by IP":"by name",
+            remote_machine.id);
+
+      if (ap_is_HTTP_REDIRECT(r->status)) {
+        n = r->status;
+        r->status = HTTP_OK; /* make Apache kernel happy */
+      }
+      else {
+        n = REDIRECT;
+      }
+      /* now do the redirection */
+      ap_table_setn(r->headers_out, "Location", r->filename);
+      return n;
+    }
+    ap_table_setn(r->headers_in, "BackhandProxied", inet_ntoa(r->connection->remote_addr.sin_addr));
+    r->filename = ap_pstrcat(r->pool, "proxy:", r->filename, NULL);
+    r->proxyreq = PROXY_PASS;
+    r->handler  = "proxy-server";
     if(loglevel & MBLL_DCSN1) {
       ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
-		   "(Type =>) = *{ %s, %s, %s }", 
-		   r->handler, r->uri, r->content_type);
+          "(Proxied =>) = *{ %s, %s, %s }", 
+          r->handler, r->filename, r->content_type);
     }
     return OK;
   }
+declined:
   if(loglevel & MBLL_DCSN1) {
     ap_log_error(APLOG_MARK, APLOG_NOTICE|APLOG_NOERRNO, NULL,
-		 "(Type =>) = { %s, %s, %s }", 
+        "(Declined =>) = { %s, %s, %s }",
 		 r->handler, r->uri, r->content_type);
   }
   return DECLINED;
@@ -1572,7 +1170,6 @@
 static const handler_rec backhand_handlers[] =
 {
   {"backhand-handler", backhand_handler},
-  {"backhand-redirection", backhand_redirection},
   {NULL}
 };
 
@@ -1589,12 +1186,12 @@
   backhand_merge_server_config,  /* server config merger */
   backhand_cmds,                 /* command table */
   backhand_handlers,             /* list of handlers */
-  backhand_translate_handler,    /* [2] filename-to-URI translation */
+  NULL,                          /* [2] filename-to-URI translation */
   NULL,                          /* [5] check/validate user_id */
   NULL,                          /* [6] check user_id is valid */
   NULL,                          /* [4] check access by host address */
-  backhand_type_checker,         /* [7] MIME type checker/setter */
-  NULL,                          /* [8] fixups */
+  NULL,                          /* [7] MIME type checker/setter */
+  backhand_fixups_hander,        /* [8] fixups */
   backhand_conn_addr_reset,      /* [10] logger */
 #if MODULE_MAGIC_NUMBER >= 19970103
   backhand_header_parser,        /* [3] header parser */

--=-f4CaSez20BXY6alUgGYy--