crossroads

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

dispatch.cc (3433B)


      1 #include "httpdispatcher"
      2 
      3 void HttpDispatcher::dispatch() {
      4     PROFILE("HttpDispatcher::dispatch");
      5 
      6     unsigned stickytarget;
      7     string host_header = "";
      8     string url = "";
      9 
     10     // Try to dispatch. Since we're in HTTP mode, we must return an
     11     // error page when dispatching fails.
     12     try {
     13 
     14 	// Get the client's request. May need for cookie inspection or for the
     15 	// host header.
     16 	while (!buf().headersreceived()) {
     17 	    // cout << "BUFFER fetching headers: " << buf().as_string() << '\n';
     18 	    if (! buf().netread(clientfd(), config.client_read_timeout())) {
     19 		msg("Didn't receive a valid client request, stopping");
     20 		throw Error("No HTTP request received");
     21 	    }
     22 	}
     23 	msg("Received client request: '" + buf().firstline() + "'\n");
     24 	// cout << "BUFFER with headers: " << buf().as_string() << '\n';
     25 
     26 	// See if hostmatching or urlmatching is used.
     27 	// This is true when hosts or urls are matched against non-dot.
     28 	bool hostmatchused = false;
     29 	bool urlmatchused = false;
     30 	for (unsigned i = 0; i < balancer.nbackends(); i++) {
     31 	    if (balancer.backend(i).hostmatch() != ".") 
     32 		hostmatchused = true;
     33 	    if (balancer.backend(i).urlmatch() != ".")
     34 		urlmatchused = true;
     35 	}
     36 	
     37 	// Build new target list if host- or url matching applies.
     38 	if (hostmatchused || urlmatchused) {
     39 	    msg("Creating matched target list for the HTTP dispatcher\n");
     40 	    
     41 	    if (hostmatchused)
     42 		host_header = buf().headerval("Host");
     43 	    if (urlmatchused)
     44 		url = buf().url();
     45 	    
     46 	    BackendVector v;
     47 	    v.isdefined(true);
     48 	    
     49 	    for (unsigned i = 0; i < balancer.nbackends(); i++) {
     50 		if (! balancer.backend(i).available())
     51 		    continue;
     52 		bool host_allowed = true, url_allowed = true;
     53 		if (hostmatchused &&
     54 		    regexec(&(balancer.backend(i).hostregex()),
     55 			    host_header.c_str(), 0, 0, 0)) {
     56 		    debugmsg("Back end " +
     57 			     balancer.backend(i).description() +
     58 			     " forbidden due to hostmatch\n");		    
     59 		    host_allowed = false;
     60 		}
     61 		if (urlmatchused &&
     62 		    regexec(&(balancer.backend(i).urlregex()),
     63 			    url.c_str(), 0, 0, 0)) {
     64 		    debugmsg("Back end " +
     65 			     balancer.backend(i).description() +
     66 			     " forbidden due to urlmatch\n");		    
     67 		    url_allowed = false;
     68 		}
     69 		if (host_allowed && url_allowed) {
     70 		    v.add(i);
     71 		    msg("Candidate target: " +
     72 			balancer.backend(i).description() + "\n");
     73 		}
     74 	    }
     75 	    targetlist(v);
     76 	}
     77 	
     78 	// Dispatch as a normal backend if sticky HTTP is off, or if the
     79 	// sticky target is badly specified.
     80 	if (!config.stickyhttp() ||
     81 	    (sscanf(buf().cookievalue("XRTarget").c_str(),
     82 		    "%d", &stickytarget) < 1 &&
     83 	     sscanf(buf().paramvalue("XRTarget").c_str(),
     84 		    "%d", &stickytarget) < 1) ||
     85 	    stickytarget >= balancer.nbackends()) {
     86 	    issticky(false);
     87 	    TcpDispatcher::dispatch();
     88 	} else {
     89 	    // Got a sticky target. Try to connect. If that fails, fallback
     90 	    // to non-sticky dispatching.
     91 	    targetbackend(stickytarget);
     92 	    Backend tb = balancer.backend(stickytarget);
     93 	    tb.live(true);
     94 	    msg("Sticky HTTP request for " + tb.description() + "\n");
     95 	    if (! tb.connect()) {
     96 		balancer.backend(stickytarget).live(false);
     97 		msg("Failed to connect to back end " + tb.description() +
     98 		    ", trying to dispatch to other\n");
     99 		issticky(false);
    100 		TcpDispatcher::dispatch();
    101 	    } else {
    102 		backendfd(tb.sock());
    103 		issticky(true);
    104 	    }
    105 	}
    106  
    107 
    108     } catch (Error const &e) {
    109 	senderrorpage(e.what());
    110 	throw e;
    111     }
    112 }
    113