一、如何响应HTTP请求
websPump中若前面两步解析请求行请求头成功,wp->state置为READY时,调用websRunRequest响应请求。
此时,websRunRequest中将wp->state置为RUNNING,之后调用route对应的service回调函数,也就是websDefineHandler中定义的各种handler。
PUBLIC void websPump(Webs *wp)//如何判断不同类型,去调用不同类型的handler呢。
{
bool canProceed;
for (canProceed = 1; canProceed; ) {
switch (wp->state) {
case WEBS_BEGIN://最初都是BEGIN状态
canProceed = parseIncoming(wp);
break;
case WEBS_CONTENT:
canProceed = processContent(wp);
break;
case WEBS_READY:
if (!websRunRequest(wp)) {
/* Reroute if the handler re-wrote the request */
websRouteRequest(wp);
wp->state = WEBS_READY;
canProceed = 1;
continue;
}
canProceed = (wp->state != WEBS_RUNNING);
break;
case WEBS_RUNNING:
/* Nothing to do until websDone is called */
return;
case WEBS_COMPLETE:
canProceed = complete(wp, 1);
break;
}
}
}
二、响应HTTP请求handler的类型
根据route中的定义,响应类型具体有actionHandler(post请求),jstHandler(动态页面),fileHandler(默认静态页面),cgiHandler(调用外部程序)等。在这些handler中将数据返回给客户端。extensions就是后缀名,如果请求的文件后缀是.jst就会调用jstHandler。
2.1 actionHandler
actionHandler比较简单,就是通过hash表,将actionName与对应websDefineAction定义的函数回调匹配上,去回调自己定义的回调函数即可,入参wp。用户定义action的行为中,要自己返回客户端action的结果。
/*
Process an action request. Returns 1 always to indicate it handled the URL
Return true to indicate the request was handled, even for errors.
*/
static bool actionHandler(Webs *wp)
{
WebsKey *sp;
char actionBuf[ME_GOAHEAD_LIMIT_URI + 1];
char *cp, *actionName;
WebsAction fn;
assert(websValid(wp));
assert(actionTable >= 0);
/*
Extract the action name
*/
scopy(actionBuf, sizeof(actionBuf), wp->path);
if ((actionName = strchr(&actionBuf[1], '/')) == NULL) {
websError(wp, HTTP_CODE_NOT_FOUND, "Missing action name");
return 1;
}
actionName++;
if ((cp = strchr(actionName, '/')) != NULL) {
*cp = '\0';
}
/*
Lookup the C action function first and then try tcl (no javascript support yet).
*/
sp = hashLookup(actionTable, actionName);
if (sp == NULL) {
websError(wp, HTTP_CODE_NOT_FOUND, "Action %s is not defined", actionName);
} else {
fn = (WebsAction) sp->content.value.symbol;
assert(fn);
if (fn) {
#if ME_GOAHEAD_LEGACY
(*((WebsProc) fn))((void*) wp, actionName, wp->query);
#else
(*fn)((void*) wp);
#endif
}
}
return 1;
}
2.2 jstHandler
jstHandler处理流程是先将page读取到内存中,从第一个字节开始,依次发送给客户端,遇到<%
%>之后,回调绑定的C函数,将函数返回结果替换<% %>返回客户端,直到页面的所有内容都发完。
这种技术可以使得页面可以动态根据服务器执行C函数的结果来响应内容。也就是动态页面。
/*
Process requests and expand all scripting commands. We read the entire web page into memory and then process. If
you have really big documents, it is better to make them plain HTML files rather than Javascript web pages.
Return true to indicate the request was handled, even for errors.
*/
//动态页面响应肯定比静态页面要慢
static bool jstHandler(Webs *wp)
{
WebsFileInfo sbuf;
char *lang, *token, *result, *ep, *cp, *buf, *nextp, *last;
ssize len;
int rc, jid;
assert(websValid(wp));
assert(wp->filename && *wp->filename);
assert(wp->ext && *wp->ext);
buf = 0;
if ((jid = jsOpenEngine(wp->vars, websJstFunctions)) < 0) {
websError(wp, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot create JavaScript engine");
goto done;
}
jsSetUserHandle(jid, wp);
if (websPageStat(wp, &sbuf) < 0) {
websError(wp, HTTP_CODE_NOT_FOUND, "Cannot stat %s", wp->filename);
goto done;
}
if (websPageOpen(wp, O_RDONLY | O_BINARY, 0666) < 0) {
websError(wp, HTTP_CODE_NOT_FOUND