fixed the problem of no percent-encoding of decoded query path in proxying

This commit is contained in:
hyung-hwan 2014-09-17 13:26:21 +00:00
parent 94f015ea98
commit f84b27c1de
12 changed files with 174 additions and 93 deletions

View File

@ -92,16 +92,19 @@ struct qse_htre_t
} s; } s;
} u; } u;
/* special attributes derived from the header */
struct
{
#define QSE_HTRE_ATTR_CHUNKED (1 << 0) #define QSE_HTRE_ATTR_CHUNKED (1 << 0)
#define QSE_HTRE_ATTR_LENGTH (1 << 1) #define QSE_HTRE_ATTR_LENGTH (1 << 1)
#define QSE_HTRE_ATTR_KEEPALIVE (1 << 2) #define QSE_HTRE_ATTR_KEEPALIVE (1 << 2)
#define QSE_HTRE_ATTR_EXPECT (1 << 3) #define QSE_HTRE_ATTR_EXPECT (1 << 3)
#define QSE_HTRE_ATTR_EXPECT100 (1 << 4) #define QSE_HTRE_ATTR_EXPECT100 (1 << 4)
#define QSE_HTRE_ATTR_PROXIED (1 << 5) #define QSE_HTRE_ATTR_PROXIED (1 << 5)
#define QSE_HTRE_QPATH_PERDEC (1 << 6) /* the qpath has been percent-decoded */
int flags; int flags;
/* special attributes derived from the header */
struct
{
qse_size_t content_length; qse_size_t content_length;
const qse_mchar_t* status; /* for cgi */ const qse_mchar_t* status; /* for cgi */
} attr; } attr;
@ -231,6 +234,10 @@ QSE_EXPORT void qse_htre_setconcb (
void* ctx void* ctx
); );
QSE_EXPORT int qse_htre_perdecqpath (
qse_htre_t* req
);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -154,6 +154,13 @@ struct qse_http_range_t
}; };
typedef struct qse_http_range_t qse_http_range_t; typedef struct qse_http_range_t qse_http_range_t;
enum qse_perenchttpstr_opt_t
{
QSE_PERENCHTTPSTR_KEEP_SLASH = (1 << 0)
};
typedef enum qse_perenchttpstr_opt_t qse_perenchttpstr_opt_t;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -195,20 +202,26 @@ QSE_EXPORT qse_mchar_t* qse_fmthttptime (
qse_size_t bufsz qse_size_t bufsz
); );
/* percent-decode a string */ /* percent-decode a string.
* returns the number of affected characters.
* for example, 0 means that no characters in the input required decoding. */
QSE_EXPORT qse_size_t qse_perdechttpstr ( QSE_EXPORT qse_size_t qse_perdechttpstr (
const qse_mchar_t* str, const qse_mchar_t* str,
qse_mchar_t* buf qse_mchar_t* buf
); );
/* percent-encode a string */ /* percent-encode a string.
* returns the number of affected characters.
* for example, 0 means that no characters in the input required encoding. */
QSE_EXPORT qse_size_t qse_perenchttpstr ( QSE_EXPORT qse_size_t qse_perenchttpstr (
int opt, /**< 0 or bitwise-OR'ed of #qse_perenchttpstr_opt_t */
const qse_mchar_t* str, const qse_mchar_t* str,
qse_mchar_t* buf qse_mchar_t* buf
); );
QSE_EXPORT qse_mchar_t* qse_perenchttpstrdup ( QSE_EXPORT qse_mchar_t* qse_perenchttpstrdup (
int opt, /**< 0 or bitwise-OR'ed of #qse_perenchttpstr_opt_t */
const qse_mchar_t* str, const qse_mchar_t* str,
qse_mmgr_t* mmgr qse_mmgr_t* mmgr
); );

View File

@ -444,7 +444,7 @@ static qse_mchar_t* parse_initial_line (qse_htrd_t* htrd, qse_mchar_t* line)
if (htrd->re.version.major > 1 || if (htrd->re.version.major > 1 ||
(htrd->re.version.major == 1 && htrd->re.version.minor >= 1)) (htrd->re.version.major == 1 && htrd->re.version.minor >= 1))
{ {
htrd->re.attr.flags |= QSE_HTRE_ATTR_KEEPALIVE; htrd->re.flags |= QSE_HTRE_ATTR_KEEPALIVE;
} }
return ++p; return ++p;
@ -500,14 +500,14 @@ static int capture_connection (qse_htrd_t* htrd, qse_htb_pair_t* pair)
n = qse_mbscmp (val->ptr, QSE_MT("close")); n = qse_mbscmp (val->ptr, QSE_MT("close"));
if (n == 0) if (n == 0)
{ {
htrd->re.attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE; htrd->re.flags &= ~QSE_HTRE_ATTR_KEEPALIVE;
return 0; return 0;
} }
n = qse_mbscmp (val->ptr, QSE_MT("keep-alive")); n = qse_mbscmp (val->ptr, QSE_MT("keep-alive"));
if (n == 0) if (n == 0)
{ {
htrd->re.attr.flags |= QSE_HTRE_ATTR_KEEPALIVE; htrd->re.flags |= QSE_HTRE_ATTR_KEEPALIVE;
return 0; return 0;
} }
@ -523,7 +523,7 @@ static int capture_connection (qse_htrd_t* htrd, qse_htb_pair_t* pair)
if (htrd->re.version.major < 1 || if (htrd->re.version.major < 1 ||
(htrd->re.version.major == 1 && htrd->re.version.minor <= 0)) (htrd->re.version.major == 1 && htrd->re.version.minor <= 0))
{ {
htrd->re.attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE; htrd->re.flags &= ~QSE_HTRE_ATTR_KEEPALIVE;
} }
return 0; return 0;
} }
@ -568,7 +568,7 @@ static int capture_content_length (qse_htrd_t* htrd, qse_htb_pair_t* pair)
return -1; return -1;
} }
if ((htrd->re.attr.flags & QSE_HTRE_ATTR_CHUNKED) && len > 0) if ((htrd->re.flags & QSE_HTRE_ATTR_CHUNKED) && len > 0)
{ {
/* content-length is greater than 0 /* content-length is greater than 0
* while transfer-encoding: chunked is specified. */ * while transfer-encoding: chunked is specified. */
@ -576,7 +576,7 @@ static int capture_content_length (qse_htrd_t* htrd, qse_htb_pair_t* pair)
return -1; return -1;
} }
htrd->re.attr.flags |= QSE_HTRE_ATTR_LENGTH; htrd->re.flags |= QSE_HTRE_ATTR_LENGTH;
htrd->re.attr.content_length = len; htrd->re.attr.content_length = len;
return 0; return 0;
} }
@ -586,14 +586,14 @@ static int capture_expect (qse_htrd_t* htrd, qse_htb_pair_t* pair)
qse_htre_hdrval_t* val; qse_htre_hdrval_t* val;
/* Expect is included */ /* Expect is included */
htrd->re.attr.flags |= QSE_HTRE_ATTR_EXPECT; htrd->re.flags |= QSE_HTRE_ATTR_EXPECT;
val = QSE_HTB_VPTR(pair); val = QSE_HTB_VPTR(pair);
while (val) while (val)
{ {
/* Expect: 100-continue is included */ /* Expect: 100-continue is included */
if (qse_mbscasecmp (val->ptr, QSE_MT("100-continue")) == 0) if (qse_mbscasecmp (val->ptr, QSE_MT("100-continue")) == 0)
htrd->re.attr.flags |= QSE_HTRE_ATTR_EXPECT100; htrd->re.flags |= QSE_HTRE_ATTR_EXPECT100;
val = val->next; val = val->next;
} }
@ -623,13 +623,13 @@ static int capture_transfer_encoding (qse_htrd_t* htrd, qse_htb_pair_t* pair)
if (n == 0) if (n == 0)
{ {
/* if (htrd->re.attr.content_length > 0) */ /* if (htrd->re.attr.content_length > 0) */
if (htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH) if (htrd->re.flags & QSE_HTRE_ATTR_LENGTH)
{ {
/* both content-length and 'transfer-encoding: chunked' are specified. */ /* both content-length and 'transfer-encoding: chunked' are specified. */
goto badre; goto badre;
} }
htrd->re.attr.flags |= QSE_HTRE_ATTR_CHUNKED; htrd->re.flags |= QSE_HTRE_ATTR_CHUNKED;
return 0; return 0;
} }
@ -1232,10 +1232,10 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
} }
/* carry on processing content body fed together with the header */ /* carry on processing content body fed together with the header */
if (htrd->re.attr.flags & QSE_HTRE_ATTR_CHUNKED) if (htrd->re.flags & QSE_HTRE_ATTR_CHUNKED)
{ {
/* transfer-encoding: chunked */ /* transfer-encoding: chunked */
QSE_ASSERT (!(htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH)); QSE_ASSERT (!(htrd->re.flags & QSE_HTRE_ATTR_LENGTH));
dechunk_start: dechunk_start:
htrd->fed.s.chunk.phase = GET_CHUNK_LEN; htrd->fed.s.chunk.phase = GET_CHUNK_LEN;
@ -1279,8 +1279,8 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
/* we need to read as many octets as /* we need to read as many octets as
* Content-Length */ * Content-Length */
if ((htrd->option & QSE_HTRD_RESPONSE) && if ((htrd->option & QSE_HTRD_RESPONSE) &&
!(htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH) && !(htrd->re.flags & QSE_HTRE_ATTR_LENGTH) &&
!(htrd->re.attr.flags & QSE_HTRE_ATTR_KEEPALIVE)) !(htrd->re.flags & QSE_HTRE_ATTR_KEEPALIVE))
{ {
/* for a response, no content-length and /* for a response, no content-length and
* no chunk are specified and 'connection' * no chunk are specified and 'connection'

View File

@ -264,3 +264,11 @@ void qse_htre_setconcb (qse_htre_t* re, qse_htre_concb_t concb, void* ctx)
re->concb_ctx = ctx; re->concb_ctx = ctx;
} }
int qse_htre_perdecqpath (qse_htre_t* re)
{
/* percent decode the query path */
if (re->type != QSE_HTRE_Q || (re->flags & QSE_HTRE_QPATH_PERDEC)) return -1;
if (qse_perdechttpstr ((re)->u.q.path, (re)->u.q.path) > 0)
re->flags |= QSE_HTRE_QPATH_PERDEC;
return 0;
}

View File

@ -390,6 +390,7 @@ qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf)
{ {
const qse_mchar_t* p = str; const qse_mchar_t* p = str;
qse_mchar_t* out = buf; qse_mchar_t* out = buf;
qse_size_t dec_count = 0;
while (*p != QSE_T('\0')) while (*p != QSE_T('\0'))
{ {
@ -405,31 +406,51 @@ qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf)
* contains a null character */ * contains a null character */
*out++ = ((q << 4) + w); *out++ = ((q << 4) + w);
p += 3; p += 3;
dec_count++;
continue; continue;
} }
} }
} }
*out++ = *p++; *out++ = *p++;
} }
*out = QSE_MT('\0'); *out = QSE_MT('\0');
return out - buf; /*return out - buf;*/
return dec_count;
} }
#define IS_UNRESERVED(c) \ #define IS_UNRESERVED(c) \
(((c) >= QSE_MT('A') && (c) <= QSE_MT('Z')) || \ (((c) >= QSE_MT('A') && (c) <= QSE_MT('Z')) || \
((c) >= QSE_MT('a') && (c) <= QSE_MT('z')) || \ ((c) >= QSE_MT('a') && (c) <= QSE_MT('z')) || \
((c) >= QSE_MT('0') && (c) <= QSE_MT('9')) || \
(c) == QSE_MT('-') || (c) == QSE_T('_') || \ (c) == QSE_MT('-') || (c) == QSE_T('_') || \
(c) == QSE_MT('.') || (c) == QSE_T('~')) (c) == QSE_MT('.') || (c) == QSE_T('~'))
#define TO_HEX(v) (QSE_MT("0123456789ABCDEF")[(v) & 15]) #define TO_HEX(v) (QSE_MT("0123456789ABCDEF")[(v) & 15])
qse_size_t qse_perenchttpstr (const qse_mchar_t* str, qse_mchar_t* buf) qse_size_t qse_perenchttpstr (int opt, const qse_mchar_t* str, qse_mchar_t* buf)
{ {
const qse_mchar_t* p = str; const qse_mchar_t* p = str;
qse_mchar_t* out = buf; qse_mchar_t* out = buf;
qse_size_t enc_count = 0;
if (opt & QSE_PERENCHTTPSTR_KEEP_SLASH)
{
while (*p != QSE_T('\0'))
{
if (IS_UNRESERVED(*p) || *p == QSE_MT('/')) *out++ = *p;
else
{
*out++ = QSE_MT('%');
*out++ = TO_HEX (*p >> 4);
*out++ = TO_HEX (*p & 15);
enc_count++;
}
p++;
}
}
else
{
while (*p != QSE_T('\0')) while (*p != QSE_T('\0'))
{ {
if (IS_UNRESERVED(*p)) *out++ = *p; if (IS_UNRESERVED(*p)) *out++ = *p;
@ -438,25 +459,37 @@ qse_size_t qse_perenchttpstr (const qse_mchar_t* str, qse_mchar_t* buf)
*out++ = QSE_MT('%'); *out++ = QSE_MT('%');
*out++ = TO_HEX (*p >> 4); *out++ = TO_HEX (*p >> 4);
*out++ = TO_HEX (*p & 15); *out++ = TO_HEX (*p & 15);
enc_count++;
} }
p++; p++;
} }
}
*out = QSE_MT('\0'); *out = QSE_MT('\0');
return out - buf; /*return out - buf;*/
return enc_count;
} }
qse_mchar_t* qse_perenchttpstrdup (const qse_mchar_t* str, qse_mmgr_t* mmgr) qse_mchar_t* qse_perenchttpstrdup (int opt, const qse_mchar_t* str, qse_mmgr_t* mmgr)
{ {
qse_mchar_t* buf; qse_mchar_t* buf;
qse_size_t len = 0; qse_size_t len = 0;
qse_size_t count = 0; qse_size_t count = 0;
/* count the number of characters that should be encoded */ /* count the number of characters that should be encoded */
if (opt & QSE_PERENCHTTPSTR_KEEP_SLASH)
{
for (len = 0; str[len] != QSE_T('\0'); len++)
{
if (!IS_UNRESERVED(str[len]) && str[len] != QSE_MT('/')) count++;
}
}
else
{
for (len = 0; str[len] != QSE_T('\0'); len++) for (len = 0; str[len] != QSE_T('\0'); len++)
{ {
if (!IS_UNRESERVED(str[len])) count++; if (!IS_UNRESERVED(str[len])) count++;
} }
}
/* if there are no characters to escape, just return the original string */ /* if there are no characters to escape, just return the original string */
if (count <= 0) return (qse_mchar_t*)str; if (count <= 0) return (qse_mchar_t*)str;
@ -466,7 +499,7 @@ qse_mchar_t* qse_perenchttpstrdup (const qse_mchar_t* str, qse_mmgr_t* mmgr)
if (buf == QSE_NULL) return QSE_NULL; if (buf == QSE_NULL) return QSE_NULL;
/* perform actual escaping */ /* perform actual escaping */
qse_perenchttpstr (str, buf); qse_perenchttpstr (opt, str, buf);
return buf; return buf;
} }

View File

@ -304,7 +304,7 @@ static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req)
} }
keepalive = cgi->keepalive; keepalive = cgi->keepalive;
if (req->attr.flags & QSE_HTRE_ATTR_LENGTH) if (req->flags & QSE_HTRE_ATTR_LENGTH)
{ {
cgi->resflags |= CGI_RES_SCRIPT_LENGTH; cgi->resflags |= CGI_RES_SCRIPT_LENGTH;
cgi->script_output_length = req->attr.content_length; cgi->script_output_length = req->attr.content_length;
@ -730,7 +730,7 @@ static int task_init_cgi (
cgi->method = qse_htre_getqmethodtype(arg->req); cgi->method = qse_htre_getqmethodtype(arg->req);
cgi->version = *qse_htre_getversion(arg->req); cgi->version = *qse_htre_getversion(arg->req);
cgi->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); cgi->keepalive = (arg->req->flags & QSE_HTRE_ATTR_KEEPALIVE);
cgi->nph = arg->nph; cgi->nph = arg->nph;
cgi->req = QSE_NULL; cgi->req = QSE_NULL;
@ -747,7 +747,7 @@ static int task_init_cgi (
} }
if (!(arg->req->state & QSE_HTRE_COMPLETED) && if (!(arg->req->state & QSE_HTRE_COMPLETED) &&
!(arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH)) !(arg->req->flags & QSE_HTRE_ATTR_LENGTH))
{ {
/* if the request is not completed and doesn't have /* if the request is not completed and doesn't have
* content-length set, it's not really possible to * content-length set, it's not really possible to
@ -821,8 +821,8 @@ static int task_init_cgi (
* should reach here. if content-length is set * should reach here. if content-length is set
* the length should match len. */ * the length should match len. */
QSE_ASSERT (len > 0); QSE_ASSERT (len > 0);
QSE_ASSERT (!(arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) || QSE_ASSERT (!(arg->req->flags & QSE_HTRE_ATTR_LENGTH) ||
((arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) && ((arg->req->flags & QSE_HTRE_ATTR_LENGTH) &&
arg->req->attr.content_length == len)); arg->req->attr.content_length == len));
cgi->reqflags |= CGI_REQ_GOTALL; cgi->reqflags |= CGI_REQ_GOTALL;
content_length = len; content_length = len;
@ -848,7 +848,7 @@ static int task_init_cgi (
cgi->req = arg->req; cgi->req = arg->req;
qse_htre_setconcb (cgi->req, cgi_snatch_client_input, task); qse_htre_setconcb (cgi->req, cgi_snatch_client_input, task);
QSE_ASSERT (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH); QSE_ASSERT (arg->req->flags & QSE_HTRE_ATTR_LENGTH);
content_length = arg->req->attr.content_length; content_length = arg->req->attr.content_length;
} }
} }

View File

@ -155,7 +155,7 @@ static qse_size_t format_dirent (
* a lot of file names to escape. */ * a lot of file names to escape. */
/* perform percent-encoding for the anchor */ /* perform percent-encoding for the anchor */
encname = qse_perenchttpstrdup (dirent->name, httpd->mmgr); encname = qse_perenchttpstrdup (0, dirent->name, httpd->mmgr);
if (encname == QSE_NULL) if (encname == QSE_NULL)
{ {
httpd->errnum = QSE_HTTPD_ENOMEM; httpd->errnum = QSE_HTTPD_ENOMEM;
@ -602,7 +602,7 @@ qse_httpd_task_t* qse_httpd_entaskdir (
data.foot.ptr = dir->foot? dir->foot: qse_httpd_getname(httpd); data.foot.ptr = dir->foot? dir->foot: qse_httpd_getname(httpd);
data.foot.len = qse_mbslen(data.foot.ptr); data.foot.len = qse_mbslen(data.foot.ptr);
data.version = *qse_htre_getversion(req); data.version = *qse_htre_getversion(req);
data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); data.keepalive = (req->flags & QSE_HTRE_ATTR_KEEPALIVE);
data.method = method; data.method = method;
QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); QSE_MEMSET (&task, 0, QSE_SIZEOF(task));

View File

@ -541,7 +541,7 @@ qse_httpd_task_t* qse_httpd_entaskfile (
data.path.ptr = (qse_mchar_t*)path; data.path.ptr = (qse_mchar_t*)path;
data.path.len = qse_mbslen(path); data.path.len = qse_mbslen(path);
data.version = *qse_htre_getversion(req); data.version = *qse_htre_getversion(req);
data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); data.keepalive = (req->flags & QSE_HTRE_ATTR_KEEPALIVE);
data.method = qse_htre_getqmethodtype(req); data.method = qse_htre_getqmethodtype(req);
xtnsize = QSE_SIZEOF(task_file_t) + data.path.len + 1; xtnsize = QSE_SIZEOF(task_file_t) + data.path.len + 1;

View File

@ -575,7 +575,7 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res)
proxy->resflags |= PROXY_RES_RECEIVED_RESHDR; proxy->resflags |= PROXY_RES_RECEIVED_RESHDR;
keepalive = proxy->keepalive; keepalive = proxy->keepalive;
if (res->attr.flags & QSE_HTRE_ATTR_LENGTH) if (res->flags & QSE_HTRE_ATTR_LENGTH)
{ {
/* the response from the peer is length based */ /* the response from the peer is length based */
proxy->resflags |= PROXY_RES_PEER_LENGTH; proxy->resflags |= PROXY_RES_PEER_LENGTH;
@ -601,7 +601,7 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res)
/* chunk response when writing back to client */ /* chunk response when writing back to client */
proxy->resflags |= PROXY_RES_CLIENT_CHUNK; proxy->resflags |= PROXY_RES_CLIENT_CHUNK;
if (res->attr.flags & QSE_HTRE_ATTR_CHUNKED) if (res->flags & QSE_HTRE_ATTR_CHUNKED)
{ {
/* mark the peer output is chunked */ /* mark the peer output is chunked */
proxy->resflags |= PROXY_RES_PEER_CHUNK; proxy->resflags |= PROXY_RES_PEER_CHUNK;
@ -623,7 +623,7 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res)
/* and push the actual disconnection task */ /* and push the actual disconnection task */
if (qse_httpd_entaskdisconnect (httpd, xtn->client, xtn->task) == QSE_NULL) return -1; if (qse_httpd_entaskdisconnect (httpd, xtn->client, xtn->task) == QSE_NULL) return -1;
if (res->attr.flags & QSE_HTRE_ATTR_CHUNKED) if (res->flags & QSE_HTRE_ATTR_CHUNKED)
proxy->resflags |= PROXY_RES_PEER_CHUNK; proxy->resflags |= PROXY_RES_PEER_CHUNK;
else else
proxy->resflags |= PROXY_RES_PEER_CLOSE; proxy->resflags |= PROXY_RES_PEER_CLOSE;
@ -925,7 +925,7 @@ static int task_init_proxy (
proxy->method = qse_htre_getqmethodtype(arg->req); proxy->method = qse_htre_getqmethodtype(arg->req);
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->flags & QSE_HTRE_ATTR_KEEPALIVE);
proxy->task = task; /* needed for url rewriting */ proxy->task = task; /* needed for url rewriting */
@ -1031,6 +1031,7 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy
{ {
int snatch_needed = 0; int snatch_needed = 0;
/* compose a request to send to the peer using the request /* compose a request to send to the peer using the request
* received from the client */ * received from the client */
@ -1038,7 +1039,26 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1) goto nomem_oops; qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1) goto nomem_oops;
proxy->qpath_pos_in_reqfwdbuf = QSE_STR_LEN(proxy->reqfwdbuf); proxy->qpath_pos_in_reqfwdbuf = QSE_STR_LEN(proxy->reqfwdbuf);
if (arg->req->flags & QSE_HTRE_QPATH_PERDEC)
{
/* the query path has been percent-decoded. so encode it back */
qse_mchar_t* qpath, * qpath_enc;
qse_size_t x;
qpath = qse_htre_getqpath(arg->req);
qpath_enc = qse_perenchttpstrdup (QSE_PERENCHTTPSTR_KEEP_SLASH, qpath, httpd->mmgr);
if (qpath_enc == QSE_NULL) goto nomem_oops;
x = qse_mbs_cat (proxy->reqfwdbuf, qpath_enc);
QSE_MMGR_FREE (httpd->mmgr, qpath_enc);
if (x == (qse_size_t)-1) goto nomem_oops;
}
else
{
/* the query path doesn't require encoding or it's never decoded */
if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqpath(arg->req)) == (qse_size_t)-1) goto nomem_oops; if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqpath(arg->req)) == (qse_size_t)-1) goto nomem_oops;
}
if (qse_htre_getqparam(arg->req)) if (qse_htre_getqparam(arg->req))
{ {
@ -1081,7 +1101,7 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc));
} }
proxy->resflags |= PROXY_RES_AWAIT_RESHDR; proxy->resflags |= PROXY_RES_AWAIT_RESHDR;
if ((arg->req->attr.flags & QSE_HTRE_ATTR_EXPECT100) && if ((arg->req->flags & QSE_HTRE_ATTR_EXPECT100) &&
(arg->req->version.major > 1 || (arg->req->version.major == 1 && arg->req->version.minor >= 1))) (arg->req->version.major > 1 || (arg->req->version.major == 1 && arg->req->version.minor >= 1)))
{ {
proxy->resflags |= PROXY_RES_AWAIT_100; proxy->resflags |= PROXY_RES_AWAIT_100;
@ -1115,8 +1135,8 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc));
if (arg->req->state & QSE_HTRE_DISCARDED) if (arg->req->state & QSE_HTRE_DISCARDED)
{ {
/* no content to add */ /* no content to add */
if ((arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) || if ((arg->req->flags & QSE_HTRE_ATTR_LENGTH) ||
(arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED)) (arg->req->flags & QSE_HTRE_ATTR_CHUNKED))
{ {
/* i don't add chunk traiers if the /* i don't add chunk traiers if the
* request content has been discarded */ * request content has been discarded */
@ -1129,15 +1149,15 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc));
} }
else if (arg->req->state & QSE_HTRE_COMPLETED) else if (arg->req->state & QSE_HTRE_COMPLETED)
{ {
if (arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED) if (arg->req->flags & QSE_HTRE_ATTR_CHUNKED)
{ {
/* add trailers if any */ /* add trailers if any */
if (qse_htre_walktrailers (arg->req, proxy_capture_client_trailer, proxy) <= -1) goto nomem_oops; if (qse_htre_walktrailers (arg->req, proxy_capture_client_trailer, proxy) <= -1) goto nomem_oops;
} }
len = qse_htre_getcontentlen(arg->req); len = qse_htre_getcontentlen(arg->req);
if (len > 0 || (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) || if (len > 0 || (arg->req->flags & QSE_HTRE_ATTR_LENGTH) ||
(arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED)) (arg->req->flags & QSE_HTRE_ATTR_CHUNKED))
{ {
qse_mchar_t buf[64]; qse_mchar_t buf[64];
@ -1163,7 +1183,7 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc));
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto nomem_oops; if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto nomem_oops;
} }
} }
else if (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) else if (arg->req->flags & QSE_HTRE_ATTR_LENGTH)
{ {
/* the Content-Length header field is contained in the request. */ /* the Content-Length header field is contained in the request. */
qse_mchar_t buf[64]; qse_mchar_t buf[64];
@ -1191,7 +1211,7 @@ qse_mbs_ncat (proxy->reqfwdbuf, spc, QSE_COUNTOF(spc));
/* if this request is not chunked nor not length based, /* if this request is not chunked nor not length based,
* the state should be QSE_HTRE_COMPLETED. so only a * the state should be QSE_HTRE_COMPLETED. so only a
* chunked request should reach here */ * chunked request should reach here */
QSE_ASSERT (arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED); QSE_ASSERT (arg->req->flags & QSE_HTRE_ATTR_CHUNKED);
proxy->reqflags |= PROXY_REQ_FWDCHUNKED; proxy->reqflags |= PROXY_REQ_FWDCHUNKED;
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Transfer-Encoding: chunked\r\n")) == (qse_size_t)-1 || if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Transfer-Encoding: chunked\r\n")) == (qse_size_t)-1 ||

View File

@ -2087,7 +2087,7 @@ static int process_request (
* any more. once it's decoded in the peek mode, * any more. once it's decoded in the peek mode,
* the decoded query path is made available in the * the decoded query path is made available in the
* non-peek mode as well */ * non-peek mode as well */
if (peek) qse_perdechttpstr (qse_htre_getqpath(req), qse_htre_getqpath(req)); if (peek) qse_htre_perdecqpath(req);
if (peek && (httpd->opt.trait & QSE_HTTPD_LOGACT)) if (peek && (httpd->opt.trait & QSE_HTTPD_LOGACT))
{ {
@ -2154,11 +2154,11 @@ if (qse_htre_getcontentlen(req) > 0)
else else
{ {
if (mth == QSE_HTTP_POST && if (mth == QSE_HTTP_POST &&
!(req->attr.flags & QSE_HTRE_ATTR_LENGTH) && !(req->flags & QSE_HTRE_ATTR_LENGTH) &&
!(req->attr.flags & QSE_HTRE_ATTR_CHUNKED)) !(req->flags & QSE_HTRE_ATTR_CHUNKED))
{ {
/* POST without Content-Length nor not chunked */ /* POST without Content-Length nor not chunked */
req->attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE; req->flags &= ~QSE_HTRE_ATTR_KEEPALIVE;
qse_httpd_discardcontent (httpd, req); qse_httpd_discardcontent (httpd, req);
task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 411, req); task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 411, req);
if (task) if (task)
@ -2234,7 +2234,7 @@ printf ("CANOT MAKE RESOURCE.... %s\n", qse_htre_getqpath(req));
if (task == QSE_NULL) goto oops; if (task == QSE_NULL) goto oops;
} }
else if (req->attr.flags & QSE_HTRE_ATTR_PROXIED) else if (req->flags & QSE_HTRE_ATTR_PROXIED)
{ {
/* the contents should be proxied. /* the contents should be proxied.
* do nothing locally */ * do nothing locally */
@ -2246,7 +2246,7 @@ printf ("CANOT MAKE RESOURCE.... %s\n", qse_htre_getqpath(req));
} }
} }
if (!(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE) || mth == QSE_HTTP_CONNECT) if (!(req->flags & QSE_HTRE_ATTR_KEEPALIVE) || mth == QSE_HTTP_CONNECT)
{ {
if (!peek) if (!peek)
{ {
@ -2727,7 +2727,7 @@ static int make_resource (
case QSE_HTTPD_SERVERSTD_ROOT_PROXY: case QSE_HTTPD_SERVERSTD_ROOT_PROXY:
target->type = QSE_HTTPD_RSRC_PROXY; target->type = QSE_HTTPD_RSRC_PROXY;
target->u.proxy = tmp.root.u.proxy; target->u.proxy = tmp.root.u.proxy;
req->attr.flags |= QSE_HTRE_ATTR_PROXIED; req->flags |= QSE_HTRE_ATTR_PROXIED;
return 0; return 0;
case QSE_HTTPD_SERVERSTD_ROOT_ERROR: case QSE_HTTPD_SERVERSTD_ROOT_ERROR:
@ -2797,7 +2797,7 @@ auth_ok:
/* if authentication is ok or no authentication is required, /* if authentication is ok or no authentication is required,
* handle 'Expect: 100-continue' if it is contained in the header */ * handle 'Expect: 100-continue' if it is contained in the header */
if ((req->attr.flags & QSE_HTRE_ATTR_EXPECT) && if ((req->flags & QSE_HTRE_ATTR_EXPECT) &&
(req->version.major > 1 || (req->version.major == 1 && req->version.minor >= 1)) && (req->version.major > 1 || (req->version.major == 1 && req->version.minor >= 1)) &&
qse_htre_getcontentlen(req) <= 0) qse_htre_getcontentlen(req) <= 0)
{ {
@ -2807,7 +2807,7 @@ auth_ok:
* if the partial or complete content is already received, * if the partial or complete content is already received,
* we don't need to send '100 continue'. */ * we don't need to send '100 continue'. */
if (req->attr.flags & QSE_HTRE_ATTR_EXPECT100) if (req->flags & QSE_HTRE_ATTR_EXPECT100)
{ {
/* "Expect: 100-continue" in the header. /* "Expect: 100-continue" in the header.
* mark to return "100 continue" */ * mark to return "100 continue" */

View File

@ -242,7 +242,7 @@ qse_httpd_task_t* qse_httpd_entaskerr (
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),
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE) (req->flags & QSE_HTRE_ATTR_KEEPALIVE)
); );
} }
@ -268,7 +268,7 @@ qse_httpd_task_t* qse_httpd_entaskauth (
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),
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)); (req->flags & QSE_HTRE_ATTR_KEEPALIVE));
} }
@ -287,7 +287,7 @@ qse_httpd_task_t* qse_httpd_entaskreloc (
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),
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)); (req->flags & QSE_HTRE_ATTR_KEEPALIVE));
} }
qse_httpd_task_t* qse_httpd_entaskredir ( qse_httpd_task_t* qse_httpd_entaskredir (
@ -303,7 +303,7 @@ qse_httpd_task_t* qse_httpd_entaskredir (
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),
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)); (req->flags & QSE_HTRE_ATTR_KEEPALIVE));
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@ -324,7 +324,7 @@ qse_httpd_task_t* qse_httpd_entasknomod (
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),
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)); (req->flags & QSE_HTRE_ATTR_KEEPALIVE));
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@ -340,7 +340,7 @@ qse_httpd_task_t* qse_httpd_entaskallow (
msg = qse_httpstatustombs (code); msg = qse_httpstatustombs (code);
version = qse_htre_getversion(req); version = qse_htre_getversion(req);
keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); keepalive = (req->flags & QSE_HTRE_ATTR_KEEPALIVE);
return qse_httpd_entaskformat ( return qse_httpd_entaskformat (
httpd, client, pred, httpd, client, pred,
QSE_MT("HTTP/%d.%d %d %s\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nAllow: %s\r\nContent-Length: 0\r\n\r\n"), QSE_MT("HTTP/%d.%d %d %s\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nAllow: %s\r\nContent-Length: 0\r\n\r\n"),

View File

@ -112,7 +112,7 @@ qse_httpd_task_t* qse_httpd_entasktext (
version->major, version->minor, version->major, version->minor,
qse_httpd_getname (httpd), qse_httpd_getname (httpd),
qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0), qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0),
((req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)? QSE_MT("keep-alive"): QSE_MT("close")), ((req->flags & QSE_HTRE_ATTR_KEEPALIVE)? QSE_MT("keep-alive"): QSE_MT("close")),
mime, b_tlen mime, b_tlen
); );
if (pred == QSE_NULL) return QSE_NULL; if (pred == QSE_NULL) return QSE_NULL;