From 1ba63f18297f6cd16d8143bf2392f8577c22ef27 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 8 Aug 2014 18:53:04 +0000 Subject: [PATCH] Added qse_str_amend() almost finished primitive url rewriting --- qse/include/qse/cmn/str.h | 22 +++ qse/lib/cmn/str-dyn.c | 36 ++--- qse/lib/cmn/str-dyn.h | 36 ++++- qse/lib/http/htrd.c | 20 ++- qse/lib/http/http.c | 4 +- qse/lib/http/httpd-proxy.c | 278 +++++++++++++++++++++++++++++-------- qse/lib/http/httpd-std.c | 14 +- qse/lib/http/httpd-task.c | 30 ++-- qse/lib/http/httpd.h | 18 +++ 9 files changed, 350 insertions(+), 108 deletions(-) diff --git a/qse/include/qse/cmn/str.h b/qse/include/qse/cmn/str.h index 2b8240ad..4dab914e 100644 --- a/qse/include/qse/cmn/str.h +++ b/qse/include/qse/cmn/str.h @@ -2747,6 +2747,13 @@ QSE_EXPORT qse_size_t qse_mbs_del ( 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_mbs_t* str ); @@ -2956,6 +2963,19 @@ QSE_EXPORT qse_size_t qse_wcs_del ( 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_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_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_amend(str,index,size,repl) qse_mbs_amend(str,index,size,repl) # define qse_str_trm(str) qse_mbs_trm(str) # define qse_str_pac(str) qse_mbs_pac(str) # 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_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_amend(str,index,size,repl) qse_wcs_amend(str,index,size,repl) # define qse_str_trm(str) qse_wcs_trm(str) # define qse_str_pac(str) qse_wcs_pac(str) # define qse_str_fcat qse_wcs_fcat diff --git a/qse/lib/cmn/str-dyn.c b/qse/lib/cmn/str-dyn.c index cad55a65..602b8012 100644 --- a/qse/lib/cmn/str-dyn.c +++ b/qse/lib/cmn/str-dyn.c @@ -136,6 +136,7 @@ static int mbs_to_wcs ( #undef str_ccat #undef str_nccat #undef str_del +#undef str_amend #undef str_trm #undef str_pac #undef str_fmt @@ -173,22 +174,23 @@ static int mbs_to_wcs ( #define str_getlen qse_mbs_getlen #define str_setlen qse_mbs_setlen #define str_clear qse_mbs_clear -#define str_swap qse_mbs_swap -#define str_cpy qse_mbs_cpy -#define str_ncpy qse_mbs_ncpy -#define str_cat qse_mbs_cat -#define resize_for_ncat resize_for_mbs_ncat -#define str_ncat qse_mbs_ncat -#define str_nrcat qse_mbs_nrcat -#define str_ccat qse_mbs_ccat -#define str_nccat qse_mbs_nccat -#define str_del qse_mbs_del -#define str_trm qse_mbs_trm -#define str_pac qse_mbs_pac -#define str_fmt qse_mbs_fmt -#define str_vfmt qse_mbs_vfmt -#define str_fcat qse_mbs_fcat -#define str_vfcat qse_mbs_vfcat +#define str_swap qse_mbs_swap +#define str_cpy qse_mbs_cpy +#define str_ncpy qse_mbs_ncpy +#define str_cat qse_mbs_cat +#define resize_for_ncat resize_for_mbs_ncat +#define str_ncat qse_mbs_ncat +#define str_nrcat qse_mbs_nrcat +#define str_ccat qse_mbs_ccat +#define str_nccat qse_mbs_nccat +#define str_del qse_mbs_del +#define str_amend qse_mbs_amend +#define str_trm qse_mbs_trm +#define str_pac qse_mbs_pac +#define str_fmt qse_mbs_fmt +#define str_vfmt qse_mbs_vfmt +#define str_fcat qse_mbs_fcat +#define str_vfcat qse_mbs_vfcat #include "str-dyn.h" /* -------------------------------------------------------- */ @@ -233,6 +235,7 @@ static int mbs_to_wcs ( #undef str_ccat #undef str_nccat #undef str_del +#undef str_amend #undef str_trm #undef str_pac #undef str_fmt @@ -280,6 +283,7 @@ static int mbs_to_wcs ( #define str_ccat qse_wcs_ccat #define str_nccat qse_wcs_nccat #define str_del qse_wcs_del +#define str_amend qse_wcs_amend #define str_trm qse_wcs_trm #define str_pac qse_wcs_pac #define str_fmt qse_wcs_fmt diff --git a/qse/lib/cmn/str-dyn.h b/qse/lib/cmn/str-dyn.h index 3dbfa4f2..9a0153d5 100644 --- a/qse/lib/cmn/str-dyn.h +++ b/qse/lib/cmn/str-dyn.h @@ -153,7 +153,7 @@ qse_size_t str_setcapa (str_t* str, qse_size_t capa) str->mmgr, QSE_SIZEOF(char_t)*(capa+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_MEMCPY (tmp, str->val.ptr, @@ -185,7 +185,7 @@ qse_size_t str_setlen (str_t* str, qse_size_t len) if (len < str->val.len) { str->val.len = len; - str->val.ptr[len] = T('\0'); + str->val.ptr[len] = T('\0'); return len; } @@ -203,7 +203,7 @@ qse_size_t str_setlen (str_t* str, qse_size_t len) void str_clear (str_t* str) { str->val.len = 0; - if (str->val.ptr != QSE_NULL) + if (str->val.ptr) { QSE_ASSERT (str->capa >= 1); 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) { - 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; 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; } +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) { - if (str->val.ptr != QSE_NULL) + if (str->val.ptr) { 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) { - if (str->val.ptr != QSE_NULL) + if (str->val.ptr) { str->val.len = strxpac (str->val.ptr, str->val.len); } diff --git a/qse/lib/http/htrd.c b/qse/lib/http/htrd.c index 0efb1762..a10a9faa 100644 --- a/qse/lib/http/htrd.c +++ b/qse/lib/http/htrd.c @@ -194,11 +194,11 @@ static qse_mchar_t* parse_initial_line (qse_htrd_t* htrd, qse_mchar_t* line) #endif /* 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 */ tmp.ptr = p; - do { p++; } while (is_upalpha_octet(*p)); + do { p++; } while (is_alpha_octet(*p)); tmp.len = p - tmp.ptr; 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 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 */ do { p++; } while (is_space_octet(*p)); @@ -1181,7 +1193,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len) htrd->fed.s.crlf = 0; /* reset the raw request length */ htrd->fed.s.plen = 0; - + if (parse_initial_line_and_headers (htrd, req, ptr - req) <= -1) return -1; /* compelete request header is received */ diff --git a/qse/lib/http/http.c b/qse/lib/http/http.c index 32e8f492..e476c1d1 100644 --- a/qse/lib/http/http.c +++ b/qse/lib/http/http.c @@ -150,7 +150,7 @@ qse_http_method_t qse_mbstohttpmethod (const qse_mchar_t* name) int n; struct mtab_t* entry; - mid = (left + right) / 2; + mid = (left + right) / 2; entry = &mtab[mid]; n = qse_mbscmp (name, entry->name); @@ -182,7 +182,7 @@ qse_http_method_t qse_mcstrtohttpmethod (const qse_mcstr_t* name) int n; struct mtab_t* entry; - mid = (left + right) / 2; + mid = (left + right) / 2; entry = &mtab[mid]; n = qse_mbsxcmp (name->ptr, name->len, entry->name); diff --git a/qse/lib/http/httpd-proxy.c b/qse/lib/http/httpd-proxy.c index ba4dafa9..359e833d 100644 --- a/qse/lib/http/httpd-proxy.c +++ b/qse/lib/http/httpd-proxy.c @@ -38,14 +38,19 @@ struct task_proxy_t #define PROXY_INIT_FAILED (1 << 0) #define PROXY_RAW (1 << 1) #define PROXY_TRANSPARENT (1 << 2) -#define PROXY_RESOLVE_PEER_NAME (1 << 3) -#define PROXY_PEER_NAME_RESOLVED (1 << 4) -#define PROXY_PEER_NAME_UNRESOLVED (1 << 5) -#define PROXY_REWRITE_URL (1 << 6) -#define PROXY_URL_REWRITTEN (1 << 7) -#define PROXY_X_FORWARDED_FOR (1 << 8) /* X-Forwarded-For added */ -#define PROXY_VIA (1 << 9) /* Via added to the request */ -#define PROXY_VIA_RETURNING (1 << 10) /* Via added to the response */ +#define PROXY_OUTBAND_PEER_NAME (1 << 3) /* the peer_name pointer points to + a separate memory chunk outside + the task_proxy_t chunk. explicit + deallocatin is required */ +#define PROXY_RESOLVE_PEER_NAME (1 << 4) +#define PROXY_PEER_NAME_RESOLVED (1 << 5) +#define PROXY_PEER_NAME_UNRESOLVED (1 << 6) +#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; qse_httpd_t* httpd; qse_httpd_client_t* client; @@ -54,7 +59,11 @@ struct task_proxy_t qse_http_version_t version; int keepalive; /* taken from the request */ + qse_httpd_task_t* task; 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_htrd_t* peer_htrd; @@ -850,7 +859,7 @@ qse_printf (QSE_T("PROXY FORWARD: @@@@@@@@@@WRITING[%.*hs]\n"), } 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. */ qse_mbs_del (proxy->reqfwdbuf, 0, n); 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 ( 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->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); + proxy->task = task; /* needed for url rewriting */ + proxy->pseudonym = (qse_mchar_t*)(proxy + 1); if (arg->rsrc->pseudonym) { @@ -910,62 +941,59 @@ static int task_init_proxy ( if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_URS) { -#if 0 const qse_mchar_t* qpath; const qse_mchar_t* metnam; - const qse_htre_hdrval_t* hosthv; + const qse_mchar_t* host_ptr; 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 */ - qpath = qse_htre_getqpath(htreq); - method = qse_htre_getqmethodtype(htreq); - metnam = qse_httpmethodtombs(method); - hosthv = qse_htre_getheaderval(htreq, QSE_MT("Host")); - if (hosthv) printf ("hosthv -> %s\n", hosthv->ptr); - qse_nwadtombs (&client->remote_addr, cliaddrbuf, QSE_COUNTOF(cliaddrbuf), QSE_NWADTOMBS_ADDR); -#endif + 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); /* enable url rewriting */ 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; if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_STR) { - qse_mchar_t* colon; - proxy->flags |= PROXY_RESOLVE_PEER_NAME; proxy->peer_name = proxy->pseudonym + len + 1; qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str); - - 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; - } + adjust_peer_name_and_port (proxy); } else { @@ -1009,8 +1037,11 @@ static int task_init_proxy ( * received from the client */ 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_htre_getqpath(arg->req)) == (qse_size_t)-1) goto oops; + qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (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)) { @@ -1068,7 +1099,6 @@ static int task_init_proxy ( (int)proxy->version.major, (int)proxy->version.minor, pseudonym, qse_httpd_getname(httpd)); if (tmp == (qse_size_t)-1) goto oops; - } 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: printf ("init_proxy failed...........................................\n"); + /* since a new task can't be added in the initializer, * i mark that initialization failed and let task_main_proxy() * 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) { 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->reqfwdbuf) qse_mbs_close (proxy->reqfwdbuf); 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; task_proxy_t* proxy = (task_proxy_t*)task->ctx; -/* TODO: HANDLE THIS PROPERLY */ - proxy->flags |= PROXY_INIT_FAILED; -printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN ....\n"); +//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; + } if (qse_httpd_activatetasktrigger (httpd, proxy->client, task) <= -1) { proxy->flags |= PROXY_INIT_FAILED; } + +printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN ....\n"); } static int task_main_proxy ( @@ -1892,6 +2058,8 @@ static int task_main_proxy ( goto oops; } + if (proxy->flags & PROXY_URL_REDIRECTED) return 0; /* URL redirected. task finished */ + if (proxy->flags & PROXY_REWRITE_URL) { /* note that url_to_rewrite is URL + extra information. */ diff --git a/qse/lib/http/httpd-std.c b/qse/lib/http/httpd-std.c index 8e90f980..4de9170a 100644 --- a/qse/lib/http/httpd-std.c +++ b/qse/lib/http/httpd-std.c @@ -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) 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. */ req->attr.flags |= QSE_HTRE_ATTR_PROXIED; return 0; } - /* htrd compacts double slashes to a single slash. - * 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) + if (qse_mbszcasecmp (tmp.qpath, QSE_MT("http://"), 7) == 0) { /* TODO: check if proxying is allowed.... */ qse_mchar_t* host, * slash; - host = tmp.qpath + 6; + host = tmp.qpath + 7; slash = qse_mbschr (host, QSE_MT('/')); if (slash && slash - host > 0) @@ -2702,10 +2703,9 @@ static int make_resource ( /* TODO: refrain from manipulating the request like this */ req->u.q.path = slash; /* TODO: use setqpath or something... */ - /******************************************************************/ /*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. */ diff --git a/qse/lib/http/httpd-task.c b/qse/lib/http/httpd-task.c index c6b62e99..ffee69f9 100644 --- a/qse/lib/http/httpd-task.c +++ b/qse/lib/http/httpd-task.c @@ -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_task_t* pred, int code, void* extra, 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 307: { - status_reloc_t* reloc; - reloc = (status_reloc_t*)extra; + qse_httpd_status_reloc_t* reloc; + reloc = (qse_httpd_status_reloc_t*)extra; extrapre = QSE_MT("Location: "); extrapst = reloc->redir? QSE_MT("/\r\n"): QSE_MT("\r\n"); extraval = reloc->dst; @@ -237,14 +231,14 @@ qse_httpd_task_t* qse_httpd_entask_err ( qse_httpd_task_t* pred, int code, 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_t* httpd, qse_httpd_client_t* client, 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, qse_htre_getqmethodtype(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_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, qse_htre_getqmethodtype(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_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.redir = 0; - return entask_status ( + return qse_httpd_entask_status ( httpd, client, pred, 301, (void*)&reloc, qse_htre_getqmethodtype(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_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.redir = 1; - return entask_status ( + return qse_httpd_entask_status ( httpd, client, pred, 301, (void*)&reloc, qse_htre_getqmethodtype(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_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); } @@ -326,7 +320,7 @@ qse_httpd_task_t* qse_httpd_entasknomod ( qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* pred, qse_htre_t* req) { - return entask_status ( + return qse_httpd_entask_status ( httpd, client, pred, 304, QSE_NULL, qse_htre_getqmethodtype(req), qse_htre_getversion(req), diff --git a/qse/lib/http/httpd.h b/qse/lib/http/httpd.h index 38dda1de..92a3c156 100644 --- a/qse/lib/http/httpd.h +++ b/qse/lib/http/httpd.h @@ -97,6 +97,13 @@ struct qse_httpd_real_task_t 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_RECV_SIZE 4096 @@ -130,6 +137,17 @@ void qse_httpd_fini ( 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_t* httpd, qse_httpd_client_t* client,