1HTTP解析器No.js使用Node.js的HTTP解析器llhttp实现HTTP协议解析。llhttp负责解析HTTP消息。No.js要做的就是保存解析结果,封装具体的能力。看看No.js是如何包装llhttp的。classHTTP_Parser{public:HTTP_Parser(llhttp_typetype,parser_callbackcallbacks={}){llhttp_init(&parser,type,&HTTP_Parser::settings);//setdataafterllhttp_init,becausellhttp_initwillcallmemsettofillzerotomemoryparser.data=this;memset((void*)&callback,0,sizeof(callback));callback=callbacks;}inton_message_begin(llhttp_t*parser);inton_status(llhttp_t*parser,constchar*at,size_tlength);inton_url(llhttp_t*parser,constchar*at,size_tlength);inton_header_field(llhttp_t*parser,constchar*at,size_tlength);inton_header_value(llhttp_t*parser,constchar*at,size_tlength);inton_headers_complete(llhttp_t*parser);inton_body(llhttp_t*parser,constchar*at,size_tlength);inton_message_complete(llhttp_t*parser);intparse(constchar*data,intlen);voidprint();private:unsignedcharmajor_version;unsignedcharminor_version;unsignedcharupgrade;unsignedcharkeepalive;time_tparse_start_time;time_theader_end_time;time_tmessage_end_time;stringurl;stringstatus;vector键;向量<字符串>值;弦体;llhttp_tparser;parser_callback回调;静态llhttp_settings_tsettings;};将llhttp的解析结果存储在HTTP_Parser对象中。把HTTP_Parser类的成员函数转成c函数作为llhttp的回调是很麻烦的。问题是llhttp执行回调时如何找到对应的HTTP_Parser对象。例如llhttp的on_message_begin回调格式为typedefint(*llhttp_cb)(llhttp_t*);我们看到回调中只有llhttp相关的数据结构,并不能获取到HTTP_Parser对象。最后,我们发现llhttp提供了数据字段关联上下文。所以llhttp和HTTP_Parser的context是在初始化HTTP_Parser的时候关联的。HTTP_Parser(llhttp_typetype,parser_callbackcallbacks={}){llhttp_init(&parser,type,&HTTP_Parser::settings);parser.data=this;}我们可以在llhttp回调中通过data字段获取到HTTP_Parser对象。下面是所有钩子的实现。llhttp_settings_tNo::HTTP::HTTP_Parser::settings={[](llhttp_t*parser){return((HTTP_Parser*)parser->data)->on_message_begin(parser);},[](llhttp_t*parser,constchar*data,size_tlen){return((HTTP_Parser*)parser->data)->on_url(parser,data,len);},[](llhttp_t*parser,constchar*data,size_tlen){return((HTTP_Parser*)parser->data)->on_status(parser,data,len);},[](llhttp_t*parser,constchar*data,size_tlen){return((HTTP_Parser*)parser->data)->on_header_field(parser,data,len);},[](llhttp_t*parser,constchar*data,size_tlen){return((HTTP_Parser*)parser->data)->on_header_value(parser,data,len);},[](llhttp_t*parser){return((HTTP_Parser*)parser->data)->on_headers_complete(parser);},[](llhttp_t*parser,constchar*data,size_tlen){return((HTTP_Parser*)parser->data)->on_body(解析器,data,len);},[](llhttp_t*parser){return((HTTP_Parser*)parser->data)->on_message_complete(parser);}};这样就完成了llhttp和No.js的关联。解析完HTTP协议,最后还是要回调No.js的JS层。HTTP_Parser目前支持三种回调。structparser_callback{void*data;p_on_headers_completeon_headers_complete;p_on_bodyon_body;p_on_body_completeon_body_complete;};2HTTPC++模块完成对llhttp的封装后,需要将此能力暴露给JS层。看看C++模块到定义。classParser:publicBaseObject{public:Parser(Environment*env,Local