goahead源码解析(三) 响应HTTP请求

本文深入解析Goahead服务器响应HTTP请求的过程,重点探讨了actionHandler、jstHandler、fileHandler和cgiHandler四种类型的handler。actionHandler通过hash表匹配并执行回调;jstHandler实现动态页面,结合C函数生成动态内容;fileHandler则处理静态文件传输;而cgiHandler涉及调用外部程序,但实际应用中可能较少使用。
摘要由CSDN通过智能技术生成

一、如何响应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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

同人与野

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值