simplified relocation handling

deleted qse_httpd_entaskredir() and related definitions
added virtual(function pointer) cgi  support.
improved pio to read /dev/fd
implemented QSE_PIO_FNCCMD for qse_pio_t
This commit is contained in:
hyung-hwan 2014-09-19 14:05:02 +00:00
parent bf25f92704
commit b7d14da21e
13 changed files with 889 additions and 715 deletions

View File

@ -357,6 +357,33 @@ static int daemonize (int devnull)
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
int xxxx (void* ctx, qse_env_char_t** envir)
{
extern char** environ;
char buf[1000];
char* cl;
int cl_i = 0;
environ = envir;
printf ("Content-Type: text/html\n\n");
printf ("<html><body><pre>\n");
system ("ls -laF /tmp");
printf ("--------------------\n");
system ("printenv");
cl = getenv("CONTENT_LENGTH");
if (cl) cl_i = atoi(cl);
//if (cl_i)
//{
while (fgets (buf, sizeof(buf), stdin) != NULL)
{
printf ("%s", buf);
}
//}
// system ("while read xxx; do echo $xxx; done; echo 123 456 789");
printf ("</pre></body></html>\n");
return 0;
}
static int make_resource ( static int make_resource (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_htre_t* req, qse_httpd_rsrc_t* rsrc) qse_htre_t* req, qse_httpd_rsrc_t* rsrc)
@ -406,7 +433,7 @@ static loccfg_t* find_loccfg (
for (loccfg = hostcfg->loccfg; loccfg; loccfg = loccfg->next) for (loccfg = hostcfg->loccfg; loccfg; loccfg = loccfg->next)
{ {
QSE_ASSERT (loccfg->locname.len > 0); QSE_ASSERT (loccfg->locname.len > 0);
if (qse_mbsbeg (qpath, loccfg->locname.ptr) && if (qse_mbsbeg (qpath, loccfg->locname.ptr) &&
(loccfg->locname.ptr[loccfg->locname.len - 1] == QSE_MT('/') || (loccfg->locname.ptr[loccfg->locname.len - 1] == QSE_MT('/') ||
qpath[loccfg->locname.len] == QSE_MT('/') || qpath[loccfg->locname.len] == QSE_MT('/') ||
qpath[loccfg->locname.len] == QSE_MT('\0'))) qpath[loccfg->locname.len] == QSE_MT('\0')))
@ -708,10 +735,10 @@ found:
if (qse_mbscmp (qse_htre_getqpath(qinfo->req), QSE_MT("/version")) == 0) if (qse_mbscmp (qse_htre_getqpath(qinfo->req), QSE_MT("/version")) == 0)
{ {
/* return static text without inspecting further */ /* return static text without inspecting further */
((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_TEXT;
/*((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_TEXT;
((qse_httpd_serverstd_root_t*)result)->u.text.ptr = QSE_MT(QSE_PACKAGE_NAME " " QSE_PACKAGE_VERSION); ((qse_httpd_serverstd_root_t*)result)->u.text.ptr = QSE_MT(QSE_PACKAGE_NAME " " QSE_PACKAGE_VERSION);
((qse_httpd_serverstd_root_t*)result)->u.text.mime = QSE_MT("text/plain"); ((qse_httpd_serverstd_root_t*)result)->u.text.mime = QSE_MT("text/plain");*/
}
else else
#endif #endif
@ -724,7 +751,10 @@ found:
((qse_httpd_serverstd_realm_t*)result)->name = loccfg->xcfg[XCFG_REALM]; ((qse_httpd_serverstd_realm_t*)result)->name = loccfg->xcfg[XCFG_REALM];
/* qinfo->xpath is not available for the REALM query in the std implementation.
* let me check if it's available in case the implementation changes */
apath = qinfo->xpath? qinfo->xpath: qse_htre_getqpath (qinfo->req); apath = qinfo->xpath? qinfo->xpath: qse_htre_getqpath (qinfo->req);
printf ("apth in READM QUERY [%s]\n", apath);
if (apath) if (apath)
{ {
const qse_mchar_t* base; const qse_mchar_t* base;
@ -803,25 +833,44 @@ found:
qse_size_t i; qse_size_t i;
qse_httpd_serverstd_cgi_t* scgi; qse_httpd_serverstd_cgi_t* scgi;
const qse_mchar_t* xpath_base; const qse_mchar_t* xpath_base;
qse_mchar_t* qpath;
xpath_base = qse_mbsbasename (qinfo->xpath); qpath = qse_htre_getqpath(qinfo->req);
scgi = (qse_httpd_serverstd_cgi_t*)result; scgi = (qse_httpd_serverstd_cgi_t*)result;
qse_memset (scgi, 0, QSE_SIZEOF(*scgi)); qse_memset (scgi, 0, QSE_SIZEOF(*scgi));
for (i = 0; i < QSE_COUNTOF(loccfg->cgi); i++) #if 1
printf ("qinfo->xpath ####### [%s] %d [%s]\n", qinfo->xpath, qinfo->xpath_nx, qpath);
//if (qse_mbscmp (qinfo->xpath, QSE_MT("/tmp/version.cgi")) == 0)
if (qse_mbscmp (qpath, QSE_MT("/local/version.cgi")) == 0)
{ {
struct cgi_t* cgi; scgi->cgi = 1;
for (cgi = loccfg->cgi[i].head; cgi; cgi = cgi->next) scgi->nph = 0;
scgi->fncptr = xxxx;
scgi->shebang = QSE_NULL;
return 0;
}
#endif
if (!qinfo->xpath_nx)
{
xpath_base = qse_mbsbasename (qinfo->xpath);
for (i = 0; i < QSE_COUNTOF(loccfg->cgi); i++)
{ {
if ((cgi->type == CGI_PREFIX && qse_mbsbeg (xpath_base, cgi->spec)) || struct cgi_t* cgi;
(cgi->type == CGI_SUFFIX && qse_mbsend (xpath_base, cgi->spec)) || for (cgi = loccfg->cgi[i].head; cgi; cgi = cgi->next)
(cgi->type == CGI_NAME && qse_mbscmp (xpath_base, cgi->spec) == 0))
{ {
scgi->cgi = 1; if ((cgi->type == CGI_PREFIX && qse_mbsbeg (xpath_base, cgi->spec)) ||
scgi->nph = cgi->nph; (cgi->type == CGI_SUFFIX && qse_mbsend (xpath_base, cgi->spec)) ||
scgi->shebang = cgi->shebang; (cgi->type == CGI_NAME && qse_mbscmp (xpath_base, cgi->spec) == 0))
return 0; {
scgi->cgi = 1;
scgi->nph = cgi->nph;
scgi->shebang = cgi->shebang;
return 0;
}
} }
} }
} }
@ -874,7 +923,7 @@ found:
id = (code == QSE_HTTPD_SERVERSTD_DIRACC)? 0: 1; id = (code == QSE_HTTPD_SERVERSTD_DIRACC)? 0: 1;
xpath_base = qse_mbsbasename (qinfo->xpath); xpath_base = qse_mbsbasename (qinfo->xpath);
*(int*)result = 200; *(int*)result = 200;
for (i = 0; i < QSE_COUNTOF(loccfg->access[id]); i++) for (i = 0; i < QSE_COUNTOF(loccfg->access[id]); i++)
{ {

View File

@ -59,6 +59,10 @@ enum qse_pio_flag_t
* them to prevent inheritance. */ * them to prevent inheritance. */
QSE_PIO_NOCLOEXEC = (1 << 5), QSE_PIO_NOCLOEXEC = (1 << 5),
/** indidate that the command to qse_pio_open() is a pointer to
* #qse_pio_fnc_t. supported on unix/linux only */
QSE_PIO_FNCCMD = (1 << 6),
/** write to stdin of a child process */ /** write to stdin of a child process */
QSE_PIO_WRITEIN = (1 << 8), QSE_PIO_WRITEIN = (1 << 8),
/** read stdout of a child process */ /** read stdout of a child process */
@ -113,6 +117,16 @@ enum qse_pio_hid_t
}; };
typedef enum qse_pio_hid_t qse_pio_hid_t; typedef enum qse_pio_hid_t qse_pio_hid_t;
typedef int (*qse_pio_fncptr_t) (void* ctx, qse_env_char_t** envir);
typedef struct qse_pio_fnc_t qse_pio_fnc_t;
struct qse_pio_fnc_t
{
qse_pio_fncptr_t ptr;
void* ctx;
};
/** /**
* The qse_pio_errnum_t type defines error numbers. * The qse_pio_errnum_t type defines error numbers.
*/ */
@ -177,6 +191,7 @@ struct qse_pio_pin_t
qse_pio_t* self; qse_pio_t* self;
}; };
/** /**
* The qse_pio_t type defines a structure to store status for piped I/O * The qse_pio_t type defines a structure to store status for piped I/O
* to a child process. The qse_pio_xxx() funtions are written around this * to a child process. The qse_pio_xxx() funtions are written around this

View File

@ -28,6 +28,8 @@
#include <qse/cmn/nwad.h> #include <qse/cmn/nwad.h>
#include <qse/cmn/time.h> #include <qse/cmn/time.h>
#include <qse/cmn/tmr.h> #include <qse/cmn/tmr.h>
#include <qse/cmn/env.h>
typedef struct qse_httpd_t qse_httpd_t; typedef struct qse_httpd_t qse_httpd_t;
typedef struct qse_httpd_mate_t qse_httpd_mate_t; typedef struct qse_httpd_mate_t qse_httpd_mate_t;
@ -689,6 +691,19 @@ struct qse_httpd_urs_t
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* ensure to define qse_httpd_fncptr_t to the same as
* qse_pio_fncptr_t in <qse/cmn/pio.h> */
typedef int (*qse_httpd_fncptr_t) (void* ctx, qse_env_char_t** envir);
typedef struct qse_httpd_fnc_t qse_httpd_fnc_t;
struct qse_httpd_fnc_t
{
qse_httpd_fncptr_t ptr;
void* ctx;
};
/* -------------------------------------------------------------------------- */
/** /**
* The qse_httpd_rsrc_type_t defines the resource type than can * The qse_httpd_rsrc_type_t defines the resource type than can
* be entasked with qse_httpd_entaskrsrc(). * be entasked with qse_httpd_entaskrsrc().
@ -702,7 +717,6 @@ enum qse_httpd_rsrc_type_t
QSE_HTTPD_RSRC_FILE, QSE_HTTPD_RSRC_FILE,
QSE_HTTPD_RSRC_PROXY, QSE_HTTPD_RSRC_PROXY,
QSE_HTTPD_RSRC_RELOC, QSE_HTTPD_RSRC_RELOC,
QSE_HTTPD_RSRC_REDIR,
QSE_HTTPD_RSRC_TEXT QSE_HTTPD_RSRC_TEXT
}; };
typedef enum qse_httpd_rsrc_type_t qse_httpd_rsrc_type_t; typedef enum qse_httpd_rsrc_type_t qse_httpd_rsrc_type_t;
@ -711,16 +725,39 @@ enum qse_httpd_rsrc_flag_t
{ {
QSE_HTTPD_RSRC_100_CONTINUE = (1 << 0) QSE_HTTPD_RSRC_100_CONTINUE = (1 << 0)
}; };
typedef enum qse_httpd_rsrc_flag_t qse_httpd_rsrc_flag_t;
enum qse_httpd_rsrc_cgi_flag_t
{
/* non-parsed header */
QSE_HTTPD_RSRC_CGI_NPH = (1 << 0),
/* 'path' points to qse_httpd_fncptr_t && 'shebang' points to its context */
QSE_HTTPD_RSRC_CGI_FNC = (1 << 1)
};
typedef enum qse_httpd_rsrc_cgi_flag_t qse_httpd_rsrc_cgi_flag_t;
typedef struct qse_httpd_rsrc_cgi_t qse_httpd_rsrc_cgi_t; typedef struct qse_httpd_rsrc_cgi_t qse_httpd_rsrc_cgi_t;
struct qse_httpd_rsrc_cgi_t struct qse_httpd_rsrc_cgi_t
{ {
const qse_mchar_t* path; /* bitwised-ORed of #qse_httpd_rsrc_cgi_flag_t */
const qse_mchar_t* script; int flags;
const qse_mchar_t* suffix;
/* script path resolved against file system */
const qse_mchar_t* path;
/* script path as in qpath */
const qse_mchar_t* script;
/* trailing part of qpath excluding the script path.
* for a qpath of /tmp/abc.cgi/a/b/c, if /tmp/abc.cgi is a script path,
* /a/b/c forms the suffix.*/
const qse_mchar_t* suffix;
const qse_mchar_t* root; const qse_mchar_t* root;
const qse_mchar_t* shebang; const qse_mchar_t* shebang;
int nph;
}; };
enum qse_httpd_rsrc_proxy_flag_t enum qse_httpd_rsrc_proxy_flag_t
@ -733,6 +770,7 @@ enum qse_httpd_rsrc_proxy_flag_t
QSE_HTTPD_RSRC_PROXY_DNS_SERVER = (1 << 5), /* dns address specified */ QSE_HTTPD_RSRC_PROXY_DNS_SERVER = (1 << 5), /* dns address specified */
QSE_HTTPD_RSRC_PROXY_URS_SERVER = (1 << 6), /* urs address specified */ QSE_HTTPD_RSRC_PROXY_URS_SERVER = (1 << 6), /* urs address specified */
}; };
typedef enum qse_httpd_rsrc_proxy_flag_t qse_httpd_rsrc_proxy_flag_t;
typedef struct qse_httpd_rsrc_proxy_t qse_httpd_rsrc_proxy_t; typedef struct qse_httpd_rsrc_proxy_t qse_httpd_rsrc_proxy_t;
struct qse_httpd_rsrc_proxy_t struct qse_httpd_rsrc_proxy_t
@ -774,6 +812,21 @@ struct qse_httpd_rsrc_dir_t
const qse_mchar_t* foot; const qse_mchar_t* foot;
}; };
enum qse_httpd_rsrc_reloc_flag_t
{
QSE_HTTPD_RSRC_RELOC_PERMANENT = (1 << 0),
QSE_HTTPD_RSRC_RELOC_KEEPMETHOD = (1 << 1),
QSE_HTTPD_RSRC_RELOC_APPENDSLASH = (1 << 2)
};
typedef enum qse_httpd_rsrc_reloc_flag_t qse_httpd_rsrc_reloc_flag_t;
typedef struct qse_httpd_rsrc_reloc_t qse_httpd_rsrc_reloc_t;
struct qse_httpd_rsrc_reloc_t
{
int flags;
const qse_mchar_t* dst;
};
typedef struct qse_httpd_rsrc_t qse_httpd_rsrc_t; typedef struct qse_httpd_rsrc_t qse_httpd_rsrc_t;
struct qse_httpd_rsrc_t struct qse_httpd_rsrc_t
{ {
@ -802,15 +855,7 @@ struct qse_httpd_rsrc_t
qse_httpd_rsrc_proxy_t proxy; qse_httpd_rsrc_proxy_t proxy;
struct qse_httpd_rsrc_reloc_t reloc;
{
const qse_mchar_t* dst;
} reloc;
struct
{
const qse_mchar_t* dst;
} redir;
struct struct
{ {
@ -1071,22 +1116,13 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskauth (
); );
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskreloc ( QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskreloc (
qse_httpd_t* httpd, qse_httpd_t* httpd,
qse_httpd_client_t* client, qse_httpd_client_t* client,
qse_httpd_task_t* pred, qse_httpd_task_t* pred,
const qse_mchar_t* dst, const qse_httpd_rsrc_reloc_t* reloc,
qse_htre_t* req qse_htre_t* req
); );
QSE_EXPORT 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
);
QSE_EXPORT qse_httpd_task_t* qse_httpd_entasknomod ( QSE_EXPORT qse_httpd_task_t* qse_httpd_entasknomod (
qse_httpd_t* httpd, qse_httpd_t* httpd,
qse_httpd_client_t* client, qse_httpd_client_t* client,

View File

@ -90,9 +90,17 @@ struct qse_httpd_serverstd_auth_t
typedef struct qse_httpd_serverstd_cgi_t qse_httpd_serverstd_cgi_t; typedef struct qse_httpd_serverstd_cgi_t qse_httpd_serverstd_cgi_t;
struct qse_httpd_serverstd_cgi_t struct qse_httpd_serverstd_cgi_t
{ {
int cgi: 1; unsigned int cgi: 1;
int nph: 1; unsigned int nph: 1;
const qse_mchar_t* shebang; /* optional, can be #QSE_NULL */
/* optional, can be #QSE_NULL. */
qse_httpd_fncptr_t fncptr;
/* optional, can be #QSE_NULL. if fncptr not #QSE_NULL, shebang is
* interpreted as void* and used as a context pointer to fnc.
* if fncptr is #QSE_NULL, it provides a pointer to the path
* to the program interpreter for executing a cgi script. */
const qse_mchar_t* shebang;
}; };
typedef struct qse_httpd_serverstd_index_t qse_httpd_serverstd_index_t; typedef struct qse_httpd_serverstd_index_t qse_httpd_serverstd_index_t;
@ -135,7 +143,22 @@ struct qse_httpd_serverstd_query_info_t
{ {
qse_httpd_client_t* client; qse_httpd_client_t* client;
qse_htre_t* req; qse_htre_t* req;
qse_mchar_t* xpath; /* query path combined with document root */
/**
* set to a query path combined with document root for these query types.
* - #QSE_HTTPD_SERVERSTD_CGI
* - #QSE_HTTPD_SERVERSTD_MIME
* - #QSE_HTTPD_SERVERSTD_DIRACC
* - #QSE_HTTPD_SERVERSTD_FILEACC
* - #QSE_HTTPD_SERVERSTD_DIRHEAD
* - #QSE_HTTPD_SERVERSTD_DIRFOOT
*
* set to #QSE_NULL for other query types.
*/
qse_mchar_t* xpath;
/** indiates that stat() failed over xpath when it's not #QSE_NULL. */
int xpath_nx;
}; };
typedef struct qse_httpd_serverstd_query_info_t qse_httpd_serverstd_query_info_t; typedef struct qse_httpd_serverstd_query_info_t qse_httpd_serverstd_query_info_t;

View File

@ -437,7 +437,7 @@ static qse_wchar_t* get_env (qse_env_t* env, const qse_wchar_t* name, int* free)
*free = 0; *free = 0;
return eq + 1; return eq + 1;
} }
p++; p++;
} }
} }
*/ */
@ -464,10 +464,10 @@ static qse_wchar_t* get_env (qse_env_t* env, const qse_wchar_t* name, int* free)
QSE_MMGR_FREE (env->mmgr, dup); QSE_MMGR_FREE (env->mmgr, dup);
p++; p++;
} }
} }
return 0; return 0;
} }
@ -494,10 +494,10 @@ static qse_mchar_t* get_env (qse_env_t* env, const qse_mchar_t* name, int* free)
*free = 0; *free = 0;
return eq + 1; return eq + 1;
} }
p++; p++;
} }
} }
return 0; return 0;
} }
#endif #endif
@ -587,14 +587,14 @@ static int load_curenv (qse_env_t* env)
if (*envstr != QSE_WT('=') && if (*envstr != QSE_WT('=') &&
add_envstrw (env, envstr) <= -1) { ret = -1; goto done; } add_envstrw (env, envstr) <= -1) { ret = -1; goto done; }
envstr += qse_wcslen (envstr) + 1; envstr += qse_wcslen (envstr) + 1;
} }
#else #else
while (*envstr != QSE_MT('\0')) while (*envstr != QSE_MT('\0'))
{ {
if (*envstr != QSE_MT('=') && if (*envstr != QSE_MT('=') &&
add_envstrm (env, envstr) <= -1) { ret = -1; goto done; } add_envstrm (env, envstr) <= -1) { ret = -1; goto done; }
envstr += qse_mbslen (envstr) + 1; envstr += qse_mbslen (envstr) + 1;
} }
#endif #endif
done: done:
@ -614,7 +614,7 @@ done:
while (*p) while (*p)
{ {
if (add_envstrw (env, *p) <= -1) return -1; if (add_envstrw (env, *p) <= -1) return -1;
p++; p++;
} }
} }
*/ */
@ -635,11 +635,10 @@ done:
QSE_MMGR_FREE (env->mmgr, dup); QSE_MMGR_FREE (env->mmgr, dup);
if (n <= -1) return -1; if (n <= -1) return -1;
p++; p++;
} }
} }
return 0; return 0;
#else #else
@ -656,10 +655,10 @@ done:
while (*p) while (*p)
{ {
if (add_envstrm (env, *p) <= -1) return -1; if (add_envstrm (env, *p) <= -1) return -1;
p++; p++;
} }
} }
return 0; return 0;
#endif #endif
} }

File diff suppressed because it is too large Load Diff

View File

@ -316,7 +316,7 @@ qse_task_slice_t* qse_task_create (
tmp = ((qse_uint8_t*)(slice + 1)) + stksize - QSE_SIZEOF(void*); tmp = ((qse_uint8_t*)(slice + 1)) + stksize - QSE_SIZEOF(void*);
tmp = (qse_uint8_t*)tmp - QSE_SIZEOF(void*); tmp = (qse_uint8_t*)tmp - QSE_SIZEOF(void*);
*(void**)tmp = NULL; /* t1 */ *(void**)tmp = QSE_NULL; /* t1 */
tmp = (qse_uint8_t*)tmp - QSE_SIZEOF(void*); tmp = (qse_uint8_t*)tmp - QSE_SIZEOF(void*);
*(void**)tmp = slice; /* t2 */ *(void**)tmp = slice; /* t2 */

View File

@ -56,6 +56,7 @@ const qse_mchar_t* qse_httpstatustombs (int code)
case 304: msg = QSE_MT("Not Modified"); break; case 304: msg = QSE_MT("Not Modified"); break;
case 305: msg = QSE_MT("Use Proxy"); break; case 305: msg = QSE_MT("Use Proxy"); break;
case 307: msg = QSE_MT("Temporary Redirect"); break; case 307: msg = QSE_MT("Temporary Redirect"); break;
case 308: msg = QSE_MT("Permanent Redirect"); break;
case 400: msg = QSE_MT("Bad Request"); break; case 400: msg = QSE_MT("Bad Request"); break;
case 401: msg = QSE_MT("Unauthorized"); break; case 401: msg = QSE_MT("Unauthorized"); break;

View File

@ -44,6 +44,7 @@ struct task_cgi_arg_t
qse_mcstr_t root; qse_mcstr_t root;
qse_mcstr_t shebang; qse_mcstr_t shebang;
int nph; int nph;
qse_httpd_fnc_t fnc;
qse_htre_t* req; qse_htre_t* req;
}; };
@ -63,6 +64,7 @@ struct task_cgi_t
qse_http_version_t version; qse_http_version_t version;
int keepalive; /* taken from the request */ int keepalive; /* taken from the request */
int nph; int nph;
qse_pio_fnc_t fnc;
qse_htrd_t* script_htrd; qse_htrd_t* script_htrd;
qse_env_t* env; qse_env_t* env;
@ -705,7 +707,7 @@ static int task_init_cgi (
qse_size_t len; qse_size_t len;
const qse_mchar_t* ptr; const qse_mchar_t* ptr;
const qse_htre_hdrval_t* tmp; const qse_htre_hdrval_t* tmp;
cgi = (task_cgi_t*)qse_httpd_gettaskxtn (httpd, task); cgi = (task_cgi_t*)qse_httpd_gettaskxtn (httpd, task);
arg = (task_cgi_arg_t*)task->ctx; arg = (task_cgi_arg_t*)task->ctx;
@ -733,6 +735,12 @@ static int task_init_cgi (
cgi->keepalive = (arg->req->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;
if (arg->fnc.ptr)
{
/* the function pointer is set */
cgi->fnc.ptr = arg->fnc.ptr;
cgi->fnc.ctx = arg->fnc.ctx;
}
content_length = 0; content_length = 0;
if (arg->req->state & QSE_HTRE_DISCARDED) goto done; if (arg->req->state & QSE_HTRE_DISCARDED) goto done;
@ -1432,6 +1440,7 @@ static int task_main_cgi (
cgi_script_htrd_xtn_t* xtn; cgi_script_htrd_xtn_t* xtn;
cgi->script_htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(cgi_script_htrd_xtn_t)); cgi->script_htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(cgi_script_htrd_xtn_t));
if (cgi->script_htrd == QSE_NULL) goto oops; if (cgi->script_htrd == QSE_NULL) goto oops;
xtn = (cgi_script_htrd_xtn_t*) qse_htrd_getxtn (cgi->script_htrd); xtn = (cgi_script_htrd_xtn_t*) qse_htrd_getxtn (cgi->script_htrd);
xtn->cgi = cgi; xtn->cgi = cgi;
xtn->task = task; xtn->task = task;
@ -1460,22 +1469,30 @@ static int task_main_cgi (
if (httpd->opt.trait & QSE_HTTPD_CGINOCLOEXEC) if (httpd->opt.trait & QSE_HTTPD_CGINOCLOEXEC)
pio_options |= QSE_PIO_NOCLOEXEC; pio_options |= QSE_PIO_NOCLOEXEC;
if (cgi->shebang[0] != QSE_MT('\0')) if (cgi->fnc.ptr)
{ {
const qse_mchar_t* tmp[4]; xpath = (qse_mchar_t*)&cgi->fnc;
tmp[0] = cgi->shebang; pio_options |= QSE_PIO_FNCCMD;
tmp[1] = QSE_MT(" "); }
tmp[2] = cgi->path; else
tmp[3] = QSE_NULL; {
xpath = qse_mbsadup (tmp, QSE_NULL, httpd->mmgr); if (cgi->shebang[0] != QSE_MT('\0'))
if (xpath == QSE_NULL) goto oops; {
const qse_mchar_t* tmp[4];
tmp[0] = cgi->shebang;
tmp[1] = QSE_MT(" ");
tmp[2] = cgi->path;
tmp[3] = QSE_NULL;
xpath = qse_mbsadup (tmp, QSE_NULL, httpd->mmgr);
if (xpath == QSE_NULL) goto oops;
}
else xpath = cgi->path;
} }
else xpath = cgi->path;
x = qse_pio_init ( x = qse_pio_init (
&cgi->pio, httpd->mmgr, (const qse_char_t*)xpath, &cgi->pio, httpd->mmgr, (const qse_char_t*)xpath,
cgi->env, pio_options); cgi->env, pio_options);
if (xpath != cgi->path) QSE_MMGR_FREE (httpd->mmgr, xpath); if (xpath != cgi->path && xpath != &cgi->fnc) QSE_MMGR_FREE (httpd->mmgr, xpath);
if (x <= -1) if (x <= -1)
{ {
@ -1539,6 +1556,12 @@ static int task_main_cgi (
} }
} }
} }
else
{
/* no forwarding buffer. the request should not send any contents
* to the cgi script. close the input to the script */
qse_pio_end (&cgi->pio, QSE_PIO_IN);
}
task->main = cgi->nph? task_main_cgi_4_nph: task_main_cgi_2; task->main = cgi->nph? task_main_cgi_4_nph: task_main_cgi_2;
return 1; return 1;
@ -1575,11 +1598,35 @@ qse_httpd_task_t* qse_httpd_entaskcgi (
task_cgi_arg_t arg; task_cgi_arg_t arg;
qse_httpd_rsrc_cgi_t rsrc; qse_httpd_rsrc_cgi_t rsrc;
QSE_MEMSET (&arg, 0, QSE_SIZEOF(arg));
rsrc = *cgi; rsrc = *cgi;
if (rsrc.flags & QSE_HTTPD_RSRC_CGI_FNC)
{
/* rsrc.script must carry a pointer to qse_pio_fnc_t */
if (rsrc.script == QSE_NULL || ((qse_pio_fnc_t*)rsrc.script)->ptr == QSE_NULL)
{
httpd->errnum = QSE_HTTPD_EINVAL;
return QSE_NULL;
}
arg.fnc.ptr = (qse_httpd_fncptr_t)rsrc.path;
arg.fnc.ctx = (void*)rsrc.shebang;
/* reset the script to an empty string for less interference
* with code handling normal script */
rsrc.path = QSE_MT("");
rsrc.shebang = QSE_MT("");
}
else
{
QSE_ASSERT (rsrc.path != QSE_NULL);
if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT("");
}
if (rsrc.script == QSE_NULL) rsrc.script = qse_htre_getqpath(req); if (rsrc.script == QSE_NULL) rsrc.script = qse_htre_getqpath(req);
if (rsrc.suffix == QSE_NULL) rsrc.suffix = QSE_MT(""); if (rsrc.suffix == QSE_NULL) rsrc.suffix = QSE_MT("");
if (rsrc.root == QSE_NULL) rsrc.root = QSE_MT(""); if (rsrc.root == QSE_NULL) rsrc.root = QSE_MT("");
if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT("");
arg.path.ptr = (qse_mchar_t*)rsrc.path; arg.path.ptr = (qse_mchar_t*)rsrc.path;
arg.path.len = qse_mbslen(rsrc.path); arg.path.len = qse_mbslen(rsrc.path);
@ -1589,7 +1636,7 @@ qse_httpd_task_t* qse_httpd_entaskcgi (
arg.suffix.len = qse_mbslen(rsrc.suffix); arg.suffix.len = qse_mbslen(rsrc.suffix);
arg.root.ptr = (qse_mchar_t*)rsrc.root; arg.root.ptr = (qse_mchar_t*)rsrc.root;
arg.root.len = qse_mbslen(rsrc.root); arg.root.len = qse_mbslen(rsrc.root);
arg.nph = rsrc.nph; arg.nph = ((rsrc.flags & QSE_HTTPD_RSRC_CGI_NPH) != 0);
arg.shebang.ptr = (qse_mchar_t*)rsrc.shebang; arg.shebang.ptr = (qse_mchar_t*)rsrc.shebang;
arg.shebang.len = qse_mbslen(rsrc.shebang); arg.shebang.len = qse_mbslen(rsrc.shebang);
arg.req = req; arg.req = req;

View File

@ -1983,7 +1983,7 @@ printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url);
{ {
/* check if it begins with redirection code followed by a colon */ /* check if it begins with redirection code followed by a colon */
int redir_code = 0; int redir_code = 0;
qse_httpd_status_reloc_t reloc; qse_httpd_rsrc_reloc_t reloc;
const qse_mchar_t* nuptr = new_url; const qse_mchar_t* nuptr = new_url;
do do
{ {
@ -1996,11 +1996,14 @@ printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url);
/* no colon is found after digits. it's probably a normal url */ /* no colon is found after digits. it's probably a normal url */
goto normal_url; goto normal_url;
} }
if (redir_code != 301 && redir_code != 302 && redir_code != 307) redir_code = 301; if (redir_code != 301 && redir_code != 302 && redir_code != 303 &&
redir_code != 307 && redir_code != 308) redir_code = 302;
nuptr++; nuptr++;
/* 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.dst = nuptr;
reloc.redir = 0; /* don't want to append extra / */
if (qse_httpd_entask_status ( if (qse_httpd_entask_status (
httpd, proxy->client, proxy->task, redir_code, &reloc, httpd, proxy->client, proxy->task, redir_code, &reloc,

View File

@ -1547,7 +1547,7 @@ static int file_stat (
* for a file. it is mainly used to get a file size and timestamps * for a file. it is mainly used to get a file size and timestamps
* of a regular file. so it should fail for a non-regular file. * of a regular file. so it should fail for a non-regular file.
* note that STAT_REG is passed to stat_file for it */ * note that STAT_REG is passed to stat_file for it */
return stat_file (httpd, path, hst, STAT_REG); return stat_file (httpd, path, hst, STAT_REG);
} }
static int file_purge (qse_httpd_t* httpd, const qse_mchar_t* path) static int file_purge (qse_httpd_t* httpd, const qse_mchar_t* path)
@ -2444,10 +2444,13 @@ static void free_resource (
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.suffix); QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.suffix);
if (target->u.cgi.script != qpath) if (target->u.cgi.script != qpath)
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.script); QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.script);
if (target->u.cgi.path != qpath) if (!(target->u.cgi.flags & QSE_HTTPD_RSRC_CGI_FNC))
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.path); {
if (target->u.cgi.shebang) if (target->u.cgi.path != qpath)
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.shebang); QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.path);
if (target->u.cgi.shebang)
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.shebang);
}
break; break;
@ -2457,8 +2460,8 @@ static void free_resource (
break; break;
case QSE_HTTPD_RSRC_FILE: case QSE_HTTPD_RSRC_FILE:
if (target->u.cgi.path != qpath) if (target->u.file.path != qpath)
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.path); QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.file.path);
break; break;
case QSE_HTTPD_RSRC_RELOC: case QSE_HTTPD_RSRC_RELOC:
@ -2466,11 +2469,6 @@ static void free_resource (
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.reloc.dst); QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.reloc.dst);
break; break;
case QSE_HTTPD_RSRC_REDIR:
if (target->u.redir.dst != qpath)
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.redir.dst);
break;
default: default:
/* nothing to do */ /* nothing to do */
break; break;
@ -2573,22 +2571,19 @@ static int attempt_cgi (
#endif #endif
/* create a relocation resource */ /* create a relocation resource */
QSE_MEMSET (target, 0, QSE_SIZEOF(*target));
target->type = QSE_HTTPD_RSRC_RELOC; target->type = QSE_HTTPD_RSRC_RELOC;
target->u.reloc.dst = merge_paths (httpd, tmp->qpath, tmp->idxfile); target->u.reloc.dst = merge_paths (httpd, tmp->qpath, tmp->idxfile);
if (target->u.reloc.dst == QSE_NULL) goto oops; if (target->u.reloc.dst == QSE_NULL) goto oops;
/* free tmp->xpath here upon success since it's not used for relocation. /* free tmp->xpath here upon success since it's not used for relocation.
* it is freed by the called upon failure so the 'oops' part don't free it */ * upon failure, it is freed by the caller. so the 'oops' part
* of this function doesn't free it. */
QSE_MMGR_FREE (httpd->mmgr, tmp->xpath); QSE_MMGR_FREE (httpd->mmgr, tmp->xpath);
return 1; return 1;
} }
else script = (qse_mchar_t*)tmp->qpath; else script = (qse_mchar_t*)tmp->qpath;
if (cgi.shebang)
{
shebang = qse_mbsdup (cgi.shebang, httpd->mmgr);
if (shebang == QSE_NULL) goto oops;
}
goto bingo; goto bingo;
} }
} }
@ -2619,14 +2614,13 @@ static int attempt_cgi (
*/ */
merge_paths_to_buf (httpd, tmp->root.u.path.val, tmp->qpath_rp, slash - tmp->qpath_rp, tmp->xpath); merge_paths_to_buf (httpd, tmp->root.u.path.val, tmp->qpath_rp, slash - tmp->qpath_rp, tmp->xpath);
xpath_changed = 1; xpath_changed = 1;
stx = stat_file (httpd, tmp->xpath, &st, 0); stx = stat_file (httpd, tmp->xpath, &st, 0);
if (stx <= -1) if (stx <= -1)
{ {
/* stop at the current segment if stating fails. /* instead of stopping here, let's give a non-existent
* if the current semgment can't be stat-ed, it's not likely that * segment to be a virtual cgi script(function pointer). */
* the next segment can be successfully stat-ed */ st.isdir = 0;
break;
} }
if (!st.isdir) if (!st.isdir)
@ -2636,9 +2630,16 @@ static int attempt_cgi (
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo)); QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
qinfo.req = req; qinfo.req = req;
qinfo.xpath = tmp->xpath; qinfo.xpath = tmp->xpath;
qinfo.xpath_nx = (stx <= -1);
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi) if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi)
{ {
if (cgi.fncptr == QSE_NULL && stx <= -1)
{
/* normal cgi script must exist. */
break;
}
/* the script name is composed of the orginal query path. /* the script name is composed of the orginal query path.
* the pointer held in 'slash' is valid for tmp->qpath as * the pointer held in 'slash' is valid for tmp->qpath as
* tmp->qpath_rp is at most the tail part of tmp->qpath. */ * tmp->qpath_rp is at most the tail part of tmp->qpath. */
@ -2646,23 +2647,57 @@ static int attempt_cgi (
suffix = qse_mbsdup (slash, httpd->mmgr); suffix = qse_mbsdup (slash, httpd->mmgr);
if (!script || !suffix) goto oops; if (!script || !suffix) goto oops;
if (cgi.shebang)
{
shebang = qse_mbsdup (cgi.shebang, httpd->mmgr);
if (shebang == QSE_NULL) goto oops;
}
goto bingo; goto bingo;
} }
} }
if (stx <= -1)
{
/* stop at the current segment if stat() fails.
* if the current segment can't be stat-ed, it's not likely that
* the next segment can be stat-ed successfully */
break;
}
} }
ptr = slash + 1; ptr = slash + 1;
} }
else else
{ {
/* no more slash is found. the last segement doesn't have to be checked /* no more slash is found. this is the last segment.
* here since it's attempted by the caller. */ * the caller has called stat() against the last segment
* before having called this function. so it's known
* that the path disn't exist.
*
* however, a virtual cgi script may not exist. a check
* for it is still required here */
qse_httpd_serverstd_query_info_t qinfo;
if (xpath_changed)
{
/* restore the tmp->xpath to the original value by
* combining the full path with the document root. */
merge_paths_to_buf (httpd, tmp->root.u.path.val, tmp->qpath_rp, (qse_size_t)-1, tmp->xpath);
xpath_changed = 0;
}
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
qinfo.req = req;
qinfo.xpath = tmp->xpath;
qinfo.xpath_nx = 1;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi && cgi.fncptr)
{
/* virtual cgi script */
script = qse_mbsdup (tmp->qpath, httpd->mmgr);
if (!script) goto oops;
suffix = QSE_NULL;
goto bingo;
}
/* not a virtual cgi script. just break */
break; break;
} }
} }
@ -2675,12 +2710,32 @@ static int attempt_cgi (
bingo: bingo:
target->type = QSE_HTTPD_RSRC_CGI; target->type = QSE_HTTPD_RSRC_CGI;
target->u.cgi.nph = cgi.nph; target->u.cgi.flags = 0;
target->u.cgi.path = tmp->xpath; if (cgi.nph) target->u.cgi.flags |= QSE_HTTPD_RSRC_CGI_NPH;
if (cgi.fncptr)
{
/* the type casting here is guly */
target->u.cgi.path = (qse_mchar_t*)cgi.fncptr;
target->u.cgi.shebang = cgi.shebang;
target->u.cgi.flags |= QSE_HTTPD_RSRC_CGI_FNC;
}
else
{
if (cgi.shebang)
{
shebang = qse_mbsdup (cgi.shebang, httpd->mmgr);
if (shebang == QSE_NULL) goto oops;
}
target->u.cgi.path = tmp->xpath;
target->u.cgi.shebang = shebang;
}
target->u.cgi.script = script; target->u.cgi.script = script;
target->u.cgi.suffix = suffix; target->u.cgi.suffix = suffix;
target->u.cgi.root = tmp->root.u.path.val; target->u.cgi.root = tmp->root.u.path.val;
target->u.cgi.shebang = shebang;
return 1; return 1;
oops: oops:
@ -2739,6 +2794,13 @@ static int make_resource (
/* handle the request locally */ /* handle the request locally */
QSE_ASSERT (tmp.root.type == QSE_HTTPD_SERVERSTD_ROOT_PATH); QSE_ASSERT (tmp.root.type == QSE_HTTPD_SERVERSTD_ROOT_PATH);
/*****************************************************************************
* BUG BUG BUG !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
* TODO: calling the realm query here is wrong especially if the prefix path is resolved to a cgi.
* for example, /abc/def/test.cgi/x/y/z,
* when this function queries for REALM, it's not known that /abc/def/test.cgi is a cgi script.
*****************************************************************************/
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_REALM, &qinfo, &tmp.realm) <= -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) server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_INDEX, &qinfo, &tmp.index) <= -1)
{ {
@ -2877,7 +2939,7 @@ auth_ok:
tmp.xpath = tpath; tmp.xpath = tpath;
tmp.idxfile = ptr; tmp.idxfile = ptr;
goto attempt_file; goto attempt_file;
} }
QSE_MMGR_FREE (httpd->mmgr, tpath); QSE_MMGR_FREE (httpd->mmgr, tpath);
} }
@ -2898,8 +2960,9 @@ auth_ok:
{ {
/* the query path doesn't end with a slash. so redirect it */ /* the query path doesn't end with a slash. so redirect it */
qse_htre_discardcontent (req); qse_htre_discardcontent (req);
target->type = QSE_HTTPD_RSRC_REDIR; target->type = QSE_HTTPD_RSRC_RELOC;
target->u.redir.dst = tmp.qpath; target->u.reloc.flags = QSE_HTTPD_RSRC_RELOC_APPENDSLASH | QSE_HTTPD_RSRC_RELOC_PERMANENT;
target->u.reloc.dst = tmp.qpath;
/* free xpath since it won't be used */ /* free xpath since it won't be used */
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath); QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
} }
@ -2929,7 +2992,16 @@ auth_ok:
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath); QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
return -1; return -1;
} }
if (n >= 1) return 0; if (n >= 1)
{
if (target->u.cgi.flags & QSE_HTTPD_RSRC_CGI_FNC)
{
/* tmp.xpath is not set to target->u.cgi.path when
* this flag is set. it must be deallocated */
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
}
return 0;
}
qinfo.xpath = tmp.xpath; qinfo.xpath = tmp.xpath;
@ -3015,8 +3087,8 @@ struct cgi_tab_t
}; };
static struct cgi_tab_t cgitab[] = static struct cgi_tab_t cgitab[] =
{ {
{ QSE_MT(".cgi"), { 1, 0, QSE_NULL } }, { QSE_MT(".cgi"), { 1, 0, QSE_NULL, QSE_NULL } },
{ QSE_MT(".nph"), { 1, 1, QSE_NULL } }, { QSE_MT(".nph"), { 1, 1, QSE_NULL, QSE_NULL } },
}; };
static int query_server ( static int query_server (
@ -3071,12 +3143,18 @@ static int query_server (
case QSE_HTTPD_SERVERSTD_CGI: case QSE_HTTPD_SERVERSTD_CGI:
{ {
qse_httpd_serverstd_cgi_t* cgi = (qse_httpd_serverstd_cgi_t*)result; qse_httpd_serverstd_cgi_t* cgi = (qse_httpd_serverstd_cgi_t*)result;
for (i = 0; i < QSE_COUNTOF(cgitab); i++)
if (!qinfo->xpath_nx)
{ {
if (qse_mbsend (qinfo->xpath, cgitab[i].suffix)) /* this standard implementation supports a normal cgi script only */
for (i = 0; i < QSE_COUNTOF(cgitab); i++)
{ {
QSE_MEMCPY (cgi, &cgitab[i].cgi, QSE_SIZEOF(*cgi)); if (qse_mbsend (qinfo->xpath, cgitab[i].suffix))
return 0; {
QSE_MEMCPY (cgi, &cgitab[i].cgi, QSE_SIZEOF(*cgi));
return 0;
}
} }
} }

View File

@ -178,14 +178,16 @@ qse_httpd_task_t* qse_httpd_entask_status (
msg = qse_httpstatustombs (code); msg = qse_httpstatustombs (code);
switch (code) switch (code)
{ {
case 301: case 301: /* Moved Permanently */
case 302: case 302: /* Found */
case 307: case 303: /* See Other (since HTTP/1.1) */
case 307: /* Temporary Redirect (since HTTP/1.1) */
case 308: /* Permanent Redirect (Experimental RFC; RFC 7238) */
{ {
qse_httpd_status_reloc_t* reloc; qse_httpd_rsrc_reloc_t* reloc;
reloc = (qse_httpd_status_reloc_t*)extra; reloc = (qse_httpd_rsrc_reloc_t*)extra;
extrapre = QSE_MT("Location: "); extrapre = QSE_MT("Location: ");
extrapst = reloc->redir? QSE_MT("/\r\n"): QSE_MT("\r\n"); extrapst = (reloc->flags & QSE_HTTPD_RSRC_RELOC_APPENDSLASH)? QSE_MT("/\r\n"): QSE_MT("\r\n");
extraval = reloc->dst; extraval = reloc->dst;
break; break;
} }
@ -276,31 +278,22 @@ qse_httpd_task_t* qse_httpd_entaskauth (
qse_httpd_task_t* qse_httpd_entaskreloc ( qse_httpd_task_t* qse_httpd_entaskreloc (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_t* httpd, qse_httpd_client_t* client,
qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req) qse_httpd_task_t* pred, const qse_httpd_rsrc_reloc_t* reloc, qse_htre_t* req)
{ {
qse_httpd_status_reloc_t reloc; int code;
reloc.dst = dst; if (reloc->flags & QSE_HTTPD_RSRC_RELOC_KEEPMETHOD)
reloc.redir = 0; {
code = (reloc->flags & QSE_HTTPD_RSRC_RELOC_PERMANENT)? 308: 307;
}
else
{
/* NOTE: 302 can be 303 for HTTP/1.1 */
code = (reloc->flags & QSE_HTTPD_RSRC_RELOC_PERMANENT)? 301: 302;
}
return qse_httpd_entask_status ( return qse_httpd_entask_status (
httpd, client, pred, 301, (void*)&reloc, httpd, client, pred, code, (void*)reloc,
qse_htre_getqmethodtype(req),
qse_htre_getversion(req),
(req->flags & QSE_HTRE_ATTR_KEEPALIVE));
}
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)
{
qse_httpd_status_reloc_t reloc;
reloc.dst = dst;
reloc.redir = 1;
return qse_httpd_entask_status (
httpd, client, pred, 301, (void*)&reloc,
qse_htre_getqmethodtype(req), qse_htre_getqmethodtype(req),
qse_htre_getversion(req), qse_htre_getversion(req),
(req->flags & QSE_HTRE_ATTR_KEEPALIVE)); (req->flags & QSE_HTRE_ATTR_KEEPALIVE));
@ -403,11 +396,7 @@ qse_httpd_task_t* qse_httpd_entaskrsrc (
break; break;
case QSE_HTTPD_RSRC_RELOC: case QSE_HTTPD_RSRC_RELOC:
task = qse_httpd_entaskreloc (httpd, client, pred, rsrc->u.reloc.dst, req); task = qse_httpd_entaskreloc (httpd, client, pred, &rsrc->u.reloc, req);
break;
case QSE_HTTPD_RSRC_REDIR:
task = qse_httpd_entaskredir (httpd, client, pred, rsrc->u.redir.dst, req);
break; break;
case QSE_HTTPD_RSRC_TEXT: case QSE_HTTPD_RSRC_TEXT:

View File

@ -100,13 +100,6 @@ struct qse_httpd_real_task_t
qse_httpd_real_task_t* next; 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_SEND_SIZE 4096
#define MAX_RECV_SIZE 4096 #define MAX_RECV_SIZE 4096