added: config: base_url_redirect

when true the server checks whether HTTP_HOST environment variable
       is the same as base_url from the config (of course without the 'http://' part
       and the last slash) - if it's not the same then the server
       redirects you into a new location base_url+REQUEST_URI
changed: variables env_* from Request are never null (after Request::Read())
       if the server didn't set such a variable it will be pointing into an empty string "\0"


git-svn-id: svn://ttmath.org/publicrep/cmslu/trunk@465 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2008-12-12 03:11:29 +00:00
parent 3462cdf827
commit 023faa66fc
8 changed files with 109 additions and 26 deletions

View File

@ -68,6 +68,8 @@ bool Config::ReadConfig(bool errors_to_stdout_)
if( status == ConfParser::ok ) if( status == ConfParser::ok )
{ {
AssignValues(); AssignValues();
data.SetAdditionalVariables();
return true; return true;
} }
else else

View File

@ -21,3 +21,27 @@ Data::Data()
void Data::SetAdditionalVariables()
{
SetHttpHost();
}
void Data::SetHttpHost()
{
if( strncmp(base_url.c_str(), "http://", 7) == 0 )
base_url_http_host = base_url.substr(7);
else
if( strncmp(base_url.c_str(), "https://", 8) == 0 )
base_url_http_host = base_url.substr(8);
else
base_url_http_host.clear();
if( base_url_http_host.empty() )
return;
// removing the last slash (if it is present)
if( base_url_http_host[ base_url_http_host.size() - 1 ] == '/' )
base_url_http_host.erase( base_url_http_host.end() - 1 );
}

View File

@ -13,6 +13,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include <string.h>
#include "misc.h" #include "misc.h"
#include "item.h" #include "item.h"
@ -64,6 +65,11 @@ public:
std::string base_url; std::string base_url;
std::string http_session_id_name; std::string http_session_id_name;
// when the HOST_HTTP environment variable doesn't point into 'base_url' (the part 'http://' and the last slash is removed)
// the server will redirect into 'base_url' + 'REQUEST_URI'
// it's useful when you want to redirect from 'mydomain.tld' into 'www.mydomain.tld' etc.
bool base_url_redirect;
// if there is one item in a directory // if there is one item in a directory
// it will be showed // it will be showed
// (instead of showing directory contents) // (instead of showing directory contents)
@ -73,21 +79,29 @@ public:
// end config members // end config members
// ----------------------------------------------------------------- // -----------------------------------------------------------------
// false at the beginning // false at the beginning
bool stdout_is_closed; bool stdout_is_closed;
// true if there was the SIGHUP signal // true if there was SIGHUP signal
volatile bool signal_hup; volatile bool signal_hup;
// contains current directories tree
Dir dir; Dir dir;
// based on base_url
// set by SetAdditionalVariables()
std::string base_url_http_host;
// call this method after the config file is read
void SetAdditionalVariables();
Data(); Data();
private:
void SetHttpHost();
}; };

View File

@ -11,7 +11,7 @@
Request::Request() Request::Request() : char_empty(0)
{ {
Clear(); Clear();
} }
@ -31,9 +31,12 @@ void Request::Clear()
page.str(""); page.str("");
debug.str(""); debug.str("");
env_request_method = 0; env_request_method = &char_empty;
env_request_uri = 0; env_request_uri = &char_empty;
env_http_cookie = 0; env_http_cookie = &char_empty;
env_remote_addr = &char_empty;
env_http_host = &char_empty;
session = 0; session = 0;
@ -176,15 +179,29 @@ int len;
const char * Request::SetEnvVar(const char * var)
{
const char * v = FCGX_GetParam(var, env);
if( v )
return v;
// char_empty contains '\0'
return &char_empty;
}
void Request::ReadEnvVariables() void Request::ReadEnvVariables()
{ {
// we store that values because FCGX_GetParam has O(n) complexity // we store that values because FCGX_GetParam has O(n) complexity
// with this variables (env_*) we have O(1) // with this variables (env_*) we have O(1)
env_request_method = FCGX_GetParam("REQUEST_METHOD", env); env_request_method = SetEnvVar("REQUEST_METHOD");
env_request_uri = FCGX_GetParam("REQUEST_URI", env); env_request_uri = SetEnvVar("REQUEST_URI");
env_http_cookie = FCGX_GetParam("HTTP_COOKIE", env); env_http_cookie = SetEnvVar("HTTP_COOKIE");
env_remote_addr = FCGX_GetParam("REMOTE_ADDR", env); env_remote_addr = SetEnvVar("REMOTE_ADDR");
env_http_host = SetEnvVar("HTTP_HOST");
log << log1 << "IP: " << env_remote_addr << logend; log << log1 << "IP: " << env_remote_addr << logend;
} }
@ -194,9 +211,6 @@ void Request::ReadEnvVariables()
void Request::CheckMethod() void Request::CheckMethod()
{ {
method = none; method = none;
if( !env_request_method )
return;
if( env_request_method[0] == 'G' ) if( env_request_method[0] == 'G' )
method = get; method = get;

View File

@ -41,11 +41,13 @@ struct Request
PostTable post_table; PostTable post_table;
CookieTable cookie_table; CookieTable cookie_table;
// environment variables (can be null) // environment variables
// they are not null -- when the server doesn't have such a variable it will be pointing into 'char_empty' which is default '\0'
const char * env_request_method; const char * env_request_method;
const char * env_request_uri; const char * env_request_uri;
const char * env_http_cookie; const char * env_http_cookie;
const char * env_remote_addr; const char * env_remote_addr;
const char * env_http_host;
// current session // current session
// is set after calling session_manager.SetSession() // is set after calling session_manager.SetSession()
@ -107,6 +109,12 @@ struct Request
void SendAll(); void SendAll();
private:
// used to set some env_* variables into it, when the server didn't set that variable
// it contains '\0'
const char char_empty;
const char * SetEnvVar(const char * var);
}; };

View File

@ -109,6 +109,23 @@ return true;
bool RequestController::BaseUrlRedirect()
{
if( request.env_request_uri[0] == 0 )
return false;
if( data.base_url_http_host == request.env_http_host )
return false;
request.result = Request::redirect;
request.str = data.base_url + (request.env_request_uri + 1); // +1 means skipping the first slash from env_request_uri
return true;
}
void RequestController::Loop() void RequestController::Loop()
{ {
while( FCGX_Accept(&request.in, &request.out, &request.err, &request.env) == 0 ) while( FCGX_Accept(&request.in, &request.out, &request.err, &request.env) == 0 )
@ -119,13 +136,19 @@ void RequestController::Loop()
{ {
request.Clear(); request.Clear();
request.Read(); request.Read();
session_manager.SetSession(); // setting request.session as well // when BaseUrlRedirect() return true we didn't have to set everything in request.Read()
request.session->CheckTimers(); // in the future request.Read() can be split and at the beginning only environment variables will be read
// and then BaseUrlRedirect() will be called (for performance)
content.Make(); if( !BaseUrlRedirect() )
{
session_manager.SetSession(); // setting request.session as well
request.session->CheckTimers();
content.Make();
}
request.SendAll(); request.SendAll();
} }
catch(const std::exception & e) catch(const std::exception & e)
{ {

View File

@ -32,6 +32,7 @@ class RequestController
Content content; Content content;
SessionManager session_manager; SessionManager session_manager;
bool BaseUrlRedirect();
public: public:

View File

@ -109,10 +109,7 @@ void base_url(Info & i)
void current_url(Info & i) void current_url(Info & i)
{ {
if( request.env_request_uri ) i.out << request.env_request_uri;
i.out << request.env_request_uri;
else
base_url(i);
} }