added X-Forwarded-For and fixed Via in httpd

This commit is contained in:
hyung-hwan 2014-07-29 16:39:14 +00:00
parent c1888aba6a
commit ae759f21e3
2 changed files with 159 additions and 15 deletions

View File

@ -2761,12 +2761,24 @@ QSE_EXPORT qse_size_t qse_mbs_fcat (
...
);
QSE_EXPORT qse_size_t qse_mbs_vfcat (
qse_mbs_t* str,
const qse_mchar_t* fmt,
va_list ap
);
QSE_EXPORT qse_size_t qse_mbs_fmt (
qse_mbs_t* str,
const qse_mchar_t* fmt,
...
);
QSE_EXPORT qse_size_t qse_mbs_vfmt (
qse_mbs_t* str,
const qse_mchar_t* fmt,
va_list ap
);
/**
* The qse_wcs_open() function creates a dynamically resizable wide-character
* string.
@ -2992,7 +3004,9 @@ QSE_EXPORT qse_size_t qse_wcs_fmt (
# 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
# define qse_str_vfcat qse_mbs_vfcat
# define qse_str_fmt qse_mbs_fmt
# define qse_str_vfmt qse_mbs_vfmt
#else
# define qse_str_setmmgr(str,mmgr) qse_wcs_wetmmgr(str,mmgr)
# define qse_str_getmmgr(str) qse_wcs_getmmgr(str)
@ -3021,7 +3035,9 @@ QSE_EXPORT qse_size_t qse_wcs_fmt (
# 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
# define qse_str_vfcat qse_wcs_vfcat
# define qse_str_fmt qse_wcs_fmt
# define qse_str_vfmt qse_wcs_vfmt
#endif

View File

@ -39,6 +39,9 @@ struct task_proxy_t
#define PROXY_RAW (1 << 1)
#define PROXY_RESOL_PEER_NAME (1 << 2)
#define PROXY_UNKNOWN_PEER_NWAD (1 << 3)
#define PROXY_X_FORWARDED_FOR (1 << 4)
#define PROXY_VIA (1 << 5)
#define PROXY_VIA_RETURNING (1 << 6)
int flags;
qse_httpd_t* httpd;
qse_httpd_client_t* client;
@ -137,10 +140,61 @@ static int proxy_add_header_to_buffer (
return 0;
}
static int proxy_add_header_to_buffer_with_extra_data (
task_proxy_t* proxy, qse_mbs_t* buf, const qse_mchar_t* key, const qse_htre_hdrval_t* val,
const qse_mchar_t* fmt, ...)
{
va_list ap;
QSE_ASSERT (val != QSE_NULL);
/* NOTE: append the extra data to each value */
do
{
va_start (ap, fmt);
if (qse_mbs_cat (buf, key) == (qse_size_t)-1 ||
qse_mbs_cat (buf, QSE_MT(": ")) == (qse_size_t)-1 ||
qse_mbs_cat (buf, val->ptr) == (qse_size_t)-1 ||
(fmt && qse_mbs_vfcat (buf, fmt, ap) == (qse_size_t)-1) ||
qse_mbs_cat (buf, QSE_MT("\r\n")) == (qse_size_t)-1)
{
va_end (ap);
proxy->httpd->errnum = QSE_HTTPD_ENOMEM;
return -1;
}
va_end (ap);
val = val->next;
}
while (val);
return 0;
}
static int proxy_capture_peer_header (qse_htre_t* req, const qse_mchar_t* key, const qse_htre_hdrval_t* val, void* ctx)
{
task_proxy_t* proxy = (task_proxy_t*)ctx;
if (!(proxy->httpd->opt.trait & QSE_HTTPD_PROXYNOVIA) && !(proxy->flags & PROXY_VIA_RETURNING))
{
if (qse_mbscasecmp (key, QSE_MT("Via")) == 0)
{
qse_mchar_t extra[128];
proxy->flags |= PROXY_VIA_RETURNING;
qse_nwadtombs (&proxy->client->local_addr, extra, QSE_COUNTOF(extra), QSE_NWADTOMBS_ALL);
return proxy_add_header_to_buffer_with_extra_data (
proxy, proxy->res, key, val,
QSE_MT(", %d.%d %hs (%hs)"),
(int)proxy->version.major,
(int)proxy->version.minor,
extra,
qse_httpd_getname(proxy->httpd));
}
}
if (qse_mbscasecmp (key, QSE_MT("Connection")) != 0 &&
qse_mbscasecmp (key, QSE_MT("Transfer-Encoding")) != 0)
{
@ -168,6 +222,43 @@ static int proxy_capture_client_header (qse_htre_t* req, const qse_mchar_t* key,
{
task_proxy_t* proxy = (task_proxy_t*)ctx;
if (!(proxy->flags & PROXY_X_FORWARDED_FOR))
{
if (qse_mbscasecmp (key, QSE_MT("X-Forwarded-For")) == 0)
{
/* append to X-Forwarded-For if it exists in the header.
* note that it add a comma even if the existing value is empty.
* actually, no such value must be sent in by a well-behaving
* client/proxy/load-balancer, etc. */
qse_mchar_t extra[128];
proxy->flags |= PROXY_X_FORWARDED_FOR;
qse_nwadtombs (&proxy->client->remote_addr, extra, QSE_COUNTOF(extra), QSE_NWADTOMBS_ALL);
return proxy_add_header_to_buffer_with_extra_data (proxy, proxy->reqfwdbuf, key, val, QSE_MT(", %hs"), extra);
}
}
if (!(proxy->httpd->opt.trait & QSE_HTTPD_PROXYNOVIA) && !(proxy->flags & PROXY_VIA))
{
if (qse_mbscasecmp (key, QSE_MT("Via")) == 0)
{
qse_mchar_t extra[128];
proxy->flags |= PROXY_VIA;
qse_nwadtombs (&proxy->client->local_addr, extra, QSE_COUNTOF(extra), QSE_NWADTOMBS_ALL);
return proxy_add_header_to_buffer_with_extra_data (
proxy, proxy->reqfwdbuf, key, val,
QSE_MT(", %d.%d %hs (%hs)"),
(int)proxy->version.major,
(int)proxy->version.minor,
extra,
qse_httpd_getname(proxy->httpd));
}
}
if (qse_mbscasecmp (key, QSE_MT("Transfer-Encoding")) != 0 &&
qse_mbscasecmp (key, QSE_MT("Content-Length")) != 0)
{
@ -539,17 +630,6 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res)
}
/* end initial line */
if (!(httpd->opt.trait & QSE_HTTPD_PROXYNOVIA) && qse_htre_getscodeval(res) != 100)
{
/* add the Via: header into the response if it is not 100. */
if (qse_mbs_cat (proxy->res, QSE_MT("Via: ")) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->res, qse_httpd_getname (httpd)) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1)
{
httpd->errnum = QSE_HTTPD_ENOMEM;
return -1;
}
}
if (proxy->resflags & PROXY_RES_PEER_LENGTH_FAKE)
{
@ -587,7 +667,30 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res)
}
if (qse_htre_walkheaders (res, proxy_capture_peer_header, proxy) <= -1) return -1;
if (!(httpd->opt.trait & QSE_HTTPD_PROXYNOVIA) && !(proxy->flags & PROXY_VIA_RETURNING) && qse_htre_getscodeval(res) != 100)
{
/* add the Via: header into the response if it is not 100. */
qse_size_t tmp;
qse_mchar_t extra[128];
qse_http_version_t v;
proxy->flags |= PROXY_VIA_RETURNING;
v = *qse_htre_getversion(res);
qse_nwadtombs (&proxy->client->local_addr, extra, QSE_COUNTOF(extra), QSE_NWADTOMBS_ALL);
tmp = qse_mbs_fcat (
proxy->res, QSE_MT("Via: %d.%d %hs (%hs)\r\n"),
(int)v.major, (int)v.minor,
extra, qse_httpd_getname(httpd));
if (tmp == (qse_size_t)-1)
{
httpd->errnum = QSE_HTTPD_ENOMEM;
return -1;
}
}
/* end of headers */
if (qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1) return -1;
/* content body begins here */
@ -834,11 +937,27 @@ static int task_init_proxy (
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("?")) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqparam(arg->req)) == (qse_size_t)-1) goto oops;
}
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getverstr(arg->req)) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1 ||
qse_htre_walkheaders (arg->req, proxy_capture_client_header, proxy) <= -1) goto oops;
if (!(proxy->flags & PROXY_X_FORWARDED_FOR))
{
/* X-Forwarded-For is not added by proxy_capture_client_header()
* above. I don't care if it's included in the trailer. */
qse_mchar_t extra[128];
proxy->flags |= PROXY_X_FORWARDED_FOR;
qse_nwadtombs (&proxy->client->remote_addr, extra, QSE_COUNTOF(extra), QSE_NWADTOMBS_ALL);
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("X-Forwarded-For: ")) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->reqfwdbuf, extra) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
}
proxy->resflags |= PROXY_RES_AWAIT_RESHDR;
if ((arg->req->attr.flags & QSE_HTRE_ATTR_EXPECT100) &&
(arg->req->version.major > 1 || (arg->req->version.major == 1 && arg->req->version.minor >= 1)))
@ -846,12 +965,21 @@ static int task_init_proxy (
proxy->resflags |= PROXY_RES_AWAIT_100;
}
if (!(httpd->opt.trait & QSE_HTTPD_PROXYNOVIA))
if (!(httpd->opt.trait & QSE_HTTPD_PROXYNOVIA) && !(proxy->flags & PROXY_VIA))
{
/* add the Via: header into the request */
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Via: ")) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->reqfwdbuf, qse_httpd_getname (httpd)) == (qse_size_t)-1 ||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
qse_size_t tmp;
qse_mchar_t extra[128];
proxy->flags |= PROXY_VIA;
qse_nwadtombs (&proxy->client->local_addr, extra, QSE_COUNTOF(extra), QSE_NWADTOMBS_ALL);
tmp = qse_mbs_fcat (
proxy->reqfwdbuf, QSE_MT("Via: %d.%d %hs (%hs)\r\n"),
(int)proxy->version.major, (int)proxy->version.minor,
extra, qse_httpd_getname(httpd));
if (tmp == (qse_size_t)-1) goto oops;
}
if (arg->req->state & QSE_HTRE_DISCARDED)