Roxen.git / server / base_server / roxen.pike

version» Context lines:

Roxen.git/server/base_server/roxen.pike:1:   // This file is part of Roxen WebServer.   // Copyright © 1996 - 2001, Roxen IS.   //   // The Roxen WebServer main program.   //   // Per Hedbor, Henrik Grubbström, Pontus Hagland, David Hedbor and others.   // ABS and suicide systems contributed freely by Francesco Chemolli    - constant cvs_version="$Id: roxen.pike,v 1.837 2003/09/15 15:14:26 mast Exp $"; + constant cvs_version="$Id: roxen.pike,v 1.838 2003/10/22 13:27:43 grubba Exp $";      //! @appears roxen   //!   //! The Roxen WebServer main program.      // The argument cache. Used by the image cache.   ArgCache argcache;      // Some headerfiles   #define IN_ROXEN
Roxen.git/server/base_server/roxen.pike:1106:   void set_port_options( string key, mapping value )   //! Set the options for the key 'key'.   //! The intepretation of the options is protocol specific.   {    mapping q = query("port_options");    q[ key ] = value;    set( "port_options" , q );    save( );   }    + #ifdef DEBUG_URL2CONF + #define URL2CONF_MSG(X...) report_debug (X) + #else + #define URL2CONF_MSG(X...) + #endif +    Configuration find_configuration_for_url(object url, void|string url_base)   //! Tries to to determine if a request for the given url would end up   //! in this server, and if so returns the corresponding configuration.   {    Configuration c;    string url_with_port = sprintf("%s://%s:%d%s", url->scheme, url->host,    url->port,    (sizeof(url->path)?url->path:"/")); -  +  +  URL2CONF_MSG("URL with port: %s\n", url_with_port); +     foreach( indices(urls), string u )    {    mixed q = urls[u]; -  +  URL2CONF_MSG("Trying %O:%O\n", u, q);    if( glob( u+"*", url_with_port ) )    { -  if( (c = q->port->find_configuration_for_url((string)url_with_port, 0, 1 )) ) +  URL2CONF_MSG("glob match\n"); +  if( q->port && +  (c = q->port->find_configuration_for_url(url_with_port, 0, 1 )) )    { -  +  URL2CONF_MSG("Found config: %O\n", c); + #if 0 +  // FIXME: The following code looks suspect; what's its intention? +  // /grubba 2003-10-22    if (search(u, "*") != -1 ||    search(u, "?") != -1)    {    // Something like "http://*:80/"       // Base url    if (url_base)    {    Standards.URI base = Standards.URI(url_base);    if (url->host == base->host &&    url->port == base->port &&    url->scheme == base->scheme)    break;    }    -  // Confguration location +  // Configuration location    Standards.URI config = Standards.URI(c->get_url());    if (url->host == config->host &&    url->port == config->port &&    url->scheme == config->scheme)    break;    -  +  URL2CONF_MSG("No match:\n" +  " host: %O : %O\n" +  " port: %O : %O\n" +  " scheme: %O : %O\n", +  url->host, config->host, +  url->port, config->port, +  url->scheme, config->scheme); +     // Do not match    c = 0;    }    else -  + #endif /* 0 */    break;    }    }    } -  +  URL2CONF_MSG("Result: %O\n", c);    return c;   }      class InternalRequestID   //! ID for internal requests that are not linked to any real request.   {    inherit RequestID;       this_program set_path( string f )    {
Roxen.git/server/base_server/roxen.pike:1189:    f = "/"+f;    }    }    }    not_query = Roxen.simplify_path( scan_for_query( f ) );    return this_object();    }       this_program set_url( string url )    { -  sscanf( url, "%s://%s/%s", prot, misc->host, string path ); -  prot = upper_case( prot ); +  object uri = Standards.URI(url); +  prot = upper_case(uri->scheme); +  misc->host = uri->host; +  string path = uri->path; +  raw_url = path;    method = "GET"; -  raw = "GET /" + url + " HTTP/1.1\r\n\r\n"; -  raw_url = "/" + path; -  -  Configuration c; -  foreach( indices(urls), string u ) -  { -  mixed q = urls[u]; -  if( glob( u+"*", url ) ) -  if( (c = q->port->find_configuration_for_url(url, this_object(), 1 )) ) -  { -  conf = c; -  port_obj = q->port; -  break; -  } -  } -  -  if(!c) -  { -  // pass 2: Find a configuration with the 'default' flag set. -  foreach( configurations, c ) -  if( c->query( "default_server" ) ) -  { -  conf = c; -  break; -  } -  else -  c = 0; -  } -  -  if(!c) -  { -  // pass 3: No such luck. Let's allow default fallbacks. -  foreach( indices(urls), string u ) -  { -  mixed q = urls[u]; -  if( (c = q->port->find_configuration_for_url( url,this_object(), 1 )) ) -  { -  conf = c; -  port_obj = q->port; -  break; -  } -  } -  } -  +  raw = "GET " + raw_url + " HTTP/1.1\r\n\r\n"; +  conf = find_configuration_for_url(uri);    return set_path( raw_url );    }       static string _sprintf()    {    return sprintf("RequestID(conf=%O; not_query=%O)", conf, not_query );    }       static void create()    {
Roxen.git/server/base_server/roxen.pike:1411:   #define INIT(X) do{ \    mapping _=(X); \    string __=_->path; \    c=_->conf; \    if(__&&id->adjust_for_config_path) \    id->adjust_for_config_path(__); \    if(!c->inited) \    c->enable_all_modules(); \    } while(0)    - #ifdef DEBUG_URL2CONF - #define URL2CONF_MSG(X...) report_debug (X) - #else - #define URL2CONF_MSG(X...) - #endif -  +     Configuration find_configuration_for_url( string url, RequestID id,    int|void no_default )    //! Given a url and requestid, try to locate a suitable configuration    //! (virtual site) for the request.    //! This interface is not at all set in stone, and might change at    //! any time.    {    Configuration c;    if( sizeof( urls ) == 1 && !no_default)    {    if(!mu) mu=urls[sorted_urls[0]];    INIT( mu );    URL2CONF_MSG ("%O %O cached: %O\n", this_object(), url, c);    return c;    } else if (!sizeof(sorted_urls)) {    URL2CONF_MSG("%O %O No active URLS!\n", this_object(), url);    return 0;    }       url = lower_case( url ); -  +  URL2CONF_MSG("sorted_urls: %O\n" +  "url: %O\n", sorted_urls, url);    // The URLs are sorted from longest to shortest, so that short    // urls (such as http://*/) will not match before more complete    // ones (such as http://*.roxen.com/)    foreach( sorted_urls, string in )    {    if( glob( in+"*", url ) )    {    INIT( urls[in] );    URL2CONF_MSG ("%O %O sorted_urls: %O\n", this_object(), url, c);    return c;
Roxen.git/server/base_server/roxen.pike:1852:   #endif    };    }    report_debug("\bDone [%.1fms]\n", (gethrtime()-st)/1000.0 );    return protocols;   }         mapping protocols;    - mapping(string:mapping) open_ports = ([ ]); + // prot:ip:port ==> Protocol. + mapping(string:mapping(string:mapping(int:Protocol))) open_ports = ([ ]); +  + // url:"port" ==> Protocol.   mapping(string:mapping(string:Configuration)) urls = ([]);   array sorted_urls = ({});      array(string) find_ips_for( string what )   {    if( what == "*" || lower_case(what) == "any" ) -  return 0; +  return ({ 0 }); // ANY       if( is_ip( what ) )    return ({ what });       array res = gethostbyname( what ); -  if( !res || !sizeof( res[1] ) ) +  if( res && sizeof( res[1] ) ) +  return Array.uniq(res[1]); +     report_error(LOC_M(46, "Cannot possibly bind to %O, that host is "    "unknown. Substituting with ANY")+"\n", what); -  else -  return Array.uniq(res[1]); +  return 0; // FAIL   }      string normalize_url(string url)   {    if (!sizeof (url - " " - "\t")) return "";       url = lower_case( url );    Standards.URI ui = Standards.URI(url);    ui->fragment = 0;    url = (string)ui;
Roxen.git/server/base_server/roxen.pike:2028:    {    report_error(LOC_M(21, "Cannot register URL %s, "    "cannot find the protocol %s!")+"\n",    url, protocol);    return 0;    }       if( !port )    port = prot->default_port;    -  array(string) required_hosts; +  urls[ url ] = ([ "conf":conf, "path":path, "hostname": host ]); +  urls[ ourl ] = urls[url] + ([]); +  sorted_urls += ({ url });    -  +  array(string)|int(-1..0) required_hosts; +     if (is_ip(host))    required_hosts = ({ host });    else if( is_ip(opts->ip) )    required_hosts = ({ opts->ip });    else    required_hosts = find_ips_for( host );    -  if (!required_hosts) -  required_hosts = ({ 0 }); // ANY +  if (!required_hosts) { +  // FIXME: Used to fallback to ANY. +  // Will this work with glob URLs? +  report_error(LOC_M(23, "Cannot register URL %s!")+"\n", url); +  return 0; +  }       mapping m;    if( !( m = open_ports[ protocol ] ) )    // always add 'ANY' (0) here, as an empty mapping, for speed reasons.    // There is now no need to check for both open_ports[prot][0] and    // open_ports[prot][0][port], we can go directly to the latter    // test.    m = open_ports[ protocol ] = ([ 0:([]) ]);       if( sizeof( required_hosts - ({ 0 }) ) // not ANY    && m[ 0 ][ port ]    && prot->supports_ipless )    // The ANY port is already open for this port, and since this    // protocol supports IP-less virtual hosting, there is no need to    // open yet another port, that would mosts probably only conflict    // with the ANY port anyway. (this is true on most OSes, it works    // on Solaris, but fails on linux)    required_hosts = ({ 0 });    -  urls[ url ] = ([ "conf":conf, "path":path, "hostname": host ]); -  urls[ ourl ] = urls[url] + ([]); -  sorted_urls += ({ url }); -  +     int failures;       foreach(required_hosts, string required_host)    {    if( m[ required_host ] && m[ required_host ][ port ] )    {    m[required_host][port]->ref(url, urls[url]);       urls[url]->port = m[required_host][port];    urls[ourl]->port = m[required_host][port];
Roxen.git/server/base_server/roxen.pike:2118:    failures++;    }    if (failures == sizeof(required_hosts))    {    report_error(LOC_M(23, "Cannot register URL %s!")+"\n", url);    return 0;    }    sort_urls();    report_notice(" "+LOC_S(3, "Registered %s for %s")+"\n",    url, conf->query_name() ); -  +     return 1;   }         Configuration find_configuration( string name )   //! Searches for a configuration with a name or fullname like the   //! given string. See also get_configuration().   {    // Optimization, in case the exact name is given...    if( Configuration o = get_configuration( name ) )