added a new root type for httpd - <XXX> where XXX is a relocation code or an error code

This commit is contained in:
hyung-hwan 2014-10-09 14:42:02 +00:00
parent 870f307d96
commit e46977a212
11 changed files with 149 additions and 56 deletions

View File

@ -152,8 +152,20 @@ struct loccfg_t
qse_mchar_t* xcfg[XCFG_MAX];
int root_is_nwad;
qse_nwad_t root_nwad;
enum
{
ROOT_TYPE_PATH = 0,
ROOT_TYPE_NWAD,
ROOT_TYPE_RELOC,
ROOT_TYPE_ERROR
} root_type;
union
{
qse_nwad_t nwad;
int error_code;
qse_httpd_rsrc_reloc_t reloc;
} root;
struct
{
qse_size_t count;
@ -521,6 +533,7 @@ static int get_server_root (
}
}
/* TODO: handle https:// .... */
if (loccfg->proxy.allow_http &&
qse_mbszcasecmp (qpath, QSE_MT("http://"), 7) == 0)
{
@ -573,25 +586,44 @@ static int get_server_root (
}
}
if (loccfg->root_is_nwad)
switch (loccfg->root_type)
{
case ROOT_TYPE_NWAD:
/* simple forwarding. it's not controlled by proxy.http or proxy.connect */
root->type = QSE_HTTPD_SERVERSTD_ROOT_PROXY;
root->u.proxy.dst.nwad = loccfg->root_nwad;
root->u.proxy.dst.nwad = loccfg->root.nwad;
root->u.proxy.src.nwad.type = root->u.proxy.dst.nwad.type;
if (loccfg->proxy.pseudonym[0])
root->u.proxy.pseudonym = loccfg->proxy.pseudonym;
goto proxy_ok;
case ROOT_TYPE_RELOC:
root->type = QSE_HTTPD_SERVERSTD_ROOT_RELOC;
root->u.reloc.flags = loccfg->root.reloc.flags;
root->u.reloc.target = qse_mbsdup (loccfg->root.reloc.target, qse_httpd_getmmgr(httpd));
if (root->u.reloc.target == QSE_NULL)
{
root->type = QSE_HTTPD_SERVERSTD_ROOT_ERROR;
root->u.error.code = 500; /* internal server error */
}
break;
case ROOT_TYPE_ERROR:
root->type = QSE_HTTPD_SERVERSTD_ROOT_ERROR;
root->u.error.code = loccfg->root.error_code;
break;
default:
/* local file system */
root->type = QSE_HTTPD_SERVERSTD_ROOT_PATH;
root->u.path.val = loccfg->xcfg[XCFG_ROOT];
root->u.path.rpl = loccfg->locname.len;
break;
}
return 0;
proxy_ok:
@ -1624,11 +1656,70 @@ static int load_loccfg (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t* list
}
#endif
if (cfg->xcfg[XCFG_ROOT] && qse_mbstonwad (cfg->xcfg[XCFG_ROOT], &cfg->root_nwad) >= 0)
cfg->root_type = ROOT_TYPE_PATH; /* default type */
if (cfg->xcfg[XCFG_ROOT])
{
cfg->root_is_nwad = 1;
/* check if the root value is special */
const qse_mchar_t* root = cfg->xcfg[XCFG_ROOT];
if (root[0] == QSE_MT('<') && QSE_ISMDIGIT(root[1]))
{
int code = 0;
root++;
while (QSE_ISMDIGIT(*root))
{
code = code * 10 + (*root - QSE_MT('0'));
root++;
}
if (code >= 400 && code <= 599 && root[0] == QSE_MT('>') && root[1] == QSE_MT('\0'))
{
cfg->root_type = ROOT_TYPE_ERROR;
cfg->root.error_code = code;
goto done;
}
if ((code == 301 || code == 302 || code == 303 || code == 307 || code == 308) && *root == QSE_MT('>'))
{
root++;
if (QSE_ISMPRINT(*root))
{
cfg->root_type = ROOT_TYPE_RELOC;
cfg->root.reloc.flags = 0;
switch (code)
{
case 308:
cfg->root.reloc.flags |= QSE_HTTPD_RSRC_RELOC_PERMANENT;
/* fall thru */
case 307:
cfg->root.reloc.flags |= QSE_HTTPD_RSRC_RELOC_KEEPMETHOD;
break;
case 301:
cfg->root.reloc.flags |= QSE_HTTPD_RSRC_RELOC_PERMANENT;
break;
}
cfg->root.reloc.target = root;
goto done;
}
}
}
if (qse_mbstonwad (cfg->xcfg[XCFG_ROOT], &cfg->root.nwad) >= 0)
{
if (cfg->root.nwad.type != QSE_NWAD_IN4 && cfg->root.nwad.type != QSE_NWAD_IN6)
{
qse_printf (QSE_T("ERROR: invalid address for root - [%hs]\n"), cfg->xcfg[XCFG_ROOT]);
return -1;
}
cfg->root_type = ROOT_TYPE_NWAD;
goto done;
}
}
done:
return 0;
}

View File

@ -29,6 +29,8 @@ server-default {
####################################################################
root = "/var/www";
#root = "1.2.3.4:80";
#root = "<302>http://www.google.com"; #301, 302, 303, 307, 308
#root = "<404>"; #400 - 599
# pseudonym to use in Via: for proxying
#pseudonym = "my-host";

View File

@ -830,7 +830,7 @@ typedef struct qse_httpd_rsrc_reloc_t qse_httpd_rsrc_reloc_t;
struct qse_httpd_rsrc_reloc_t
{
int flags; /**< 0 or bitwise-ORed of #qse_httpd_rsrc_reloc_flag_t */
const qse_mchar_t* dst;
const qse_mchar_t* target;
};
typedef struct qse_httpd_rsrc_t qse_httpd_rsrc_t;
@ -1095,7 +1095,7 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entasktext (
qse_htre_t* req
);
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskerr (
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskerror (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
qse_httpd_task_t* pred,

View File

@ -1414,7 +1414,7 @@ printf ("task_main_cgi_2 trigger[0].mask=%d trigger[1].mask=%d cmask=%d\n",
return 1;
oops:
return (qse_httpd_entask_err (httpd, client, task, 500, cgi->method, &cgi->version, cgi->keepalive) == QSE_NULL)? -1: 0;
return (qse_httpd_entask_error (httpd, client, task, 500, cgi->method, &cgi->version, cgi->keepalive) == QSE_NULL)? -1: 0;
}
static int task_main_cgi (
@ -1578,7 +1578,7 @@ oops:
cgi->script_htrd = QSE_NULL;
}
return (qse_httpd_entask_err (
return (qse_httpd_entask_error (
httpd, client, task, http_errnum,
cgi->method, &cgi->version, cgi->keepalive) == QSE_NULL)? -1: 0;
}

View File

@ -586,7 +586,7 @@ qse_httpd_task_t* qse_httpd_entaskdir (
int status;
status = (httpd->errnum == QSE_HTTPD_ENOENT)? 404:
(httpd->errnum == QSE_HTTPD_EACCES)? 403: 500;
return qse_httpd_entaskerr (httpd, client, pred, status, req);
return qse_httpd_entaskerror (httpd, client, pred, status, req);
}
else
{
@ -643,7 +643,7 @@ qse_httpd_task_t* qse_httpd_entaskdir (
}
}
return qse_httpd_entaskerr (httpd, client, pred, status, req);
return qse_httpd_entaskerror (httpd, client, pred, status, req);
}
@ -657,11 +657,11 @@ qse_httpd_task_t* qse_httpd_entaskdir (
(httpd->errnum == QSE_HTTPD_EACCES)? 403: 500;
}
return qse_httpd_entaskerr (httpd, client, pred, status, req);
return qse_httpd_entaskerror (httpd, client, pred, status, req);
}
default:
/* Method not allowed */
return qse_httpd_entaskerr (httpd, client, pred, 405, req);
return qse_httpd_entaskerror (httpd, client, pred, 405, req);
}
}

View File

@ -191,7 +191,7 @@ static QSE_INLINE int task_main_getfile (
int http_errnum;
http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404:
(httpd->errnum == QSE_HTTPD_EACCES)? 403: 500;
x = qse_httpd_entask_err (
x = qse_httpd_entask_error (
httpd, client, x, http_errnum,
file->method, &file->version, file->keepalive);
goto no_file_send;
@ -203,7 +203,7 @@ static QSE_INLINE int task_main_getfile (
int http_errnum;
http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404:
(httpd->errnum == QSE_HTTPD_EACCES)? 403: 500;
x = qse_httpd_entask_err (
x = qse_httpd_entask_error (
httpd, client, x, http_errnum,
file->method, &file->version, file->keepalive);
goto no_file_send;
@ -226,7 +226,7 @@ static QSE_INLINE int task_main_getfile (
if (file->u.get.range.from >= st.size)
{
x = qse_httpd_entask_err (
x = qse_httpd_entask_error (
httpd, client, x, 416, file->method, &file->version, file->keepalive);
goto no_file_send;
}
@ -491,7 +491,7 @@ static int task_main_putfile_2 (
/* snatching is over. writing error may have occurred as well.
* file->u.put.status should hold a proper status code */
if (qse_httpd_entask_err (
if (qse_httpd_entask_error (
httpd, client, task, file->u.put.status,
file->method, &file->version, file->keepalive) == QSE_NULL) return -1;
return 0; /* no more data to read. task over */
@ -516,7 +516,7 @@ static int task_main_putfile (
* note: if initialization error occurred and there is contents for the
* client to send, this reply may get to the client before it finishes
* sending the contents. */
if (qse_httpd_entask_err (
if (qse_httpd_entask_error (
httpd, client, task, file->u.put.status,
file->method, &file->version, file->keepalive) == QSE_NULL) return -1;
return 0; /* task over */
@ -603,7 +603,7 @@ qse_httpd_task_t* qse_httpd_entaskfile (
/*while (tmp->next) tmp = tmp->next;*/ /* get the last value */
if (qse_parsehttprange (tmp->ptr, &data.u.get.range) <= -1)
{
return qse_httpd_entaskerr (httpd, client, pred, 416, req);
return qse_httpd_entaskerror (httpd, client, pred, 416, req);
}
}
else
@ -638,13 +638,13 @@ qse_httpd_task_t* qse_httpd_entaskfile (
(httpd->errnum == QSE_HTTPD_EACCES)? 403: 500;
}
return qse_httpd_entaskerr (httpd, client, pred, status, req);
return qse_httpd_entaskerror (httpd, client, pred, status, req);
}
default:
/* Method not allowed */
qse_htre_discardcontent (req);
return qse_httpd_entaskerr (httpd, client, pred, 405, req);
return qse_httpd_entaskerror (httpd, client, pred, 405, req);
}
}

View File

@ -1865,7 +1865,7 @@ qse_printf (QSE_T("TRAILING DATA=%d, [%hs]\n"), (int)QSE_MBS_LEN(proxy->res), QS
oops:
if (proxy->resflags & PROXY_RES_EVER_SENTBACK) return -1;
return (qse_httpd_entask_err (httpd, client, task, http_errnum, proxy->method, &proxy->version, proxy->keepalive) == QSE_NULL)? -1: 0;
return (qse_httpd_entask_error (httpd, client, task, http_errnum, proxy->method, &proxy->version, proxy->keepalive) == QSE_NULL)? -1: 0;
}
static int task_main_proxy_1 (
@ -1958,7 +1958,7 @@ static int task_main_proxy_1 (
return 1;
oops:
return (qse_httpd_entask_err (httpd, client, task, http_errnum, proxy->method, &proxy->version, proxy->keepalive) == QSE_NULL)? -1: 0;
return (qse_httpd_entask_error (httpd, client, task, http_errnum, proxy->method, &proxy->version, proxy->keepalive) == QSE_NULL)? -1: 0;
}
static void on_peer_name_resolved (qse_httpd_t* httpd, const qse_mchar_t* name, const qse_nwad_t* nwad, void* ctx)
@ -2062,7 +2062,7 @@ printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url);
/* relocation code is given explictly, no slash appending is needed.
* use qse_httpd_entask_status() rather than qse_httpd_entaskreloc(). */
reloc.flags = 0;
reloc.dst = nuptr;
reloc.target = nuptr;
if (qse_httpd_entask_status (
httpd, proxy->client, proxy->task, redir_code, &reloc,
@ -2402,7 +2402,7 @@ oops:
proxy->peer_htrd = QSE_NULL;
}
return (qse_httpd_entask_err (
return (qse_httpd_entask_error (
httpd, client, task, http_errnum,
proxy->method, &proxy->version, proxy->keepalive) == QSE_NULL)? -1: 0;
}

View File

@ -2189,7 +2189,7 @@ if (qse_htre_getcontentlen(req) > 0)
/* POST without Content-Length nor not chunked */
req->flags &= ~QSE_HTRE_ATTR_KEEPALIVE;
qse_httpd_discardcontent (httpd, req);
task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 411, req);
task = qse_httpd_entaskerror (httpd, client, QSE_NULL, 411, req);
if (task)
{
/* 411 Length Required - can't keep alive. Force disconnect */
@ -2204,7 +2204,7 @@ if (qse_htre_getcontentlen(req) > 0)
* 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);
task = qse_httpd_entaskerror (httpd, client, QSE_NULL, 500, req);
}
else
{
@ -2252,7 +2252,7 @@ printf ("CANOT MAKE RESOURCE.... %s\n", qse_htre_getqpath(req));
* '500 Internal Server Error'. If it wants to return a specific
* error code, it should return 0 with the QSE_HTTPD_RSRC_ERROR
* resource. */
task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 500, req);
task = qse_httpd_entaskerror (httpd, client, QSE_NULL, 500, req);
}
else
{
@ -2494,8 +2494,8 @@ static void free_resource (
break;
case QSE_HTTPD_RSRC_RELOC:
if (target->u.reloc.dst != qpath)
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.reloc.dst);
if (target->u.reloc.target != qpath)
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.reloc.target);
break;
default:
@ -2608,8 +2608,8 @@ static int attempt_cgi (
/* create a relocation resource */
QSE_MEMSET (target, 0, QSE_SIZEOF(*target));
target->type = QSE_HTTPD_RSRC_RELOC;
target->u.reloc.dst = merge_paths (httpd, tmp->qpath, tmp->idxfile);
if (target->u.reloc.dst == QSE_NULL) goto oops;
target->u.reloc.target = merge_paths (httpd, tmp->qpath, tmp->idxfile);
if (target->u.reloc.target == QSE_NULL) goto oops;
/* free tmp->xpath here upon success since it's not used for relocation.
* upon failure, it is freed by the caller. so the 'oops' part
@ -3022,7 +3022,7 @@ auth_ok:
qse_htre_discardcontent (req);
target->type = QSE_HTTPD_RSRC_RELOC;
target->u.reloc.flags = QSE_HTTPD_RSRC_RELOC_APPENDSLASH | QSE_HTTPD_RSRC_RELOC_PERMANENT;
target->u.reloc.dst = tmp.qpath;
target->u.reloc.target = tmp.qpath;
/* free xpath since it won't be used */
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
}
@ -3089,8 +3089,8 @@ auth_ok:
/* create a relocation resource */
target->type = QSE_HTTPD_RSRC_RELOC;
target->u.reloc.dst = merge_paths (httpd, tmp.qpath, tmp.idxfile);
if (target->u.reloc.dst == QSE_NULL) return -1;
target->u.reloc.target = merge_paths (httpd, tmp.qpath, tmp.idxfile);
if (target->u.reloc.target == QSE_NULL) return -1;
}
else if (acc == QSE_HTTPD_SERVERSTD_DIRACC)
{

View File

@ -188,7 +188,7 @@ qse_httpd_task_t* qse_httpd_entask_status (
reloc = (qse_httpd_rsrc_reloc_t*)extra;
extrapre = QSE_MT("Location: ");
extrapst = (reloc->flags & QSE_HTTPD_RSRC_RELOC_APPENDSLASH)? QSE_MT("/\r\n"): QSE_MT("\r\n");
extraval = reloc->dst;
extraval = reloc->target;
break;
}
@ -228,7 +228,7 @@ qse_httpd_task_t* qse_httpd_entask_status (
}
/*------------------------------------------------------------------------*/
qse_httpd_task_t* qse_httpd_entask_err (
qse_httpd_task_t* qse_httpd_entask_error (
qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_httpd_task_t* pred, int code,
qse_http_method_t method, const qse_http_version_t* version, int keepalive)
@ -236,7 +236,7 @@ qse_httpd_task_t* qse_httpd_entask_err (
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_entaskerror (
qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_httpd_task_t* pred, int code, qse_htre_t* req)
{
@ -384,7 +384,7 @@ qse_httpd_task_t* qse_httpd_entaskrsrc (
break;
case QSE_HTTPD_RSRC_ERROR:
task = qse_httpd_entaskerr (httpd, client, pred, rsrc->u.error.code, req);
task = qse_httpd_entaskerror (httpd, client, pred, rsrc->u.error.code, req);
break;
case QSE_HTTPD_RSRC_FILE:

View File

@ -102,7 +102,7 @@ qse_httpd_task_t* qse_httpd_entasktext (
default:
/* Method not allowed */
return qse_httpd_entaskerr (httpd, client, pred, 405, req);
return qse_httpd_entaskerror (httpd, client, pred, 405, req);
}
qse_fmtuintmaxtombs (b_tlen, QSE_COUNTOF(b_tlen), tlen, 10, -1, QSE_MT('\0'), QSE_NULL);

View File

@ -131,7 +131,7 @@ qse_httpd_task_t* qse_httpd_entask_status (
int keepalive
);
qse_httpd_task_t* qse_httpd_entask_err (
qse_httpd_task_t* qse_httpd_entask_error (
qse_httpd_t* httpd,
qse_httpd_client_t* client,
qse_httpd_task_t* pred,