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
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
http.c是goahead web服务器的核心文件之一,主要负责处理HTTP请求响应。以下是http.c文件的解析: 1. 首先,http.c文件包含了一些必要的头文件,例如<sys/stat.h>和<fcntl.h>等。这些头文件提供了一些系统级别的函数和结构体。 2. 接着,http.c中定义了一些常量、宏和全局变量。例如,HTTP请求方法的枚举类型、HTTP响应状态码的宏定义、HTTP请求头部的结构体等。 3. 然后,http.c中定义了一些函数,这些函数负责处理HTTP请求响应。例如,processHttpRequest()函数用于处理HTTP请求,sendHttpResponse()函数用于发送HTTP响应,parseFirstLine()函数用于解析HTTP请求的第一行等。 4. 在processHttpRequest()函数中,首先解析HTTP请求的第一行,然后解析HTTP请求头部,最后根据HTTP请求方法调用不同的处理函数。例如,如果是GET方法,就调用processGetRequest()函数处理请求。 5. 在processGetRequest()函数中,首先解析HTTP请求的路径,然后判断该路径是否合法,最后打开文件并发送HTTP响应。如果文件无法打开或者发送失败,就发送相应的错误响应。 6. 在sendHttpResponse()函数中,首先根据HTTP响应状态码设置响应头部,然后将响应头部和主体发送给客户端。 7. 最后,在main()函数中,启动goahead web服务器,并监听指定的端口号,等待客户端连接。 以上就是http.c文件的解析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

同人与野

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

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

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

打赏作者

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

抵扣说明:

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

余额充值