2021SC@SDUSC BRPC源码分析(十)HTTP
enum HeaderIndexPolicy {
HPACK_INDEX_HEADER = 0,
HPACK_NOT_INDEX_HEADER = 1,
HPACK_NEVER_INDEX_HEADER = 2,
};
struct HPackOptions {
HeaderIndexPolicy index_policy;
bool encode_name;
bool encode_value;
HPackOptions();
};
class HPacker : public Describable {
public:
struct Header {
std::string name;
std::string value;
Header() {}
explicit Header(const std::string& name2) : name(name2) {}
Header(const std::string& name2, const std::string& value2)
: name(name2), value(value2) {}
};
HPacker();
~HPacker();
int Init(size_t max_table_size = H2Settings::DEFAULT_HEADER_TABLE_SIZE);
void Encode(butil::IOBufAppender* out, const Header& header,
const HPackOptions& options);
void Encode(butil::IOBufAppender* out, const Header& header)
{ return Encode(out, header, HPackOptions()); }
ssize_t Decode(butil::IOBuf* source, Header* h);
ssize_t Decode(butil::IOBufBytesIterator& source, Header* h);
void Describe(std::ostream& os, const DescribeOptions&) const;
private:
DISALLOW_COPY_AND_ASSIGN(HPacker);
int FindHeaderFromIndexTable(const Header& h) const;
int FindNameFromIndexTable(const std::string& name) const;
const Header* HeaderAt(int index) const;
ssize_t DecodeWithKnownPrefix(
butil::IOBufBytesIterator& iter, Header* h, uint8_t prefix_size) const;
IndexTable* _encode_table;
IndexTable* _decode_table;
};
// Lowercase the input string, a fast implementation.
void tolower(std::string* s);
HPACK_INDEX_HEADER
附加此HPACK_INDEX_HEADER
警告解码器动态表。如果给定的头匹配其中一个索引头,该头将被索引替换。如果不是,将HPACK_INDEX_HEADER
附加到解码器动态表中。HPACK_NOT_INDEX_HEADER
附加HPACK_NOT_INDEX_HEADER
,不警告解码器动态表。如果给定的头匹配其中一个索引头,该头将被索引替换。如果没有,直接追加该报头 WITHOUT 对解码器动态表进行任何修改。HPACK_NEVER_INDEX_HEADER
它将永远不会被索引替换。- encode_name如果为true, name字符串将被编码为huffman编码。默认值:false。
- encode_value如果为true, value字符串将被编码为huffman编码。默认值:false。
- Init(size_t max_table_size = H2Settings::DEFAULT_HEADER_TABLE_SIZE)初始化实例。成功返回0,否则返回-1。
- Encode()编码头并将编码后的缓冲区附加到|out|,成功返回true。
- Decode(butil::IOBuf* source, Header* h)尝试解码最多一个Header来源和擦除相应的缓冲区。返回:
— 成功解码报头时的$解码缓冲区的大小
— 当源未完成时为0
— -1时,源是畸形的 - Describe(std::ostream& os, const DescribeOptions&)与前面的Decode(butil::IOBuf* source, Header* h)类似,只是源来自IOBufBytesIterator。
#define HTTP_PARSER_VERSION_MAJOR 2
#define HTTP_PARSER_VERSION_MINOR 3
#define HTTP_PARSER_VERSION_PATCH 0
#ifndef BRPC_HTTP_PARSER_STRICT
# define BRPC_HTTP_PARSER_STRICT 1
#endif
#ifndef BRPC_HTTP_MAX_HEADER_SIZE
# define BRPC_HTTP_MAX_HEADER_SIZE (80*1024)
#endif
namespace brpc {
struct http_parser;
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
typedef int (*http_cb) (http_parser*);
#define HTTP_METHOD_MAP(XX) \
……
略
……
enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
enum http_parser_flags
{ F_CHUNKED = 1 << 0
, F_CONNECTION_KEEP_ALIVE = 1 << 1
, F_CONNECTION_CLOSE = 1 << 2
, F_TRAILING = 1 << 3
, F_UPGRADE = 1 << 4
, F_SKIPBODY = 1 << 5
};
#define HTTP_ERRNO_MAP(XX) \
……
略
……
#define HTTP_ERRNO_GEN(n, s) HPE_##n,
enum http_errno {
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
};
#undef HTTP_ERRNO_GEN
#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
struct http_parser {
……
略
……
/** PUBLIC **/
void *data;
};
struct http_parser_settings {
……
略
……
};
enum http_parser_url_fields
……
略
……
};
struct http_parser_url {
uint16_t field_set; /* Bitmask of (1 << UF_*) values */
uint16_t port; /* Converted UF_PORT string */
struct {
uint16_t off; /* Offset into buffer in which field starts */
uint16_t len; /* Length of run in buffer */
} field_data[UF_MAX];
};
unsigned long http_parser_version(void);
void http_parser_init(http_parser *parser, enum http_parser_type type);
size_t http_parser_execute(http_parser *parser,
const http_parser_settings *settings,
const char *data,
size_t len);
int http_should_keep_alive(const http_parser *parser);
const char *http_method_str(enum http_method m);
const char *http_errno_name(enum http_errno err);
const char *http_errno_description(enum http_errno err);
int http_parser_parse_url(const char *buf, size_t buflen,
int is_connect,
struct http_parser_url *u);
void http_parser_pause(http_parser *parser, int paused);
int http_body_is_final(const http_parser *parser);
const char* http_parser_type_name(enum http_parser_type type);
const char* http_parser_state_name(unsigned int state);
const char* http_parser_header_state_name(unsigned int header_state);
}
- 更改这个http_parser.h,同时也是在更新在Makefile中的SONAME。
- 使用-DBRPC_HTTP_PARSER_STRICT=0编译可以减少检查,但运行速度更快。
- 允许的最大标题大小。如果宏在包含此头文件之前没有定义,则使用默认值。要更改最大头大小,在构建环境中定义宏(例如-DBRPC_HTTP_MAX_HEADER_SIZE=)。将宏定义为一个非常大的数字以删除头文件大小的有效限制。(例如-DBRPC_HTTP_MAX_HEADER_SIZE = 0 x7fffffff)
- Callback函数返回非零来表示错误。然后解析器将停止执行。唯一的例外是on_headers_complete。在HTTP_RESPONSE解析器中,从on_headers_complete返回’1’将告诉解析器它不应该期望获得body。当接收一个HEAD请求的响应时使用,该请求可能包含“Content-Length”或“Transfer-Encoding: chunked”头,表明body的存在。
http_data_cb
不返回数据块。对于每个字符串,它将被任意多次调用。例如,可能会得到10个“on_url”的callback,每个只提供几个字符的数据。http_parser_flags
http_parser的标志值。标志字段。HTTP_ERRNO_MAP(XX)
映射errno相关的常量提供的参数应该是一个带有两个参数的宏。HTTP_ERRNO_GEN(n, s)
为上面的每个errno值定义HPE_*值。HTTP_PARSER_ERRNO(p)
从http_parser中获取http_errno值。- data一个指向connection或socket对象的指针。
http_parser_url
http_parser_parse_url()的结果结构。调用者应该索引到field_data[]与UF_值iff field_set有相关(1 << UF_)位设置。作为一个clients(因为可能有填充剩余),clients转换任何端口到uint16_t。http_parser_version(void)
返回库版本。位16-23包含主版本号,位8-15包含次要版本号,位0-7包含补丁级别。
-http_parser_execute
执行解析器。返回已解析字节数。设置parser->http_errno
错误。http_should_keep_alive
如果在on_headers_complete或on_message_complete Callback中http_should_keep_alive()返回0,那么这应该是连接的最后一条消息。如果是Server,响应"Connection: close"头。如果是Client,关闭连接。http_method_str(enum http_method m);
返回HTTP方法的字符串版本。http_errno_name(enum http_errno err);
返回给定错误的字符串名称。http_errno_description(enum http_errno err);
返回给定错误的字符串描述。http_parser_parse_url(const char *buf, size_t buflen,int is_connect,struct http_parser_url *u);
解析URL;失败时返回非零。http_parser_pause(http_parser *parser, int paused);
解析URL;失败时返回非零。http_body_is_final(const http_parser *parser);
检查这是否是主体的最终块。http_parser_type_name(enum http_parser_type type);
返回给定类型的字符串名称。http_parser_state_name(unsigned int state);
返回给定状态的字符串名称。