added urs.prerewrite()

This commit is contained in:
hyung-hwan 2014-09-01 17:37:08 +00:00
parent 46f13c54b3
commit fc20cb22ea
6 changed files with 200 additions and 85 deletions

View File

@ -195,7 +195,7 @@ struct loccfg_t
int dns_retries; int dns_retries;
int urs_timeout; int urs_timeout;
int urs_retries; int urs_retries;
const qse_mchar_t pseudonym[128]; /* TODO: good size? */ qse_mchar_t pseudonym[128]; /* TODO: good size? */
} proxy; } proxy;
loccfg_t* next; loccfg_t* next;
@ -224,6 +224,7 @@ struct server_xtn_t
qse_httpd_serverstd_freersrc_t orgfreersrc; qse_httpd_serverstd_freersrc_t orgfreersrc;
qse_httpd_serverstd_query_t orgquery; qse_httpd_serverstd_query_t orgquery;
qse_htb_t* cfgtab; qse_htb_t* cfgtab;
}; };
@ -234,9 +235,10 @@ struct httpd_xtn_t
{ {
const qse_char_t* cfgfile; const qse_char_t* cfgfile;
qse_xli_t* xli; qse_xli_t* xli;
qse_httpd_impede_t orgimpede; qse_httpd_impede_t org_impede;
int impede_code; int impede_code;
qse_httpd_urs_prerewrite_t org_urs_prerewrite;
loccfg_t dflcfg; loccfg_t dflcfg;
}; };
@ -538,6 +540,10 @@ static int get_server_root (
if (loccfg->proxy.pseudonym[0]) if (loccfg->proxy.pseudonym[0])
root->u.proxy.pseudonym = loccfg->proxy.pseudonym; root->u.proxy.pseudonym = loccfg->proxy.pseudonym;
/* move the host name part backward by 1 byte to make a room for
* terminating null. An orginal input of http://www.yahoo.com/ab/cd
* becomes http:/www.yahoo.com\0ab/cd. host gets to point to the
* www.yahoo.com. qpath(qinfo->req.u.q.path) is updated to ab/cd. */
qse_memmove (host - 1, host, slash - host); qse_memmove (host - 1, host, slash - host);
slash[-1] = QSE_MT('\0'); slash[-1] = QSE_MT('\0');
host = host - 1; host = host - 1;
@ -589,7 +595,6 @@ static int get_server_root (
root->u.path.rpl = loccfg->locname.len; root->u.path.rpl = loccfg->locname.len;
return 0; return 0;
proxy_ok: proxy_ok:
if (loccfg->proxy.dns_enabled) if (loccfg->proxy.dns_enabled)
{ {
@ -2125,15 +2130,26 @@ static void impede_httpd (qse_httpd_t* httpd)
} }
/* chain-call the orignal impedence function */ /* chain-call the orignal impedence function */
if (httpd_xtn->orgimpede) httpd_xtn->orgimpede (httpd); if (httpd_xtn->org_impede) httpd_xtn->org_impede (httpd);
} }
static int prerewrite_url (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req, const qse_mchar_t* host, qse_mchar_t** url)
{
httpd_xtn_t* httpd_xtn;
httpd_xtn = qse_httpd_getxtnstd (httpd);
/* TODO: override prerewrite url */
return httpd_xtn->org_urs_prerewrite (httpd, client, req, host, url);
}
static void logact_httpd (qse_httpd_t* httpd, const qse_httpd_act_t* act) static void logact_httpd (qse_httpd_t* httpd, const qse_httpd_act_t* act)
{ {
httpd_xtn_t* httpd_xtn; /*httpd_xtn_t* httpd_xtn;*/
qse_char_t tmp[128], tmp2[128], tmp3[128]; qse_char_t tmp[128], tmp2[128], tmp3[128];
httpd_xtn = qse_httpd_getxtnstd (httpd); /*httpd_xtn = qse_httpd_getxtnstd (httpd);*/
switch (act->code) switch (act->code)
{ {
@ -2302,6 +2318,7 @@ static int httpd_main (int argc, qse_char_t* argv[])
int trait, ret; int trait, ret;
qse_httpd_rcb_t rcb; qse_httpd_rcb_t rcb;
qse_httpd_ecb_t ecb; qse_httpd_ecb_t ecb;
qse_httpd_scb_t scb;
ret = handle_args (argc, argv); ret = handle_args (argc, argv);
if (ret <= -1) return -1; if (ret <= -1) return -1;
@ -2346,8 +2363,13 @@ static int httpd_main (int argc, qse_char_t* argv[])
tmout.nsec = 0; tmout.nsec = 0;
qse_httpd_setopt (httpd, QSE_HTTPD_IDLELIMIT, &tmout); qse_httpd_setopt (httpd, QSE_HTTPD_IDLELIMIT, &tmout);
qse_httpd_getopt (httpd, QSE_HTTPD_SCB, &scb);
httpd_xtn->org_urs_prerewrite = scb.urs.prerewrite;
scb.urs.prerewrite = prerewrite_url;
qse_httpd_setopt (httpd, QSE_HTTPD_SCB, &scb);
qse_httpd_getopt (httpd, QSE_HTTPD_RCB, &rcb); qse_httpd_getopt (httpd, QSE_HTTPD_RCB, &rcb);
httpd_xtn->orgimpede = rcb.impede; httpd_xtn->org_impede = rcb.impede;
rcb.impede = impede_httpd; /* executed when qse_httpd_impede() is called */ rcb.impede = impede_httpd; /* executed when qse_httpd_impede() is called */
if (g_debug) rcb.logact = logact_httpd; /* i don't remember old logging handler */ if (g_debug) rcb.logact = logact_httpd; /* i don't remember old logging handler */
qse_httpd_setopt (httpd, QSE_HTTPD_RCB, &rcb); qse_httpd_setopt (httpd, QSE_HTTPD_RCB, &rcb);

View File

@ -145,11 +145,59 @@ typedef void (*qse_httpd_resol_t) (
typedef void (*qse_httpd_rewrite_t) ( typedef void (*qse_httpd_rewrite_t) (
qse_httpd_t* httpd, qse_httpd_t* httpd,
/* optional original URL. if the original URL is not
* avaialble,it can be set to #QSE_NULL */
const qse_mchar_t* url, const qse_mchar_t* url,
/* rewritten URL */
const qse_mchar_t* new_url, const qse_mchar_t* new_url,
/* content data pointer */
void* ctx void* ctx
); );
typedef int (*qse_httpd_urs_open_t) (
qse_httpd_t* httpd,
qse_httpd_urs_t* urs
);
typedef void (*qse_httpd_urs_close_t) (
qse_httpd_t* httpd,
qse_httpd_urs_t* urs
);
typedef int (*qse_httpd_urs_recv_t) (
qse_httpd_t* httpd,
qse_httpd_urs_t* urs,
qse_ubi_t handle
);
typedef int (*qse_httpd_urs_send_t) (
qse_httpd_t* httpd,
qse_httpd_urs_t* urs,
const qse_mchar_t* url,
qse_httpd_rewrite_t rewrite,
const qse_httpd_natr_t* urs_server,
void* ctx
);
/* on success, url must point to a null-teminated string which
* can be freed with qse_httpd_freemem() when not needed anymore.
* the return value of 0 indicates that the string is the final
* rewriting result and no sending to urs-server is required.
* if the return value is greater than 0, the string sent to the
* urs-server for the actual rewriting. a negative return value
* indicates failure.
*/
typedef int (*qse_httpd_urs_prerewrite_t) (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
qse_htre_t* req,
const qse_mchar_t* host,
qse_mchar_t** url
);
typedef struct qse_httpd_scb_t qse_httpd_scb_t; typedef struct qse_httpd_scb_t qse_httpd_scb_t;
struct qse_httpd_scb_t struct qse_httpd_scb_t
{ {
@ -278,12 +326,11 @@ struct qse_httpd_scb_t
struct struct
{ {
int (*open) (qse_httpd_t* httpd, qse_httpd_urs_t* urs); qse_httpd_urs_open_t open;
void (*close) (qse_httpd_t* httpd, qse_httpd_urs_t* urs); qse_httpd_urs_close_t close;
int (*recv) (qse_httpd_t* httpd, qse_httpd_urs_t* urs, qse_ubi_t handle); qse_httpd_urs_recv_t recv;
int (*send) (qse_httpd_t* httpd, qse_httpd_urs_t* urs, qse_httpd_urs_send_t send;
const qse_mchar_t* url, qse_httpd_rewrite_t rewrite, qse_httpd_urs_prerewrite_t prerewrite;
const qse_httpd_natr_t* urs_server, void* ctx);
} urs; } urs;
}; };
@ -598,7 +645,6 @@ struct qse_httpd_rsrc_proxy_t
{ {
int flags; /* bitwise-ORed of qse_httpd_rsrc_proxy_flag_t enumerators */ int flags; /* bitwise-ORed of qse_httpd_rsrc_proxy_flag_t enumerators */
const qse_mchar_t* host; /* host name part that were in the original request url */
union union
{ {
qse_nwad_t nwad; qse_nwad_t nwad;
@ -606,13 +652,22 @@ struct qse_httpd_rsrc_proxy_t
union union
{ {
qse_nwad_t nwad; qse_nwad_t nwad;
/* turn QSE_HTTPD_RSRC_PROXY_DST_STR on in flags and set the
* destination host name to the str field. if the bit is not set
* nwad field is used. */
const qse_mchar_t* str; const qse_mchar_t* str;
} dst; /* remote destination address to connect to */ } dst; /* remote destination address to connect to */
qse_httpd_natr_t dns_server; qse_httpd_natr_t dns_server;
qse_httpd_natr_t urs_server; qse_httpd_natr_t urs_server;
const qse_mchar_t* pseudonym; /* pseudonym to use in Via: */ /* optional pseudonym to use for Via: */
const qse_mchar_t* pseudonym;
/* optional host name. it's preferred over the Host header in some
* contexts. */
const qse_mchar_t* host;
}; };
typedef struct qse_httpd_rsrc_dir_t qse_httpd_rsrc_dir_t; typedef struct qse_httpd_rsrc_dir_t qse_httpd_rsrc_dir_t;

View File

@ -277,6 +277,9 @@ static void* custom_awk_modopen (qse_awk_t* awk, const qse_awk_mod_spec_t* spec)
#elif defined(__DOS__) #elif defined(__DOS__)
/* the DOS code here is not generic enough. it's for a specific
* dos-extender only. the best is to enable QSE_ENABLE_STATIC_MODULE
* when building for DOS. */
void* h; void* h;
qse_mchar_t* modpath; qse_mchar_t* modpath;
const qse_char_t* tmp[4]; const qse_char_t* tmp[4];

View File

@ -48,11 +48,12 @@ struct task_proxy_t
#define PROXY_PEER_NAME_RESOLVED (1 << 7) #define PROXY_PEER_NAME_RESOLVED (1 << 7)
#define PROXY_PEER_NAME_UNRESOLVED (1 << 8) #define PROXY_PEER_NAME_UNRESOLVED (1 << 8)
#define PROXY_REWRITE_URL (1 << 9) #define PROXY_REWRITE_URL (1 << 9)
#define PROXY_URL_REWRITTEN (1 << 10) #define PROXY_URL_PREREWRITTEN (1 << 10) /* URL has been prerewritten in prerewrite(). */
#define PROXY_URL_REDIRECTED (1 << 11) #define PROXY_URL_REWRITTEN (1 << 11)
#define PROXY_X_FORWARDED_FOR (1 << 12) /* X-Forwarded-For added */ #define PROXY_URL_REDIRECTED (1 << 12)
#define PROXY_VIA (1 << 13) /* Via added to the request */ #define PROXY_X_FORWARDED_FOR (1 << 13) /* X-Forwarded-For added */
#define PROXY_VIA_RETURNING (1 << 14) /* Via added to the response */ #define PROXY_VIA (1 << 14) /* Via added to the request */
#define PROXY_VIA_RETURNING (1 << 15) /* Via added to the response */
int flags; int flags;
qse_httpd_t* httpd; qse_httpd_t* httpd;
qse_httpd_client_t* client; qse_httpd_client_t* client;
@ -84,7 +85,6 @@ struct task_proxy_t
int reqflags; int reqflags;
qse_htre_t* req; /* set to original client request associated with this if necessary */ qse_htre_t* req; /* set to original client request associated with this if necessary */
qse_mbs_t* reqfwdbuf; /* content from the request */ qse_mbs_t* reqfwdbuf; /* content from the request */
const qse_mchar_t* host;
qse_mbs_t* res; qse_mbs_t* res;
qse_size_t res_consumed; qse_size_t res_consumed;
@ -894,12 +894,11 @@ static void adjust_peer_name_and_port (task_proxy_t* proxy)
colon = qse_mbschr (proxy->peer_name, QSE_MT(':')); colon = qse_mbschr (proxy->peer_name, QSE_MT(':'));
if (colon) if (colon)
{ {
qse_mchar_t* endptr;
/* handle a port number after the colon sign */ /* handle a port number after the colon sign */
*colon = QSE_MT('\0'); *colon = QSE_MT('\0');
QSE_MBSTONUM (proxy->peer_port, colon + 1, &endptr, 10); proxy->peer_port = qse_mbstoui (colon + 1, 10);
/* TODO: check if *endptr is QSE_T('\0')? */ /* TODO: check if there is a garbage after the port number.
* check if the port number has overflown */
} }
else else
{ {
@ -948,7 +947,6 @@ static int task_init_proxy (
{ {
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_DNS) if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_DNS)
{ {
/* TODO: get pseudonym from parameter... */
proxy->peer_name = proxy->pseudonym + len + 1; proxy->peer_name = proxy->pseudonym + len + 1;
qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str); qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str);
@ -977,50 +975,18 @@ static int task_init_proxy (
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_URS) if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_URS)
{ {
const qse_mchar_t* qpath; int x = httpd->opt.scb.urs.prerewrite (httpd, client, arg->req, arg->rsrc->host, &proxy->url_to_rewrite);
const qse_mchar_t* metnam; if (x <= -1) goto oops;
const qse_mchar_t* host_ptr = QSE_NULL;
qse_mchar_t cliaddrbuf[128];
qse_size_t total_len;
qpath = qse_htre_getqpath(arg->req);
metnam = qse_httpmethodtombs(proxy->method);
total_len = qse_mbslen(qpath) + qse_mbslen(metnam);
if (arg->rsrc->host)
{
host_ptr = arg->rsrc->host;
total_len += qse_mbslen(host_ptr);
}
else
{
const qse_htre_hdrval_t* hosthv;
hosthv = qse_htre_getheaderval(arg->req, QSE_MT("Host"));
if (hosthv)
{
/* the first host header only */
host_ptr = hosthv->ptr;
total_len += hosthv->len;
}
}
total_len += qse_nwadtombs (&client->remote_addr, cliaddrbuf, QSE_COUNTOF(cliaddrbuf), QSE_NWADTOMBS_ADDR);
total_len += 128; /* extra space */
proxy->url_to_rewrite = qse_httpd_allocmem (httpd, total_len);
if (proxy->url_to_rewrite == QSE_NULL) goto oops;
/* URL client-ip/client-fqdn ident method */
if (proxy->method != QSE_HTTP_CONNECT && host_ptr)
qse_mbsxfmt (proxy->url_to_rewrite, total_len, QSE_MT("http://%s%s %s/- - %s"), host_ptr, qpath, cliaddrbuf, metnam);
else
qse_mbsxfmt (proxy->url_to_rewrite, total_len, QSE_MT("%s %s/- - %s"), qpath, cliaddrbuf, metnam);
printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy->url_to_rewrite); printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy->url_to_rewrite);
/* enable url rewriting */ /* enable url rewriting */
proxy->flags |= PROXY_REWRITE_URL; proxy->flags |= PROXY_REWRITE_URL;
if (x == 0)
{
/* prerewrite() indicates that proxy->url_to_rewrite is the final
* rewriting result and no futher rewriting is required */
proxy->flags |= PROXY_URL_PREREWRITTEN;
}
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_URS_SERVER) if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_URS_SERVER)
{ {
@ -1042,7 +1008,6 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy
proxy->reqfwdbuf = qse_mbs_open (httpd->mmgr, 0, (len < 512? 512: len)); proxy->reqfwdbuf = qse_mbs_open (httpd->mmgr, 0, (len < 512? 512: len));
if (proxy->reqfwdbuf == QSE_NULL) goto nomem_oops; if (proxy->reqfwdbuf == QSE_NULL) goto nomem_oops;
proxy->host = arg->rsrc->host;
if (proxy->flags & PROXY_RAW) if (proxy->flags & PROXY_RAW)
{ {
/* TODO: when connect is attempted, no keep-alive must be hornored. /* TODO: when connect is attempted, no keep-alive must be hornored.
@ -2090,6 +2055,15 @@ static int task_main_proxy (
if (proxy->flags & PROXY_URL_REDIRECTED) return 0; /* URL redirected. task finished */ if (proxy->flags & PROXY_URL_REDIRECTED) return 0; /* URL redirected. task finished */
if (proxy->flags & PROXY_REWRITE_URL) if (proxy->flags & PROXY_REWRITE_URL)
{
if (proxy->flags & PROXY_URL_PREREWRITTEN)
{
/* proxy->url_to_rewrite is the final rewritten URL by prerewrite().
* pass QSE_NULL as the second parameter to on_url_rewritten() to
* indicate that the original URL is not known */
on_url_rewritten (httpd, QSE_NULL, proxy->url_to_rewrite, task);
}
else
{ {
/* note that url_to_rewrite is URL + extra information. */ /* note that url_to_rewrite is URL + extra information. */
if (qse_httpd_rewriteurl (httpd, proxy->url_to_rewrite, on_url_rewritten, if (qse_httpd_rewriteurl (httpd, proxy->url_to_rewrite, on_url_rewritten,
@ -2099,6 +2073,7 @@ static int task_main_proxy (
if ((proxy->flags & PROXY_REWRITE_URL) && if ((proxy->flags & PROXY_REWRITE_URL) &&
qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops; qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops;
}
return 1; return 1;
} }

View File

@ -476,3 +476,55 @@ oops:
return -1; return -1;
} }
static int urs_prerewrite (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req, const qse_mchar_t* host, qse_mchar_t** url)
{
const qse_mchar_t* qpath;
int mtype;
const qse_mchar_t* mname;
const qse_mchar_t* host_ptr = QSE_NULL;
qse_mchar_t cliaddrbuf[128];
qse_size_t total_len;
qse_mchar_t* url_to_rewrite;
qpath = qse_htre_getqpath(req);
mtype = qse_htre_getqmethodtype(req);
mname = qse_htre_getqmethodname(req);
total_len = qse_mbslen(qpath) + qse_mbslen(mname);
if (host)
{
/* use the host name set explicitly by the caller */
host_ptr = host;
total_len += qse_mbslen(host_ptr);
}
else
{
/* find the host name in the http header */
const qse_htre_hdrval_t* hosthv;
hosthv = qse_htre_getheaderval(req, QSE_MT("Host"));
if (hosthv)
{
/* the first host header only */
host_ptr = hosthv->ptr;
total_len += hosthv->len;
}
}
total_len += qse_nwadtombs (&client->remote_addr, cliaddrbuf, QSE_COUNTOF(cliaddrbuf), QSE_NWADTOMBS_ADDR);
total_len += 128; /* extra space */
url_to_rewrite = qse_httpd_allocmem (httpd, total_len);
if (url_to_rewrite == QSE_NULL) return -1;
/* URL client-ip/client-fqdn ident method */
if (mtype != QSE_HTTP_CONNECT && host_ptr)
qse_mbsxfmt (url_to_rewrite, total_len, QSE_MT("http://%s%s %s/- - %s"), host_ptr, qpath, cliaddrbuf, mname);
else
qse_mbsxfmt (url_to_rewrite, total_len, QSE_MT("%s %s/- - %s"), qpath, cliaddrbuf, mname);
*url = url_to_rewrite;
return 1;
}

View File

@ -2317,6 +2317,7 @@ static qse_size_t hash_string (const qse_mchar_t *str)
#include "httpd-std-dns.h" #include "httpd-std-dns.h"
#include "httpd-std-urs.h" #include "httpd-std-urs.h"
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
static qse_httpd_scb_t httpd_system_callbacks = static qse_httpd_scb_t httpd_system_callbacks =
@ -2324,13 +2325,15 @@ static qse_httpd_scb_t httpd_system_callbacks =
/* server */ /* server */
{ server_open, { server_open,
server_close, server_close,
server_accept }, server_accept
},
{ peer_open, { peer_open,
peer_close, peer_close,
peer_connected, peer_connected,
peer_recv, peer_recv,
peer_send }, peer_send
},
/* multiplexer */ /* multiplexer */
{ mux_open, { mux_open,
@ -2369,19 +2372,23 @@ static qse_httpd_scb_t httpd_system_callbacks =
client_send, client_send,
client_sendfile, client_sendfile,
client_accepted, client_accepted,
client_closed }, client_closed
},
/* dns */ /* dns */
{ dns_open, { dns_open,
dns_close, dns_close,
dns_recv, dns_recv,
dns_send }, dns_send
},
/* urs */ /* urs */
{ urs_open, { urs_open,
urs_close, urs_close,
urs_recv, urs_recv,
urs_send } urs_send,
urs_prerewrite
}
}; };
static qse_httpd_rcb_t httpd_request_callbacks = static qse_httpd_rcb_t httpd_request_callbacks =
@ -3282,3 +3289,4 @@ int qse_httpd_loopstd (qse_httpd_t* httpd, const qse_httpd_dnsstd_t* dns, const
/* main loop */ /* main loop */
return qse_httpd_loop (httpd); return qse_httpd_loop (httpd);
} }