crossroads

Git mirror of https://crossroads.e-tunity.com/
git clone git://git.finwo.net/app/crossroads
Log | Files | Refs | LICENSE

handle.cc (3718B)


      1 #include "httpdispatcher"
      2 
      3 void HttpDispatcher::handle() {
      4     PROFILE("HttpDispatcher::handle");
      5 
      6     // The client request was already retrieved before starting the
      7     // dispatcher. We can continue by applying server-directed headers.
      8     if (config.addxrversion())
      9 	buf().setheader ("XR", VER);
     10     if (config.addxforwardedfor())
     11 	buf().addheader ("X-Forwarded-For",
     12 			 inet2string(clientfd().clientaddr().sin_addr));
     13     for (unsigned n = 0; n < config.nserverheaders(); n++)
     14 	buf().setheader (config.serverheader(n));
     15 
     16     // Patch up the Host: header if requested so.
     17     if (config.replacehostheader()) {
     18 	ostringstream o;
     19 	o << balancer.backend(targetbackend()).server()
     20 	  << ":" << balancer.backend(targetbackend()).port();
     21 	buf().replaceheader("Host:", o.str());
     22     }
     23 
     24     // Flush client info received so far to the back end.
     25     debugmsg("Sending client request to back end\n");
     26     buf().netwrite(backendfd(), config.backend_write_timeout());
     27 
     28     // Let's see if we will need to modify the server headers.
     29     bool modify_serverheaders = false;
     30     if (config.addxrversion() ||
     31 	(config.stickyhttp() && !issticky()))
     32 	modify_serverheaders = true;
     33 
     34     // Store the client request. May want to log it later.
     35     string client_request = buf().firstline();
     36 
     37     // Go into copy-thru mode. If required, catch the server headers on
     38     // their first appearance and modify them.
     39     bool backend_response_checked = false;
     40     while (1) {
     41 	Fdset readset (maxtimeout(config.client_read_timeout(),
     42 				  config.backend_read_timeout()));
     43 	readset.add(clientfd());
     44 	readset.add(backendfd());
     45 	readset.wait_r();
     46 
     47 	Socket sock;
     48 	unsigned timeout;
     49 	if (readset.readable(clientfd())) {
     50 	    sock = clientfd();
     51 	    timeout = config.client_read_timeout();
     52 	} else if (readset.readable(backendfd())) {
     53 	    sock = backendfd();
     54 	    timeout = config.backend_read_timeout();
     55 	} else
     56 	    break;
     57 
     58 	buf().reset();
     59 
     60 	if (!buf().netread(sock, timeout))
     61 	    break;
     62 
     63 	if (sock == backendfd() && modify_serverheaders) {
     64 	    debugmsg("Back end response seen, applying modifications\n");
     65 	    modify_serverheaders = false;
     66 	    while (! buf().headersreceived())
     67 		if (!buf().netread (sock, config.backend_read_timeout()))
     68 		    throw Error("Failed to get headers from back end");
     69 	    if (config.addxrversion())
     70 		buf().setheader("XR", VER);
     71 	    if (config.stickyhttp() && !issticky()) {
     72 		ostringstream o;
     73 		o << "XRTarget=" << targetbackend() << "; path=/";
     74 		buf().setheader("Set-Cookie", o.str());
     75 	    }
     76 	}
     77 
     78 	// The back end response may now get flushed to the client.
     79 	// If the response code is 4** or 5**, log it as a warning.
     80 	if (!backend_response_checked &&
     81 	    sock == backendfd() && buf().headersreceived()) {
     82 	    string respcode = buf().stringat(9, 3);
     83 	    if (respcode[0] == '4' || respcode[0] == '5')
     84 		warnmsg("HTTP back end indicates fault: '" <<
     85 			buf().firstline() << "' as response to '" <<
     86 			client_request << "'\n");
     87 	    backend_response_checked = true;
     88 	}
     89 
     90 	// Flush info to the other connected side.
     91 	Socket othersock;
     92 	if (sock == clientfd()) {
     93 	    othersock = backendfd();
     94 	    timeout = config.backend_write_timeout();
     95 	    // Re-patch Host header if requested
     96 	    if (config.replacehostheader()) {
     97 		ostringstream o;
     98 		o << balancer.backend(targetbackend()).server()
     99 		  << ":" << balancer.backend(targetbackend()).port();
    100 		buf().replaceheader("Host:", o.str());
    101 	    }
    102 	} else {
    103 	    othersock = clientfd();
    104 	    timeout = config.client_write_timeout();
    105 	}
    106 
    107 	debugmsg ("Had data on " << sock.fd() <<
    108 		  ", sending to " << othersock.fd() << '\n');
    109 
    110 	buf().netwrite(othersock, timeout);
    111 	if (sock == backendfd())
    112 	    balancer.backend(targetbackend()).addbytes(buf().bufsz());
    113     }
    114 }