Added qse_str_amend()

almost finished primitive url rewriting
This commit is contained in:
hyung-hwan 2014-08-08 18:53:04 +00:00
parent 0bb946c800
commit 1ba63f1829
9 changed files with 350 additions and 108 deletions

View File

@ -2747,6 +2747,13 @@ QSE_EXPORT qse_size_t qse_mbs_del (
qse_size_t size qse_size_t size
); );
QSE_EXPORT qse_size_t qse_mbs_amend (
qse_mbs_t* str,
qse_size_t index,
qse_size_t size,
const qse_mchar_t* repl
);
QSE_EXPORT qse_size_t qse_mbs_trm ( QSE_EXPORT qse_size_t qse_mbs_trm (
qse_mbs_t* str qse_mbs_t* str
); );
@ -2956,6 +2963,19 @@ QSE_EXPORT qse_size_t qse_wcs_del (
qse_size_t size qse_size_t size
); );
/**
* The qse_wcs_amend() function is a versatile string editing function.
* It selects a string segment as long as \a size characters starting from
* the \a index position and changes it to the replacement string \a repl.
* \return (qse_size_t)-1 on failure, string length on success.
*/
QSE_EXPORT qse_size_t qse_wcs_amend (
qse_wcs_t* str,
qse_size_t index,
qse_size_t size,
const qse_wchar_t* repl
);
QSE_EXPORT qse_size_t qse_wcs_trm ( QSE_EXPORT qse_size_t qse_wcs_trm (
qse_wcs_t* str qse_wcs_t* str
); );
@ -3001,6 +3021,7 @@ QSE_EXPORT qse_size_t qse_wcs_fmt (
# define qse_str_ccat(str,c) qse_mbs_ccat(str,c) # define qse_str_ccat(str,c) qse_mbs_ccat(str,c)
# define qse_str_nccat(str,c,len) qse_mbs_nccat(str,c,len) # define qse_str_nccat(str,c,len) qse_mbs_nccat(str,c,len)
# define qse_str_del(str,index,size) qse_mbs_del(str,index,size) # define qse_str_del(str,index,size) qse_mbs_del(str,index,size)
# define qse_str_amend(str,index,size,repl) qse_mbs_amend(str,index,size,repl)
# define qse_str_trm(str) qse_mbs_trm(str) # define qse_str_trm(str) qse_mbs_trm(str)
# define qse_str_pac(str) qse_mbs_pac(str) # define qse_str_pac(str) qse_mbs_pac(str)
# define qse_str_fcat qse_mbs_fcat # define qse_str_fcat qse_mbs_fcat
@ -3032,6 +3053,7 @@ QSE_EXPORT qse_size_t qse_wcs_fmt (
# define qse_str_ccat(str,c) qse_wcs_ccat(str,c) # define qse_str_ccat(str,c) qse_wcs_ccat(str,c)
# define qse_str_nccat(str,c,len) qse_wcs_nccat(str,c,len) # define qse_str_nccat(str,c,len) qse_wcs_nccat(str,c,len)
# define qse_str_del(str,index,size) qse_wcs_del(str,index,size) # define qse_str_del(str,index,size) qse_wcs_del(str,index,size)
# define qse_str_amend(str,index,size,repl) qse_wcs_amend(str,index,size,repl)
# define qse_str_trm(str) qse_wcs_trm(str) # define qse_str_trm(str) qse_wcs_trm(str)
# define qse_str_pac(str) qse_wcs_pac(str) # define qse_str_pac(str) qse_wcs_pac(str)
# define qse_str_fcat qse_wcs_fcat # define qse_str_fcat qse_wcs_fcat

View File

@ -136,6 +136,7 @@ static int mbs_to_wcs (
#undef str_ccat #undef str_ccat
#undef str_nccat #undef str_nccat
#undef str_del #undef str_del
#undef str_amend
#undef str_trm #undef str_trm
#undef str_pac #undef str_pac
#undef str_fmt #undef str_fmt
@ -183,6 +184,7 @@ static int mbs_to_wcs (
#define str_ccat qse_mbs_ccat #define str_ccat qse_mbs_ccat
#define str_nccat qse_mbs_nccat #define str_nccat qse_mbs_nccat
#define str_del qse_mbs_del #define str_del qse_mbs_del
#define str_amend qse_mbs_amend
#define str_trm qse_mbs_trm #define str_trm qse_mbs_trm
#define str_pac qse_mbs_pac #define str_pac qse_mbs_pac
#define str_fmt qse_mbs_fmt #define str_fmt qse_mbs_fmt
@ -233,6 +235,7 @@ static int mbs_to_wcs (
#undef str_ccat #undef str_ccat
#undef str_nccat #undef str_nccat
#undef str_del #undef str_del
#undef str_amend
#undef str_trm #undef str_trm
#undef str_pac #undef str_pac
#undef str_fmt #undef str_fmt
@ -280,6 +283,7 @@ static int mbs_to_wcs (
#define str_ccat qse_wcs_ccat #define str_ccat qse_wcs_ccat
#define str_nccat qse_wcs_nccat #define str_nccat qse_wcs_nccat
#define str_del qse_wcs_del #define str_del qse_wcs_del
#define str_amend qse_wcs_amend
#define str_trm qse_wcs_trm #define str_trm qse_wcs_trm
#define str_pac qse_wcs_pac #define str_pac qse_wcs_pac
#define str_fmt qse_wcs_fmt #define str_fmt qse_wcs_fmt

View File

@ -153,7 +153,7 @@ qse_size_t str_setcapa (str_t* str, qse_size_t capa)
str->mmgr, QSE_SIZEOF(char_t)*(capa+1)); str->mmgr, QSE_SIZEOF(char_t)*(capa+1));
if (tmp == QSE_NULL) return (qse_size_t)-1; if (tmp == QSE_NULL) return (qse_size_t)-1;
if (str->val.ptr != QSE_NULL) if (str->val.ptr)
{ {
qse_size_t ncopy = (str->val.len <= capa)? str->val.len: capa; qse_size_t ncopy = (str->val.len <= capa)? str->val.len: capa;
QSE_MEMCPY (tmp, str->val.ptr, QSE_MEMCPY (tmp, str->val.ptr,
@ -203,7 +203,7 @@ qse_size_t str_setlen (str_t* str, qse_size_t len)
void str_clear (str_t* str) void str_clear (str_t* str)
{ {
str->val.len = 0; str->val.len = 0;
if (str->val.ptr != QSE_NULL) if (str->val.ptr)
{ {
QSE_ASSERT (str->capa >= 1); QSE_ASSERT (str->capa >= 1);
str->val.ptr[0] = T('\0'); str->val.ptr[0] = T('\0');
@ -385,7 +385,7 @@ qse_size_t str_nccat (str_t* str, char_t c, qse_size_t len)
qse_size_t str_del (str_t* str, qse_size_t index, qse_size_t size) qse_size_t str_del (str_t* str, qse_size_t index, qse_size_t size)
{ {
if (str->val.ptr != QSE_NULL && index < str->val.len && size > 0) if (str->val.ptr && index < str->val.len && size > 0)
{ {
qse_size_t nidx = index + size; qse_size_t nidx = index + size;
if (nidx >= str->val.len) if (nidx >= str->val.len)
@ -405,9 +405,33 @@ qse_size_t str_del (str_t* str, qse_size_t index, qse_size_t size)
return str->val.len; return str->val.len;
} }
qse_size_t str_amend (str_t* str, qse_size_t pos, qse_size_t len, const char_t* repl)
{
qse_size_t max_len;
qse_size_t repl_len = strlen(repl);
if (pos >= str->val.len) pos = str->val.len;
max_len = str->val.len - pos;
if (len > max_len) len = max_len;
if (len > repl_len)
{
str_del (str, pos, len - repl_len);
}
else if (len < repl_len)
{
qse_size_t old_str_len = str->val.len;
if (str_setlen (str, str->val.len + repl_len - len) == (qse_size_t)-1) return (qse_size_t)-1;
QSE_MEMMOVE (&str->val.ptr[pos + repl_len], &str->val.ptr[pos + len], QSE_SIZEOF(*repl) * (old_str_len - (pos + len)));
}
if (repl_len > 0) QSE_MEMMOVE (&str->val.ptr[pos], repl, QSE_SIZEOF(*repl) * repl_len);
return str->val.len;
}
qse_size_t str_trm (str_t* str) qse_size_t str_trm (str_t* str)
{ {
if (str->val.ptr != QSE_NULL) if (str->val.ptr)
{ {
str->val.len = strxtrm (str->val.ptr, str->val.len); str->val.len = strxtrm (str->val.ptr, str->val.len);
} }
@ -417,7 +441,7 @@ qse_size_t str_trm (str_t* str)
qse_size_t str_pac (str_t* str) qse_size_t str_pac (str_t* str)
{ {
if (str->val.ptr != QSE_NULL) if (str->val.ptr)
{ {
str->val.len = strxpac (str->val.ptr, str->val.len); str->val.len = strxpac (str->val.ptr, str->val.len);
} }

View File

@ -194,11 +194,11 @@ static qse_mchar_t* parse_initial_line (qse_htrd_t* htrd, qse_mchar_t* line)
#endif #endif
/* the method should start with an alphabet */ /* the method should start with an alphabet */
if (!is_upalpha_octet(*p)) goto badre; if (!is_alpha_octet(*p)) goto badre;
/* get the method name */ /* get the method name */
tmp.ptr = p; tmp.ptr = p;
do { p++; } while (is_upalpha_octet(*p)); do { p++; } while (is_alpha_octet(*p));
tmp.len = p - tmp.ptr; tmp.len = p - tmp.ptr;
htrd->re.type = QSE_HTRE_Q; htrd->re.type = QSE_HTRE_Q;
@ -390,7 +390,19 @@ static qse_mchar_t* parse_initial_line (qse_htrd_t* htrd, qse_mchar_t* line)
#endif #endif
if (htrd->option & QSE_HTRD_CANONQPATH) if (htrd->option & QSE_HTRD_CANONQPATH)
qse_canonmbspath (htrd->re.u.q.path, htrd->re.u.q.path, 0); {
qse_mchar_t* qpath = htrd->re.u.q.path;
/* if the url begins with xxx://,
* skip xxx:/ and canonicalize from the second slash */
while (is_alpha_octet(*qpath)) qpath++;
if (qse_mbszcmp (qpath, QSE_MT("://"), 3) == 0)
qpath = qpath + 2; /* set the position to the second / in :// */
else
qpath = htrd->re.u.q.path;
qse_canonmbspath (qpath, qpath, 0);
}
/* skip spaces after the url part */ /* skip spaces after the url part */
do { p++; } while (is_space_octet(*p)); do { p++; } while (is_space_octet(*p));

View File

@ -38,14 +38,19 @@ struct task_proxy_t
#define PROXY_INIT_FAILED (1 << 0) #define PROXY_INIT_FAILED (1 << 0)
#define PROXY_RAW (1 << 1) #define PROXY_RAW (1 << 1)
#define PROXY_TRANSPARENT (1 << 2) #define PROXY_TRANSPARENT (1 << 2)
#define PROXY_RESOLVE_PEER_NAME (1 << 3) #define PROXY_OUTBAND_PEER_NAME (1 << 3) /* the peer_name pointer points to
#define PROXY_PEER_NAME_RESOLVED (1 << 4) a separate memory chunk outside
#define PROXY_PEER_NAME_UNRESOLVED (1 << 5) the task_proxy_t chunk. explicit
#define PROXY_REWRITE_URL (1 << 6) deallocatin is required */
#define PROXY_URL_REWRITTEN (1 << 7) #define PROXY_RESOLVE_PEER_NAME (1 << 4)
#define PROXY_X_FORWARDED_FOR (1 << 8) /* X-Forwarded-For added */ #define PROXY_PEER_NAME_RESOLVED (1 << 5)
#define PROXY_VIA (1 << 9) /* Via added to the request */ #define PROXY_PEER_NAME_UNRESOLVED (1 << 6)
#define PROXY_VIA_RETURNING (1 << 10) /* Via added to the response */ #define PROXY_REWRITE_URL (1 << 7)
#define PROXY_URL_REWRITTEN (1 << 8)
#define PROXY_URL_REDIRECTED (1 << 9)
#define PROXY_X_FORWARDED_FOR (1 << 10) /* X-Forwarded-For added */
#define PROXY_VIA (1 << 11) /* Via added to the request */
#define PROXY_VIA_RETURNING (1 << 12) /* 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;
@ -54,7 +59,11 @@ struct task_proxy_t
qse_http_version_t version; qse_http_version_t version;
int keepalive; /* taken from the request */ int keepalive; /* taken from the request */
qse_httpd_task_t* task;
qse_mchar_t* url_to_rewrite; qse_mchar_t* url_to_rewrite;
qse_size_t qpath_pos_in_reqfwdbuf;
qse_size_t qpath_len_in_reqfwdbuf;
qse_mchar_t* pseudonym; qse_mchar_t* pseudonym;
qse_htrd_t* peer_htrd; qse_htrd_t* peer_htrd;
@ -850,7 +859,7 @@ qse_printf (QSE_T("PROXY FORWARD: @@@@@@@@@@WRITING[%.*hs]\n"),
} }
else if (n > 0) else if (n > 0)
{ {
/* TODO: improve performance.. instead of copying the remaing part /* TODO: improve performance.. instead of copying the remaining part
to the head all the time.. grow the buffer to a certain limit. */ to the head all the time.. grow the buffer to a certain limit. */
qse_mbs_del (proxy->reqfwdbuf, 0, n); qse_mbs_del (proxy->reqfwdbuf, 0, n);
if (QSE_MBS_LEN(proxy->reqfwdbuf) <= 0) if (QSE_MBS_LEN(proxy->reqfwdbuf) <= 0)
@ -875,6 +884,26 @@ to the head all the time.. grow the buffer to a certain limit. */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
static void adjust_peer_name_and_port (task_proxy_t* proxy)
{
qse_mchar_t* colon;
colon = qse_mbschr (proxy->peer_name, QSE_MT(':'));
if (colon)
{
qse_mchar_t* endptr;
/* handle a port number after the colon sign */
*colon = QSE_MT('\0');
QSE_MBSTONUM (proxy->peer_port, colon + 1, &endptr, 10);
/* TODO: check if *endptr is QSE_T('\0')? */
}
else
{
if (proxy->flags & PROXY_RAW) proxy->peer_port = QSE_HTTPD_DEFAULT_SECURE_PORT;
else proxy->peer_port = QSE_HTTPD_DEFAULT_PORT;
}
}
static int task_init_proxy ( static int task_init_proxy (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
{ {
@ -894,6 +923,8 @@ static int task_init_proxy (
proxy->version = *qse_htre_getversion(arg->req); proxy->version = *qse_htre_getversion(arg->req);
proxy->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); proxy->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
proxy->task = task; /* needed for url rewriting */
proxy->pseudonym = (qse_mchar_t*)(proxy + 1); proxy->pseudonym = (qse_mchar_t*)(proxy + 1);
if (arg->rsrc->pseudonym) if (arg->rsrc->pseudonym)
{ {
@ -910,62 +941,59 @@ static int task_init_proxy (
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_URS) if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_URS)
{ {
#if 0
const qse_mchar_t* qpath; const qse_mchar_t* qpath;
const qse_mchar_t* metnam; const qse_mchar_t* metnam;
const qse_htre_hdrval_t* hosthv; const qse_mchar_t* host_ptr;
qse_mchar_t cliaddrbuf[128]; 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 */ /* URL client-ip/client-fqdn ident method */
qpath = qse_htre_getqpath(htreq); if (proxy->method != QSE_HTTP_CONNECT && host_ptr)
method = qse_htre_getqmethodtype(htreq); qse_mbsxfmt (proxy->url_to_rewrite, total_len, QSE_MT("http://%s%s %s/- - %s"), host_ptr, qpath, cliaddrbuf, metnam);
metnam = qse_httpmethodtombs(method); else
hosthv = qse_htre_getheaderval(htreq, QSE_MT("Host")); qse_mbsxfmt (proxy->url_to_rewrite, total_len, QSE_MT("%s %s/- - %s"), qpath, cliaddrbuf, metnam);
if (hosthv) printf ("hosthv -> %s\n", hosthv->ptr);
qse_nwadtombs (&client->remote_addr, cliaddrbuf, QSE_COUNTOF(cliaddrbuf), QSE_NWADTOMBS_ADDR);
#endif
printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy->url_to_rewrite);
/* enable url rewriting */ /* enable url rewriting */
proxy->flags |= PROXY_REWRITE_URL; proxy->flags |= PROXY_REWRITE_URL;
#if 0
/* TODO: build URL TO REWRITE */
if (method == QSE_HTTP_CONNECT)
url_len = qse_mbsxfmt (QSE_NULL, 0, QSE_MT("%s %s/- - %s"), qpath, cliaddrbuf, metnam);
else if (host)
url_len = qse_mbsxfmt (QSE_NULL, 0, QSE_MT("http://%s%s %s/- - %s"), host, qpath, cliaddrbuf, metnam);
else if (hosthv)
url_len = qse_mbsxfmt (QSE_NULL, 0, QSE_MT("http://%s%s %s/- - %s"), hosthv->ptr, qpath, cliaddrbuf, metnam);
else
url_len = qse_mbsxfmt (QSE_NULL, 0, QSE_MT("%s %s/- - %s"), qpath, cliaddrbuf, metnam);
#endif
} }
proxy->peer.local = arg->rsrc->src.nwad; proxy->peer.local = arg->rsrc->src.nwad;
if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_STR) if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_STR)
{ {
qse_mchar_t* colon;
proxy->flags |= PROXY_RESOLVE_PEER_NAME; proxy->flags |= PROXY_RESOLVE_PEER_NAME;
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);
adjust_peer_name_and_port (proxy);
colon = qse_mbschr (proxy->peer_name, QSE_MT(':'));
if (colon)
{
qse_mchar_t* endptr;
/* handle a port number after the colon sign */
*colon = QSE_MT('\0');
QSE_MBSTONUM (proxy->peer_port, colon + 1, &endptr, 10);
/* TODO: check if *endptr is QSE_T('\0')? */
}
else
{
if (proxy->flags & PROXY_RAW) proxy->peer_port = QSE_HTTPD_DEFAULT_SECURE_PORT;
else proxy->peer_port = QSE_HTTPD_DEFAULT_PORT;
}
} }
else else
{ {
@ -1009,8 +1037,11 @@ static int task_init_proxy (
* received from the client */ * received from the client */
if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqmethodname(arg->req)) == (qse_size_t)-1 || if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqmethodname(arg->req)) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1 || qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1) goto oops;
qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqpath(arg->req)) == (qse_size_t)-1) goto oops;
proxy->qpath_pos_in_reqfwdbuf = QSE_STR_LEN(proxy->reqfwdbuf);
if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqpath(arg->req)) == (qse_size_t)-1) goto oops;
proxy->qpath_len_in_reqfwdbuf = QSE_STR_LEN(proxy->reqfwdbuf) - proxy->qpath_pos_in_reqfwdbuf;
if (qse_htre_getqparam(arg->req)) if (qse_htre_getqparam(arg->req))
{ {
@ -1068,7 +1099,6 @@ static int task_init_proxy (
(int)proxy->version.major, (int)proxy->version.minor, (int)proxy->version.major, (int)proxy->version.minor,
pseudonym, qse_httpd_getname(httpd)); pseudonym, qse_httpd_getname(httpd));
if (tmp == (qse_size_t)-1) goto oops; if (tmp == (qse_size_t)-1) goto oops;
} }
if (arg->req->state & QSE_HTRE_DISCARDED) if (arg->req->state & QSE_HTRE_DISCARDED)
@ -1201,9 +1231,18 @@ qse_printf (QSE_T("GOING TO PROXY [%hs]\n"), QSE_MBS_PTR(proxy->reqfwdbuf));
oops: oops:
printf ("init_proxy failed...........................................\n"); printf ("init_proxy failed...........................................\n");
/* since a new task can't be added in the initializer, /* since a new task can't be added in the initializer,
* i mark that initialization failed and let task_main_proxy() * i mark that initialization failed and let task_main_proxy()
* add an error task */ * add an error task */
if (proxy->url_to_rewrite)
{
qse_httpd_freemem (httpd, proxy->url_to_rewrite);
proxy->url_to_rewrite = QSE_NULL;
proxy->flags &= ~PROXY_REWRITE_URL;
}
if (proxy->reqfwdbuf) if (proxy->reqfwdbuf)
{ {
qse_mbs_close (proxy->reqfwdbuf); qse_mbs_close (proxy->reqfwdbuf);
@ -1231,6 +1270,8 @@ static void task_fini_proxy (
if (proxy->peer_htrd) qse_htrd_close (proxy->peer_htrd); if (proxy->peer_htrd) qse_htrd_close (proxy->peer_htrd);
if (proxy->reqfwdbuf) qse_mbs_close (proxy->reqfwdbuf); if (proxy->reqfwdbuf) qse_mbs_close (proxy->reqfwdbuf);
if (proxy->req) qse_htre_unsetconcb (proxy->req); if (proxy->req) qse_htre_unsetconcb (proxy->req);
if (proxy->url_to_rewrite) qse_httpd_freemem (httpd, proxy->url_to_rewrite);
if (proxy->flags & PROXY_OUTBAND_PEER_NAME) qse_httpd_freemem (httpd, proxy->peer_name);
} }
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
@ -1868,14 +1909,139 @@ static void on_url_rewritten (qse_httpd_t* httpd, const qse_mchar_t* url, const
qse_httpd_task_t* task = (qse_httpd_task_t*)ctx; qse_httpd_task_t* task = (qse_httpd_task_t*)ctx;
task_proxy_t* proxy = (task_proxy_t*)task->ctx; task_proxy_t* proxy = (task_proxy_t*)task->ctx;
/* TODO: HANDLE THIS PROPERLY */ //new_url = "302:http://www.google.com/login.html";
//new_url = "127.0.0.1:443";
new_url = "http://www.google.com/a/b/c";
if (new_url)
{
qse_nwad_t nwad;
proxy->flags &= ~PROXY_REWRITE_URL;
if (new_url[0] == QSE_MT('\0'))
{
/* no change. carry on */
}
else if (qse_mbstonwad (new_url, &nwad) >= 0)
{
/* if a network address is returned, change the peer address only */
/* TODO: prevent proxying to self */
proxy->peer.nwad = nwad;
proxy->flags |= PROXY_URL_REWRITTEN;
proxy->flags &= ~PROXY_RESOLVE_PEER_NAME; /* skip dns */
}
else if (new_url[0] >= QSE_MT('0') && new_url[0] <= QSE_MT('9'))
{
/* redirection */
int redir_code = 0;
qse_httpd_status_reloc_t reloc;
const qse_mchar_t* nuptr = new_url;
do
{
redir_code = redir_code * 10 + (*nuptr - QSE_MT('0'));
nuptr++;
}
while (*nuptr >= QSE_MT('0') && *nuptr <= QSE_MT('9'));
if (*nuptr != QSE_MT(':')) goto fail;
if (redir_code != 301 && redir_code != 302 && redir_code != 307) redir_code = 301;
nuptr++;
reloc.dst = nuptr;
reloc.redir = 0; /* don't want to append extra / */
if (qse_httpd_entask_status (
httpd, proxy->client, proxy->task, redir_code, &reloc,
proxy->method, &proxy->version, proxy->keepalive) == QSE_NULL)
{
goto fail;
}
proxy->flags |= PROXY_URL_REDIRECTED;
}
else
{
if (proxy->flags & PROXY_RAW)
{
qse_mchar_t* tmp;
QSE_ASSERT (QSE_STR_LEN(proxy->reqfwdbuf) == 0);
tmp = qse_mbsdup (new_url, qse_httpd_getmmgr(httpd));
if (tmp == QSE_NULL)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
goto fail;
}
proxy->flags |= PROXY_RESOLVE_PEER_NAME | PROXY_OUTBAND_PEER_NAME;
proxy->peer_name = tmp;
adjust_peer_name_and_port (proxy);
}
else
{
QSE_ASSERT (QSE_STR_LEN(proxy->reqfwdbuf) > 0);
/* TODO: Host rewriting?? */
/* TODO: Host rewriting - to support it, headers must be made available thru request cloning.
* the request may not be valid after task_init_proxy */
if (qse_mbszcasecmp (new_url, QSE_MT("http://"), 7) == 0)
{
const qse_mchar_t* host;
host = new_url + 7;
if (host[0] != QSE_MT('/') && host[0] != QSE_MT('\0'))
{
const qse_mchar_t* slash;
qse_mchar_t* tmp;
slash = qse_mbschr (host, QSE_MT('/'));
if (slash)
{
tmp = qse_mbsxdup (host, slash - host, qse_httpd_getmmgr(httpd));
new_url = slash;
}
else
{
tmp = qse_mbsdup (host, qse_httpd_getmmgr(httpd));
new_url = QSE_MT("/");
}
if (tmp == QSE_NULL)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
goto fail;
}
proxy->flags |= PROXY_RESOLVE_PEER_NAME | PROXY_OUTBAND_PEER_NAME;
proxy->peer_name = tmp;
adjust_peer_name_and_port (proxy);
}
}
if (qse_mbs_amend (proxy->reqfwdbuf, proxy->qpath_pos_in_reqfwdbuf, proxy->qpath_len_in_reqfwdbuf, new_url) == (qse_size_t)-1)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
goto fail;
}
}
proxy->flags |= PROXY_URL_REWRITTEN;
}
}
else
{
fail:
/* url rewriting failed */
proxy->flags |= PROXY_INIT_FAILED; proxy->flags |= PROXY_INIT_FAILED;
printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN ....\n"); }
if (qse_httpd_activatetasktrigger (httpd, proxy->client, task) <= -1) if (qse_httpd_activatetasktrigger (httpd, proxy->client, task) <= -1)
{ {
proxy->flags |= PROXY_INIT_FAILED; proxy->flags |= PROXY_INIT_FAILED;
} }
printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN ....\n");
} }
static int task_main_proxy ( static int task_main_proxy (
@ -1892,6 +2058,8 @@ static int task_main_proxy (
goto oops; goto oops;
} }
if (proxy->flags & PROXY_URL_REDIRECTED) return 0; /* URL redirected. task finished */
if (proxy->flags & PROXY_REWRITE_URL) if (proxy->flags & PROXY_REWRITE_URL)
{ {
/* note that url_to_rewrite is URL + extra information. */ /* note that url_to_rewrite is URL + extra information. */

View File

@ -2656,20 +2656,21 @@ static int make_resource (
if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_PSEUDONYM, &target->u.proxy.pseudonym) <= -1) if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_PSEUDONYM, &target->u.proxy.pseudonym) <= -1)
target->u.proxy.pseudonym = QSE_NULL; target->u.proxy.pseudonym = QSE_NULL;
/******************************************************************/
/*TODO: load this from configuration. reamove this after debugging */
//target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
/******************************************************************/
/* mark that this request is going to be proxied. */ /* mark that this request is going to be proxied. */
req->attr.flags |= QSE_HTRE_ATTR_PROXIED; req->attr.flags |= QSE_HTRE_ATTR_PROXIED;
return 0; return 0;
} }
/* htrd compacts double slashes to a single slash. if (qse_mbszcasecmp (tmp.qpath, QSE_MT("http://"), 7) == 0)
* so inspect if the query path begins with http:/ instead of http:// */
/*if (qse_mbszcasecmp (tmp.qpath, QSE_MT("http://"), 7) == 0)*/
if (qse_mbszcasecmp (tmp.qpath, QSE_MT("http:/"), 6) == 0)
{ {
/* TODO: check if proxying is allowed.... */ /* TODO: check if proxying is allowed.... */
qse_mchar_t* host, * slash; qse_mchar_t* host, * slash;
host = tmp.qpath + 6; host = tmp.qpath + 7;
slash = qse_mbschr (host, QSE_MT('/')); slash = qse_mbschr (host, QSE_MT('/'));
if (slash && slash - host > 0) if (slash && slash - host > 0)
@ -2702,10 +2703,9 @@ static int make_resource (
/* TODO: refrain from manipulating the request like this */ /* TODO: refrain from manipulating the request like this */
req->u.q.path = slash; /* TODO: use setqpath or something... */ req->u.q.path = slash; /* TODO: use setqpath or something... */
/******************************************************************/ /******************************************************************/
/*TODO: load this from configuration. reamove this after debugging */ /*TODO: load this from configuration. reamove this after debugging */
//target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS; target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
/******************************************************************/ /******************************************************************/
/* mark that this request is going to be proxied. */ /* mark that this request is going to be proxied. */

View File

@ -158,14 +158,8 @@ qse_httpd_task_t* qse_httpd_entaskformat (
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
typedef struct status_reloc_t status_reloc_t;
struct status_reloc_t
{
const qse_mchar_t* dst;
int redir;
};
static qse_httpd_task_t* entask_status ( qse_httpd_task_t* qse_httpd_entask_status (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_httpd_task_t* pred, int code, void* extra, qse_httpd_task_t* pred, int code, void* extra,
qse_http_method_t method, const qse_http_version_t* version, qse_http_method_t method, const qse_http_version_t* version,
@ -188,8 +182,8 @@ static qse_httpd_task_t* entask_status (
case 302: case 302:
case 307: case 307:
{ {
status_reloc_t* reloc; qse_httpd_status_reloc_t* reloc;
reloc = (status_reloc_t*)extra; reloc = (qse_httpd_status_reloc_t*)extra;
extrapre = QSE_MT("Location: "); extrapre = QSE_MT("Location: ");
extrapst = reloc->redir? QSE_MT("/\r\n"): QSE_MT("\r\n"); extrapst = reloc->redir? QSE_MT("/\r\n"): QSE_MT("\r\n");
extraval = reloc->dst; extraval = reloc->dst;
@ -237,14 +231,14 @@ qse_httpd_task_t* qse_httpd_entask_err (
qse_httpd_task_t* pred, int code, qse_httpd_task_t* pred, int code,
qse_http_method_t method, const qse_http_version_t* version, int keepalive) qse_http_method_t method, const qse_http_version_t* version, int keepalive)
{ {
return entask_status (httpd, client, pred, code, QSE_NULL, method, version, keepalive); return qse_httpd_entask_status (httpd, client, pred, code, QSE_NULL, method, version, keepalive);
} }
qse_httpd_task_t* qse_httpd_entaskerr ( qse_httpd_task_t* qse_httpd_entaskerr (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_httpd_task_t* pred, int code, qse_htre_t* req) qse_httpd_task_t* pred, int code, qse_htre_t* req)
{ {
return entask_status ( return qse_httpd_entask_status (
httpd, client, pred, code, QSE_NULL, httpd, client, pred, code, QSE_NULL,
qse_htre_getqmethodtype(req), qse_htre_getqmethodtype(req),
qse_htre_getversion(req), qse_htre_getversion(req),
@ -270,7 +264,7 @@ qse_httpd_task_t* qse_httpd_entaskauth (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_httpd_task_t* pred, const qse_mchar_t* realm, qse_htre_t* req) qse_httpd_task_t* pred, const qse_mchar_t* realm, qse_htre_t* req)
{ {
return entask_status ( return qse_httpd_entask_status (
httpd, client, pred, 401, (void*)realm, httpd, client, pred, 401, (void*)realm,
qse_htre_getqmethodtype(req), qse_htre_getqmethodtype(req),
qse_htre_getversion(req), qse_htre_getversion(req),
@ -284,12 +278,12 @@ qse_httpd_task_t* qse_httpd_entaskreloc (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req) qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req)
{ {
status_reloc_t reloc; qse_httpd_status_reloc_t reloc;
reloc.dst = dst; reloc.dst = dst;
reloc.redir = 0; reloc.redir = 0;
return entask_status ( return qse_httpd_entask_status (
httpd, client, pred, 301, (void*)&reloc, httpd, client, pred, 301, (void*)&reloc,
qse_htre_getqmethodtype(req), qse_htre_getqmethodtype(req),
qse_htre_getversion(req), qse_htre_getversion(req),
@ -300,12 +294,12 @@ qse_httpd_task_t* qse_httpd_entaskredir (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req) qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req)
{ {
status_reloc_t reloc; qse_httpd_status_reloc_t reloc;
reloc.dst = dst; reloc.dst = dst;
reloc.redir = 1; reloc.redir = 1;
return entask_status ( return qse_httpd_entask_status (
httpd, client, pred, 301, (void*)&reloc, httpd, client, pred, 301, (void*)&reloc,
qse_htre_getqmethodtype(req), qse_htre_getqmethodtype(req),
qse_htre_getversion(req), qse_htre_getversion(req),
@ -318,7 +312,7 @@ qse_httpd_task_t* qse_httpd_entask_nomod (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* pred, qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* pred,
qse_http_method_t method, const qse_http_version_t* version, int keepalive) qse_http_method_t method, const qse_http_version_t* version, int keepalive)
{ {
return entask_status ( return qse_httpd_entask_status (
httpd, client, pred, 304, QSE_NULL, method, version, keepalive); httpd, client, pred, 304, QSE_NULL, method, version, keepalive);
} }
@ -326,7 +320,7 @@ qse_httpd_task_t* qse_httpd_entasknomod (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_httpd_task_t* pred, qse_htre_t* req) qse_httpd_task_t* pred, qse_htre_t* req)
{ {
return entask_status ( return qse_httpd_entask_status (
httpd, client, pred, 304, QSE_NULL, httpd, client, pred, 304, QSE_NULL,
qse_htre_getqmethodtype(req), qse_htre_getqmethodtype(req),
qse_htre_getversion(req), qse_htre_getversion(req),

View File

@ -97,6 +97,13 @@ struct qse_httpd_real_task_t
qse_httpd_real_task_t* next; qse_httpd_real_task_t* next;
}; };
typedef struct qse_httpd_status_reloc_t qse_httpd_status_reloc_t;
struct qse_httpd_status_reloc_t
{
const qse_mchar_t* dst;
int redir;
};
#define MAX_SEND_SIZE 4096 #define MAX_SEND_SIZE 4096
#define MAX_RECV_SIZE 4096 #define MAX_RECV_SIZE 4096
@ -130,6 +137,17 @@ void qse_httpd_fini (
qse_httpd_t* httpd qse_httpd_t* httpd
); );
qse_httpd_task_t* qse_httpd_entask_status (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
qse_httpd_task_t* pred,
int code,
void* extra,
qse_http_method_t method,
const qse_http_version_t* version,
int keepalive
);
qse_httpd_task_t* qse_httpd_entask_err ( qse_httpd_task_t* qse_httpd_entask_err (
qse_httpd_t* httpd, qse_httpd_t* httpd,
qse_httpd_client_t* client, qse_httpd_client_t* client,