访问http:h2
了解如何访问Http2。
例子
示例/http_c++
大约h2
brpc将HTTP/2协议命名为“h2”,无论是否加密。然而,不带SSL的HTTP/2连接显示在官方名称为“h2c”的/connections上,而带SSL的连接显示为“h2”。
brpc中http和h2的API基本相同。在没有明确声明的情况下,提到的http特性也适用于h2。
创建频道
为了使用brpc::频道
访问http/h2服务,ChannelOptions.protocol(通道选项协议)
必须设置为协议_HTTP
或协议_H2
。
一旦设置了协议频道::初始化
可以是任何有效的URL。注释:Init()只使用URL内的主机和端口,其他部分被丢弃。允许完整的URL只会让用户省去额外的解析代码。
brpc公司::频道选项 选项;
选项。协议 = brpc公司::协议_HTTP; //或brpc::PROTOCOL_H2如果 (通道。初始化(“www.baidu.com” /*任何url*/, &选项) != 0) {
日志(错误) << “无法初始化通道”;
返回 -1;
}
http/h2通道还支持BNS地址或其他命名服务。
GET(获取)
brpc公司::控制器 碳纳米管;
碳纳米管。http_请求().乌里() = “www.baidu.com/index.html”; //请求URL通道。调用方法(无效的, &碳纳米管, 无效的, 无效的, 无效的/*已完成*/);
http/h2与protobuf关系不大,因此调用方法
为NULL,但控制器
和完成
。发出非NULL的异步RPC完成
。
cntl.响应_附件()
是http/h2响应的主体并键入butil::IOBuf
。IOBuf公司
可以转换为标准::字符串
通过to_string()
,它需要分配内存并复制所有数据。如果性能很重要,则代码应考虑支持IOBuf公司
而不需要连续记忆。
邮政
默认的HTTP方法是GET,可以更改为POST或其他http方法。应将要POST的数据放入请求_附件()
,已键入butil::IOBuf并且能够附加std::字符串
或字符*
直接。
brpc公司::控制器 碳纳米管;
碳纳米管。http_请求().乌里() = "..."; //请求URL碳纳米管。http_请求().设置方法(brpc公司::HTTP_方法_测试);
碳纳米管。请求_附件().追加("{\"消息\"以下为:\"你好,世界!\"}");
通道。调用方法(无效的, &碳纳米管, 无效的, 无效的, 无效的/*已完成*/);
如果车身需要大量打印才能构建,请考虑使用butil::IOBufBuilder
,具有与相同的接口标准::鸵鸟流
当需要打印大量对象时,可能比c-style printf更简单、更高效。
brpc公司::控制器 碳纳米管;
碳纳米管。http_请求().乌里() = "..."; //请求URL碳纳米管。http_请求().设置方法(brpc公司::HTTP_方法_测试);
但是::IOBufBuilder公司 操作系统;
操作系统 << “大量打印” << 可打印对象 << ...;
操作系统。移动到(碳纳米管。请求_附件());
通道。调用方法(无效的, &碳纳米管, 无效的, 无效的, 无效的/*已完成*/);
更改HTTP版本
brpc的默认行为是http/1.1。
与http/1.1相比,http/1.0缺少长连接(KeepAlive)。要将brpc客户端与一些旧的http服务器通信,可以按以下方式配置客户端:
碳纳米管。http_请求().设置版本(1, 0);
设置http版本不适用于h2,但客户端接收到的h2响应和服务器接收到的h2请求中的版本设置为(2,0)。
brpc服务器自动识别http版本,并在无需用户帮助的情况下做出相应响应。
网址
URL的一般形式:
//URI方案:http://en.wikipedia.org/wiki/URI_scheme//// foo://用户名:密码@example.com:8042/over/here/index.dtb?type=动物&name=独角鲸#鼻子// \_/ \_______________/ \_________/ \__/ \___/ \_/ \______________________/ \__/// | | | | | | | |//|userinfo主机端口||查询片段// | \________________________________/\_____________|____|/ \__/ \__///方案||||||//权限|||||//可解释为键的路径// | |// \_______________________________________________|____|/ \____/ \_____/// | | | | |//可解释为值的层次部分// | |//可解释为文件名|// |//|//可解释为扩展
正如我们在上面的例子中看到的,频道。首字母()
和cntl.http_request().uri()
两者都需要URL。为什么uri()
需要额外设置,而不是使用URL初始化()
直接?
实际上,在简单的情况下会重复这些设置。但在更复杂的场景中,它们是不同的:
- 访问NamingService下的多个服务器(例如BNS),在这种情况下
频道::初始化
接受对NamingService有意义的名称(例如BNS中的节点名称),而uri()
使用URL分配。 - 通过http/h2代理访问服务器,在这种情况下
频道::初始化
采用代理服务器的地址,而uri()
仍分配有URL。
如果用户已设置主机
标头(不区分大小写),框架不做任何更改。
如果用户未设置主机
标头和URL具有主机,例如http://www.foo.com/path,http请求包含“主机:网址:www.foo.com”.
如果用户未设置主机标头,并且URL也没有主机,例如“/index.html?name=value”,但通道初始化的地址包含域名。框架集主机
带有目标服务器域名的标头。如果此地址是“网址:http://www.foo.com“,此http服务器应看到主持人:www.foo.com
,如果此地址为“http://www.foo.com:8989“,此http服务器应该是主持人:www.foo.com:8989
。
如果用户没有设置主机头,并且URL也没有主机,例如“/index.html?name=value”,并且频道初始化的地址不包含域名。框架集主机
标头和目标服务器的IP和端口。位于10.46.188.39:8989的http服务器应看到主持人:10.46.188.39:8989
。
标头在h2中命名为“:authority”。
常见用法
以http请求为例(与http响应类似),常见操作如下:
访问名为的HTTP标头富
常数 标准::一串* 价值 = 碳纳米管->http_请求().获取标题(“Foo”); //不存在时为NULL
设置名为富
碳纳米管->http_请求().设置标题(“傻瓜”, “价值”);
访问名为的查询富
常数 标准::一串* 价值 = 碳纳米管->http_请求().乌里().获取查询(“傻瓜”); //不存在时为NULL
设置名为的查询富
碳纳米管->http_请求().乌里().SetQuery(设置查询)(“傻瓜”, “价值”);
设置HTTP方法
碳纳米管->http_请求().设置方法(brpc公司::HTTP_方法_测试);
设置URL
碳纳米管->http_请求().乌里() = ”http://www.baidu.com(百度)”;
设置内容类型
碳纳米管->http_请求().集合内容类型(“文本/纯文本”);
获取HTTP正文
但是::IOBuf公司& 缓冲器 = 碳纳米管->请求_附件();
标准::一串 字符串 = 碳纳米管->请求_附件().到字符串(_S)(); //触发复制基础
设置HTTP正文
碳纳米管->请求_附件().追加("....");
但是::IOBufBuilder公司 操作系统; 操作系统 << "....";
操作系统。移动(_T)(碳纳米管->请求_附件());
http头说明:
- 标头的field_name是区分大小写的,根据rfc2616型.brpc支持区分大小写的字段名,并在打印时保持与用户设置的大小写相同。
- 如果多个标题具有相同的字段名,根据rfc2616型,值应合并并用逗号(,)分隔。用户可以自己找出如何使用这种值。
- 查询用“&”分隔,查询中的键/值用“=”分隔。值可以省略。例如,
key1=值1&key2&key3=值3
是有效的查询字符串,其中键2
是空字符串。
调试HTTP消息
打开-http_详细以便框架打印每个http请求和响应。注意,这应该只用于测试或调试,而不是在线服务。
HTTP错误
当服务器返回非2xx HTTP状态代码时,HTTP RPC被视为失败并且cntl->错误代码()
在客户端设置为EHTTP公司
,用户可以检查cntl->http_response().status_code()
了解更具体的HTTP错误。此外,服务器可以将描述错误的html或json放入cntl->response_attachment()
它作为http主体发送回客户端。
压缩请求正文
控制器::set_request_compress_type(brpc::compress_type_GZIP)
使框架尝试gzip HTTP主体。“尝试”意味着压缩可能不会发生,因为:
- 正文的大小小于-http_body_compress_threshold指定的字节,默认值为512。原因是gzip不是一种非常快的压缩算法,当主体较小时,压缩引起的延迟甚至可能大于更快传输所节省的延迟。
减压响应机构
由于通用性,brpc不会自动解压缩响应体。解压缩代码并不复杂,用户可以自己完成。代码如下:
#包括 <brpc/policy/gzip_compress.h>
...
常数 标准::一串* 编码 = 碳纳米管->http_响应().获取标题(“内容编码”);
如果 (编码 != 无效的 && *编码 == “gzip”) {
但是::IOBuf公司 未压缩的;
如果 (!brpc公司::政策::Gzip解压缩(碳纳米管->响应_附件(), &未压缩的)) {
日志(错误) << “无法解压缩响应正文”;
返回;
}
碳纳米管->响应_附件().互换(未压缩的);
}
//现在,cntl->response_attachment()包含解压缩的数据
渐进式下载
http客户端通常在http主体完全下载之前不会完成RPC。在此过程中,http正文存储在内存中。如果主体非常大或无限大(用于实时流的FLV文件),内存将持续增长,直到RPC超时。这种http客户端不适合下载非常大的文件。
brpc客户端支持在读取整个正文之前完成RPC,以便用户可以在RPC之后逐步读取http正文。请注意,此功能并不意味着“支持http分块模式”,实际上brpc中的http实现从一开始就支持分块模式。真正的问题是如何让用户处理非常大或无限大的http主体,这并不意味着采用分块模式。
如何使用:
实施下面的ProgressiveReader:
#包括 <brpc/progressive_reader.h>
...
班 渐进式阅读器 {
公众的以下为:
//读取一个部分时调用。 //返回的错误被视为*permenant*和套接字,其中 //读取的数据将被关闭。 //可以通过阻塞此函数来处理临时错误 //可能会阻止套接字上的HTTP解析。 事实上的 但是::状态 OnReadOnePart(常数 空隙* 数据, 尺寸_t 长度) = 0;
//当没有什么可读的时调用。“状态”是 //为什么调用此方法。 //-status.ok():消息已完成并成功使用。 //-否则:套接字已损坏或OnReadOnePart()失败。 //此方法将调用一次且仅调用一次。没有其他方法 //在后面被调用。用户可以释放内部此对象的内存。 事实上的 空隙 OnEndOf消息(常数 但是::状态& 地位) = 0;
};
OnReadOnePart
每次读取一段数据时都会调用。OnEndOf消息
在数据结束时调用,或者连接断开。在实施之前仔细阅读评论。
设置cntl.response_will_be_read_progressively();
在RPC之前,使brpc在读取所有标头后立即结束RPC。
呼叫中国。ReadProgressiveAttachmentBy(新的MyProgressiveReader);
RPC之后。MyProgressiveReader(我的进步阅读器)
是用户实现的实例渐进式阅读器
用户可以删除其中的对象OnEndOf消息
。
渐进式上传
目前,在启动http调用之前,POST数据应该是完整的,因此brpc http客户端仍然不适合上载非常大的主体。
使用身份验证访问服务器
生成授权数据(_D)
根据服务器的身份验证方法,并将其设置为授权
收割台。如果使用curl,请添加选项-H“授权:<auth_data>”
。
发送https请求
https是“http-over-SSL”的缩写,SSL不是http的专用协议,但对所有协议都有效。打开客户端SSL的通用方法是在这里.brpc自动为以https://开头的URI启用SSL,以使使用更加方便。