轻量web服务器开发日记06-request结构体的实现

request结构体在antweb服务器中的作用是存放请求报文内容的,而其请求报文主要包含起始行的http版本号、url和请求方法,首部的host、connection、accept等等,还有主体内容(若请求方法是post)。
antweb服务器在分析请求报文进行响应处理时,需要从request结构体中获取每一部分的信息进行分析后得出响应报文,然后构建出response结构体来存放响应报文。
而antweb中的request结构体中存放的请求报文的首部并不是http所有的首部,我只是挑了一些首部进行存放,保证服务器基本能运行,若读者想增加更多的首部项只需要修改该结构体就可以了。
(1)request结构体:

typedef struct {
    //请求报文
    bufstr *request_content;
    //请求报文的起始行
    bufstr *request_line;
    //请求报文的首部
    bufstr *request_head;
    //是否有请求主体
    int have_body;
    //请求报文的主体部分
    bufstr *request_body;
    //是否主体数据接收完整
    int read_all;
    //请求报文的方法
    bufstr *line_method;
    //请求报文起始行的url
    bufstr *line_url;
    //请求报文的http版本号
    bufstr *line_version;
    //请求报文的首部host项的值
    bufstr *head_host;
    //请求报文的首部Connection项的值
    bufstr *head_connection;
    //请求报文的首部Content-Length项(若有主体)的值
    bufstr *head_content_length;
    //请求报文的首部accept项的值
    bufstr *head_accept;
} request;

在下面操作函数是对请求报文进行存放、分解、分析操作,而用bufstr结构体(日记03介绍)进行存放,因为request如上面所示,存放请求报文的各部分是用bufstr结构体。
(2)从某个连接套接字中获取请求报文

bufstr *request_read(mempool *mpool,int fd)
{
    int n,mbsize,flag=0;
    memblock *mblock = NULL;
    char *swap = NULL;
    bufstr *src = bufstr_init(mpool);
    mbsize = MBSIZE;
    mblock = mempool_take_mblocks(mpool,1);
    swap = (char*)mblock->memptr;
    while((n = recv(fd,swap,mbsize,MSG_DONTWAIT))>0)
    {
        flag = 1 ;
        bufstr_append_string_len(mpool,src,swap,n); 
    }
    if(!flag)
    {
        return NULL;
    }
    mempool_put_mblocks(mpool,mblock);
    return src;
}

(3)从请求报文中获取起始行:

bufstr *request_read(mempool *mpool,int fd)
{
    int n,mbsize,flag=0;
    memblock *mblock = NULL;
    char *swap = NULL;
    bufstr *src = bufstr_init(mpool);
    mbsize = MBSIZE;
    mblock = mempool_take_mblocks(mpool,1);
    swap = (char*)mblock->memptr;
    while((n = recv(fd,swap,mbsize,MSG_DONTWAIT))>0)
    {
        flag = 1 ;
        bufstr_append_string_len(mpool,src,swap,n); 
    }
    if(!flag)
    {
        return NULL;
    }
    mempool_put_mblocks(mpool,mblock);
    return src;
}

(4)从请求报文中获取首部(不是http全部首部,我只获取部分首部)并转换成小写字母:

bufstr *get_header_lower(mempool *mpool, bufstr *src)
{
    char *start = NULL, *end = NULL,*http_message = NULL;
    bufstr *header = NULL;
    if(!src || !mpool)
    {
        return NULL;
    }
    if(!src->used)
    {
        return NULL;
    }
    http_message = read_string_bufstr(src);
    start = strstr(http_message,"\n");
    if(start == NULL || strlen(http_message) == start - http_message + 1)
    {
        return NULL;
    }
    start ++;
    header = bufstr_init(mpool);
    end = strstr(start,"\r\n\r\n");
    if(end != NULL)
    {
        end += 2;
        *end = '/0';
    }
    else 
    {
        end = strstr(start,"\n\n");
        if(end != NULL)
        {
            end += 1;
            *end = '/0';
        }
        else
        {
            end = http_message + strlen(http_message);
        }
    }
    string_to_lower(start);
    bufstr_copy_string_len(mpool,header,start,end - start);
    free(http_message);
    return header;
}

(5)若请求方法是post或其他含有主体的请求报文,则从请求报文中获取主体:

bufstr *get_request_body(mempool *mpool,bufstr *src,int *content_length)
{
    char *temp = NULL,*http_message = NULL;
    bufstr *body = NULL;
    if(!mpool || !src)
    {
        return NULL;
    }
    if(!src->used)
    {
        return NULL;
    }
    http_message = read_string_bufstr(src);

    temp = strstr(http_message,"\r\n\r\n");
    if(temp != NULL && strlen(http_message) > temp - http_message + 4)
    {
        temp += 4;
        body = bufstr_init(mpool);
        bufstr_copy_string_len(mpool,body,temp,http_message + strlen(http_message) - temp);
        return body;
    }
    temp = strstr(http_message,"\n\n");
    if(temp == NULL || strlen(http_message) == temp - http_message + 2)
    {
        return NULL;
    }
    temp += 2;
    body = bufstr_init(mpool);
    bufstr_copy_string_len(mpool,body,temp,http_message + strlen(http_message) - temp);
    if(content_length != NULL)
    {
        *content_length = strlen(temp);
    }
    free(http_message);
    return body;
}

下面是其他的操作函数,若读者需要了解某个函数时可以评论告诉我,我看见就更新内容:

//创建一个request结构体并通过函数返回
request *request_init();
//释放resquest结构体rq 
void request_free(mempool *mpool,request *rq);
//读取连接的请求报文存入到src中
bufstr *request_read(mempool *mpool,int fd);
//获取http起始行,以bufstr指针返回
bufstr *get_start_line(mempool *mpool, bufstr *src);
//获取http首部(字母为小写),以bufstr指针返回
bufstr *get_header_lower(mempool *mpool, bufstr *src);
//获取http主体部分,以bufstr指针返回,其长度以content_length指针返回
bufstr *get_request_body(mempool *mpool,bufstr *src,int *content_length);
//获取请求起始行的方法
bufstr *get_start_line_method(mempool *mpool, bufstr *src);
//获取请求起始行的url
bufstr *get_start_line_url(mempool *mpool, bufstr *src);
//获取请求起始行url的原始路径
bufstr *get_raw_url(mempool *mpool, bufstr *url);
//获取请求起始行的版本号
bufstr *get_start_line_version(mempool *mpool, bufstr *src);
//获取指定首部字段(小写)的value值
bufstr *get_header_value(mempool *mpool, bufstr *head, char *key);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值