enhanced httpd

This commit is contained in:
2014-08-11 05:44:03 +00:00
parent 1ba63f1829
commit 2fa6802c03
11 changed files with 481 additions and 134 deletions

View File

@ -58,11 +58,11 @@ struct task_cgi_t
int init_failed;
qse_httpd_t* httpd;
const qse_mchar_t* path;
const qse_mchar_t* script;
const qse_mchar_t* suffix;
const qse_mchar_t* root;
const qse_mchar_t* shebang;
qse_mchar_t* path;
qse_mchar_t* script;
qse_mchar_t* suffix;
qse_mchar_t* root;
qse_mchar_t* shebang;
int method;
qse_http_version_t version;
@ -1601,16 +1601,16 @@ qse_httpd_task_t* qse_httpd_entaskcgi (
if (rsrc.root == QSE_NULL) rsrc.root = QSE_MT("");
if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT("");
arg.path.ptr = rsrc.path;
arg.path.ptr = (qse_mchar_t*)rsrc.path;
arg.path.len = qse_mbslen(rsrc.path);
arg.script.ptr = rsrc.script;
arg.script.ptr = (qse_mchar_t*)rsrc.script;
arg.script.len = qse_mbslen(rsrc.script);
arg.suffix.ptr = rsrc.suffix;
arg.suffix.ptr = (qse_mchar_t*)rsrc.suffix;
arg.suffix.len = qse_mbslen(rsrc.suffix);
arg.root.ptr = rsrc.root;
arg.root.ptr = (qse_mchar_t*)rsrc.root;
arg.root.len = qse_mbslen(rsrc.root);
arg.nph = rsrc.nph;
arg.shebang.ptr = rsrc.shebang;
arg.shebang.ptr = (qse_mchar_t*)rsrc.shebang;
arg.shebang.len = qse_mbslen(rsrc.shebang);
arg.req = req;

View File

@ -606,11 +606,11 @@ qse_httpd_task_t* qse_httpd_entaskdir (
/* create a directory listing task */
qse_httpd_task_t task, * x;
data.path.ptr = dir->path;
data.path.ptr = (qse_mchar_t*)dir->path;
data.path.len = qse_mbslen(data.path.ptr);
data.qpath.ptr = qse_htre_getqpath(req);
data.qpath.len = qse_mbslen(data.qpath.ptr);
data.head.ptr = dir->head? dir->head: QSE_MT("<style type='text/css'>body { background-color:#d0e4fe; font-size: 0.9em; } div.header { font-weight: bold; margin-bottom: 5px; } div.footer { border-top: 1px solid #99AABB; text-align: right; } table { font-size: 0.9em; } td { white-space: nowrap; } td.size { text-align: right; }</style>");
data.head.ptr = dir->head? (qse_mchar_t*)dir->head: QSE_MT("<style type='text/css'>body { background-color:#d0e4fe; font-size: 0.9em; } div.header { font-weight: bold; margin-bottom: 5px; } div.footer { border-top: 1px solid #99AABB; text-align: right; } table { font-size: 0.9em; } td { white-space: nowrap; } td.size { text-align: right; }</style>");
data.head.len = qse_mbslen(data.head.ptr);
data.foot.ptr = dir->foot? dir->foot: qse_httpd_getname(httpd);
data.foot.len = qse_mbslen(data.foot.ptr);

View File

@ -539,7 +539,7 @@ qse_httpd_task_t* qse_httpd_entaskfile (
qse_size_t xtnsize;
QSE_MEMSET (&data, 0, QSE_SIZEOF(data));
data.path.ptr = path;
data.path.ptr = (qse_mchar_t*)path;
data.path.len = qse_mbslen(path);
data.version = *qse_htre_getversion(req);
data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
@ -563,7 +563,7 @@ qse_httpd_task_t* qse_httpd_entaskfile (
if (mime)
{
data.u.get.mime.ptr = mime;
data.u.get.mime.ptr = (qse_mchar_t*)mime;
data.u.get.mime.len = qse_mbslen(mime);
xtnsize += data.u.get.mime.len + 1;
}

View File

@ -943,7 +943,7 @@ static int task_init_proxy (
{
const qse_mchar_t* qpath;
const qse_mchar_t* metnam;
const qse_mchar_t* host_ptr;
const qse_mchar_t* host_ptr = QSE_NULL;
qse_mchar_t cliaddrbuf[128];
qse_size_t total_len;

View File

@ -554,14 +554,14 @@ static int init_xtn_ssl (qse_httpd_t* httpd, qse_httpd_server_t* server)
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
server_xtn = (server_xtn_t*)qse_httpd_getserverxtn (httpd, server);
if (server_xtn->query (httpd, server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_SSL, &ssl) <= -1)
if (server_xtn->query (httpd, server, QSE_HTTPD_SERVERSTD_SSL, QSE_NULL, &ssl) <= -1)
{
return -1;
}
if (ssl.certfile == QSE_NULL || ssl.keyfile == QSE_NULL)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
return -1;
}
@ -2126,7 +2126,7 @@ if (qse_htre_getcontentlen(req) > 0)
/* failed to make a resource. just send the internal server error.
* the makersrc handler can return a negative number to return
* '500 Internal Server Error'. If it wants to return a specific
* error code, it should return 0 with the QSE_HTTPD_RSRC_ERR
* error code, it should return 0 with the QSE_HTTPD_RSRC_ERROR
* resource. */
qse_httpd_discardcontent (httpd, req);
task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 500, req);
@ -2148,7 +2148,7 @@ if (qse_htre_getcontentlen(req) > 0)
/* if the resource is indicating to return an error,
* discard the contents since i won't return them */
if (rsrc.type == QSE_HTTPD_RSRC_ERR)
if (rsrc.type == QSE_HTTPD_RSRC_ERROR)
{
qse_httpd_discardcontent (httpd, req);
}
@ -2175,7 +2175,7 @@ printf ("CANOT MAKE RESOURCE.... %s\n", qse_htre_getqpath(req));
/* failed to make a resource. just send the internal server error.
* the makersrc handler can return a negative number to return
* '500 Internal Server Error'. If it wants to return a specific
* error code, it should return 0 with the QSE_HTTPD_RSRC_ERR
* error code, it should return 0 with the QSE_HTTPD_RSRC_ERROR
* resource. */
task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 500, req);
}
@ -2237,10 +2237,10 @@ static int format_error (
server_xtn = qse_httpd_getserverxtn (httpd, client->server);
if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_ERRHEAD, &head) <= -1) head = QSE_NULL;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_ERRHEAD, QSE_NULL, &head) <= -1) head = QSE_NULL;
if (head == QSE_NULL) head = QSE_MT("<style type='text/css'>body { background-color:#d0e4fe; font-size: 0.9em; } div.header { font-weight: bold; margin-bottom: 5px; } div.footer { border-top: 1px solid #99AABB; text-align: right; }</style>");
if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_ERRFOOT, &foot) <= -1) foot = QSE_NULL;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_ERRFOOT, QSE_NULL, &foot) <= -1) foot = QSE_NULL;
if (foot == QSE_NULL) foot = qse_httpd_getname(httpd);
msg = qse_httpstatustombs(code);
@ -2486,8 +2486,15 @@ static int attempt_cgi (
if (tmp->final_match)
{
qse_httpd_serverstd_query_info_t qinfo;
/* it is a final match. tmp->xpath is tmp->root + tmp->qpath */
if (server_xtn->query (httpd, client->server, req, tmp->xpath, QSE_HTTPD_SERVERSTD_CGI, &cgi) >= 0 && cgi.cgi)
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
qinfo.req = req;
qinfo.xpath = tmp->xpath;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi)
{
if (tmp->idxfile)
{
@ -2555,7 +2562,13 @@ static int attempt_cgi (
if (!st.isdir)
{
if (server_xtn->query (httpd, client->server, req, tmp->xpath, QSE_HTTPD_SERVERSTD_CGI, &cgi) >= 0 && cgi.cgi)
qse_httpd_serverstd_query_info_t qinfo;
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
qinfo.req = req;
qinfo.xpath = tmp->xpath;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi)
{
/* the script name is composed of the orginal query path.
* the pointer held in 'slash' is valid for tmp->qpath as
@ -2620,6 +2633,8 @@ static int make_resource (
qse_httpd_stat_t st;
int n, stx, acc;
qse_httpd_serverstd_query_info_t qinfo;
QSE_MEMSET (&tmp, 0, QSE_SIZEOF(tmp));
tmp.qpath = qse_htre_getqpath(req);
tmp.qpath_len = qse_mbslen (tmp.qpath);
@ -2628,6 +2643,10 @@ static int make_resource (
server_xtn = qse_httpd_getserverxtn (httpd, client->server);
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
qinfo.req = req;
#if 0
mth = qse_htre_getqmethodtype (req);
if (mth == QSE_HTTP_CONNECT)
{
@ -2653,7 +2672,7 @@ static int make_resource (
}
/* pseudonym for raw proxying should not be useful. but set it for consistency */
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_HTTPD_SERVERSTD_PSEUDONYM, &qinfo, &target->u.proxy.pseudonym) <= -1)
target->u.proxy.pseudonym = QSE_NULL;
/******************************************************************/
@ -2693,11 +2712,11 @@ static int make_resource (
{
/* make the source binding type the same as destination */
if (qse_getnwadport(&target->u.proxy.dst.nwad) == 0)
qse_setnwadport (&target->u.proxy.dst.nwad, qse_hton16(80));
qse_setnwadport (&target->u.proxy.dst.nwad, qse_hton16(QSE_HTTPD_DEFAULT_PORT));
target->u.proxy.src.nwad.type = target->u.proxy.dst.nwad.type;
}
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_HTTPD_SERVERSTD_PSEUDONYM, &qinfo, &target->u.proxy.pseudonym) <= -1)
target->u.proxy.pseudonym = QSE_NULL;
/* TODO: refrain from manipulating the request like this */
@ -2705,7 +2724,7 @@ static int make_resource (
/******************************************************************/
/*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. */
@ -2714,7 +2733,9 @@ target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
}
}
if (server_xtn->query (httpd, client->server, req, QSE_NULL, QSE_HTTPD_SERVERSTD_ROOT, &tmp.root) <= -1) return -1;
#endif
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_ROOT, &qinfo, &tmp.root) <= -1) return -1;
switch (tmp.root.type)
{
case QSE_HTTPD_SERVERSTD_ROOT_NWAD:
@ -2730,7 +2751,7 @@ target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
target->u.proxy.dst.nwad = tmp.root.u.nwad;
target->u.proxy.src.nwad.type = target->u.proxy.dst.nwad.type;
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_HTTPD_SERVERSTD_PSEUDONYM, &qinfo, &target->u.proxy.pseudonym) <= -1)
target->u.proxy.pseudonym = QSE_NULL;
/* mark that this request is going to be proxied. */
@ -2742,13 +2763,24 @@ target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
target->u.text.ptr = tmp.root.u.text.ptr;
target->u.text.mime = tmp.root.u.text.mime;
return 0;
case QSE_HTTPD_SERVERSTD_ROOT_PROXY:
target->type = QSE_HTTPD_RSRC_PROXY;
target->u.proxy = tmp.root.u.proxy;
req->attr.flags |= QSE_HTRE_ATTR_PROXIED;
return 0;
case QSE_HTTPD_SERVERSTD_ROOT_ERROR:
target->type = QSE_HTTPD_RSRC_ERROR;
target->u.error.code = tmp.root.u.error.code;
return 0;
}
/* handle the request locally */
QSE_ASSERT (tmp.root.type == QSE_HTTPD_SERVERSTD_ROOT_PATH);
if (server_xtn->query (httpd, client->server, req, QSE_NULL, QSE_HTTPD_SERVERSTD_REALM, &tmp.realm) <= -1 ||
server_xtn->query (httpd, client->server, req, QSE_NULL, QSE_HTTPD_SERVERSTD_INDEX, &tmp.index) <= -1)
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_REALM, &qinfo, &tmp.realm) <= -1 ||
server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_INDEX, &qinfo, &tmp.index) <= -1)
{
return -1;
}
@ -2792,7 +2824,7 @@ target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
tmp.auth.key.ptr = server_xtn->auth.ptr;
tmp.auth.key.len = authl2;
if (server_xtn->query (httpd, client->server, req, QSE_NULL, QSE_HTTPD_SERVERSTD_AUTH, &tmp.auth) >= 0 && tmp.auth.authok) goto auth_ok;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_AUTH, &qinfo, &tmp.auth) >= 0 && tmp.auth.authok) goto auth_ok;
}
}
@ -2825,8 +2857,8 @@ auth_ok:
{
/* Expectation Failed */
qse_htre_discardcontent (req);
target->type = QSE_HTTPD_RSRC_ERR;
target->u.err.code = 417;
target->type = QSE_HTTPD_RSRC_ERROR;
target->u.error.code = 417;
return 0;
}
}
@ -2891,12 +2923,14 @@ auth_ok:
}
}
qinfo.xpath = tmp.xpath;
/* it is a directory - should i allow it? */
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRACC, &target->u.err.code) <= -1) target->u.err.code = 500;
if (target->u.err.code < 200 || target->u.err.code > 299)
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_DIRACC, &qinfo, &target->u.error.code) <= -1) target->u.error.code = 500;
if (target->u.error.code < 200 || target->u.error.code > 299)
{
qse_htre_discardcontent (req);
target->type = QSE_HTTPD_RSRC_ERR;
target->type = QSE_HTTPD_RSRC_ERROR;
/* free xpath since it won't be used */
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
}
@ -2913,8 +2947,8 @@ auth_ok:
{
target->type = QSE_HTTPD_RSRC_DIR;
target->u.dir.path = tmp.xpath;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRHEAD, &target->u.dir.head) <= -1) target->u.dir.head = QSE_NULL;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRFOOT, &target->u.dir.foot) <= -1) target->u.dir.foot = QSE_NULL;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_DIRHEAD, &qinfo, &target->u.dir.head) <= -1) target->u.dir.head = QSE_NULL;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_DIRFOOT, &qinfo, &target->u.dir.foot) <= -1) target->u.dir.foot = QSE_NULL;
}
}
else
@ -2937,18 +2971,19 @@ auth_ok:
}
if (n >= 1) return 0;
acc = (tmp.idxfile || !qse_mbsend(tmp.qpath, QSE_MT("/")))?
QSE_HTTPD_SERVERSTD_FILEACC: QSE_HTTPD_SERVERSTD_DIRACC;
qinfo.xpath = tmp.xpath;
/* check file's access permission */
if (server_xtn->query (httpd, client->server, req, tmp.xpath, acc, &target->u.err.code) <= -1) target->u.err.code = 500;
acc = (tmp.idxfile || !qse_mbsend(tmp.qpath, QSE_MT("/")))?
QSE_HTTPD_SERVERSTD_FILEACC: QSE_HTTPD_SERVERSTD_DIRACC;
if (server_xtn->query (httpd, client->server, acc, &qinfo, &target->u.error.code) <= -1) target->u.error.code = 500;
if (target->u.err.code < 200 || target->u.err.code > 299)
if (target->u.error.code < 200 || target->u.error.code > 299)
{
/* free xpath since it won't be used */
qse_htre_discardcontent (req);
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
target->type = QSE_HTTPD_RSRC_ERR;
target->type = QSE_HTTPD_RSRC_ERROR;
}
else
{
@ -2970,15 +3005,15 @@ auth_ok:
target->type = QSE_HTTPD_RSRC_DIR;
target->u.dir.path = tmp.xpath;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRHEAD, &target->u.dir.head) <= -1) target->u.dir.head = QSE_NULL;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRFOOT, &target->u.dir.foot) <= -1) target->u.dir.foot = QSE_NULL;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_DIRHEAD, &qinfo, &target->u.dir.head) <= -1) target->u.dir.head = QSE_NULL;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_DIRFOOT, &qinfo, &target->u.dir.foot) <= -1) target->u.dir.foot = QSE_NULL;
}
else
{
target->type = QSE_HTTPD_RSRC_FILE;
target->u.file.path = tmp.xpath;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_MIME, &target->u.file.mime) <= -1)
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_MIME, &qinfo, &target->u.file.mime) <= -1)
{
/* don't care about failure */
target->u.file.mime = QSE_NULL;
@ -3026,8 +3061,9 @@ static struct cgi_tab_t cgitab[] =
static int query_server (
qse_httpd_t* httpd, qse_httpd_server_t* server,
qse_htre_t* req, const qse_mchar_t* xpath,
qse_httpd_serverstd_query_code_t code, void* result)
qse_httpd_serverstd_query_code_t code,
const qse_httpd_serverstd_query_info_t* qinfo,
void* result)
{
qse_size_t i;
@ -3077,7 +3113,7 @@ static int query_server (
qse_httpd_serverstd_cgi_t* cgi = (qse_httpd_serverstd_cgi_t*)result;
for (i = 0; i < QSE_COUNTOF(cgitab); i++)
{
if (qse_mbsend (xpath, cgitab[i].suffix))
if (qse_mbsend (qinfo->xpath, cgitab[i].suffix))
{
QSE_MEMCPY (cgi, &cgitab[i].cgi, QSE_SIZEOF(*cgi));
return 0;
@ -3092,7 +3128,7 @@ static int query_server (
/* TODO: binary search if the table is large */
for (i = 0; i < QSE_COUNTOF(mimetab); i++)
{
if (qse_mbsend (xpath, mimetab[i].suffix))
if (qse_mbsend (qinfo->xpath, mimetab[i].suffix))
{
*(const qse_mchar_t**)result = mimetab[i].type;
return 0;
@ -3108,7 +3144,7 @@ static int query_server (
/* i don't allow PUT or DELET by default.
* override this query result if you want to change
* the behavior. */
switch (qse_htre_getqmethodtype(req))
switch (qse_htre_getqmethodtype(qinfo->req))
{
case QSE_HTTP_OPTIONS:
case QSE_HTTP_HEAD:

View File

@ -390,8 +390,8 @@ qse_httpd_task_t* qse_httpd_entaskrsrc (
task = qse_httpd_entaskdir (httpd, client, pred, &rsrc->u.dir, req);
break;
case QSE_HTTPD_RSRC_ERR:
task = qse_httpd_entaskerr (httpd, client, pred, rsrc->u.err.code, req);
case QSE_HTTPD_RSRC_ERROR:
task = qse_httpd_entaskerr (httpd, client, pred, rsrc->u.error.code, req);
break;
case QSE_HTTPD_RSRC_FILE: