Skip to content

Latest commit

 

History

History
519 lines (376 loc) · 31.1 KB

http_protocol_client.md

File metadata and controls

519 lines (376 loc) · 31.1 KB

English

前言

tRPC-Cpp 默认支持 tRPC 协议,同时也支持 HTTP 协议。 用户可在 HTTP 请求中发送 Plain Text 或者 JSON 等数据来访问标准 HTTP 服务,也可在请求中发送 Protobuf 数据来访问 RPC 服务。 这可以使一个 RPC 服务同时支持 tRPC 和 HTTP 协议,当前支持通过 HTTP 客户端访问 tRPC 服务。

本文介绍如何基于 tRPC-Cpp (下面简称 tRPC)访问 HTTP 服务,开发者可以了解到如下内容:

  • 访问 HTTP 标准服务
    • 快速上手:使用一个 HTTP Client 访问 HTTP 服务。
    • 基础用法:设置请求常用接口;获取响应常用接口。
    • 进阶用法:发送 HTTPS请求;请求消息压缩、响应消息解压缩;大文件上传、下载。
  • 访问 HTTP RPC 服务
  • FAQ

访问 HTTP 标准服务

快速上手

在正式开始前,可以先尝试运行示例代码,直观感受下 HTTP 服务运行过程。 另外,成功运行的服务可以用作客户端访问的目标服务对象,方便验证客户端访问接口的结果。

体验 HTTP 服务

示例:http

方法:进入 tRPC 代码仓库主目录,然后运行下面的命令。

sh examples/features/http/run.sh

示例程序输出:

# 部分过程输出片段内容
response content: hello world!
response content: {"msg":"hello world!"}
response content: {"msg": "hello world!", "age": 18, "height": 180}

# 测例运行成功或失败状态(1: 成功,0:失败)
name: GET string, ok: 1
name: GET json, ok: 1
name: GET http response, ok: 1
name: GET http response(not found), ok: 1
name: HEAD string, ok: 1
name: POST string, ok: 1
name: POST json, ok: 1
name: POST string, then wait http response, ok: 1
name: UNARY invoking, ok: 1
final result of http calling: 1

简单看下客户端的运行输出结果:发出 GET, HEAD, POST 请求并接收到了对应的响应。另外,还有一个 Unary RPC 成功执行了。

接下来看看访问 HTTP 服务的步骤。

访问 HTTP 服务的基本步骤

  1. 获取 HttpServiceProxyPtr 对象 proxy:使用 GetTrpcClient()->GetProxy<HttpServiceProxy>(...)
  2. 创建 ClientContextPtr 对象 context:使用 MakeClientContext(proxy)
  3. 调用期望访问的接口并检查调用返回码,比如 GetString or PostString 等(可根据业务场景选择使用同步接口或者异步接口)。

下面以 fiber 协程 为例,介绍 GetString 访问过程。

示例:http_client.cc

访问过程

  1. 获取 HttpServiceProxyPtr 对象 proxy:使用 ::trpc::GetTrpcClient()->GetProxy<HttpServiceProxy>(...)

    std::string service_name{"http_client_xx"};
    ::trpc::ServiceProxyOption option;
    
    // ... 此处省略  option 初始化过程
    // 此处的 proxy 获取后在其他地方可继续使用,不需要每次都获取
    auto proxy = ::trpc::GetTrpcClient()->GetProxy<::trpc::http::HttpServiceProxy>(servie_name, option);

    创建 HttpServiceProxyPtr 有 3 种方式:

    -1- 代码中设置 ServiceProxyOption 对象。

    -2- 使用 yaml 配置文件指定 service 配置项。(推荐)

    -3- 通过回调函数初始化 ServiceProxyOption + yaml 配置项。

    可参考 client_guide

  2. 创建 ClientContextPtr 对象 context:使用 MakeClientContext(proxy)

    auto ctx = ::trpc::MakeClientContext(proxy);
  3. 调用 GetString

    // ...
    auto proxy = ::trpc::GetTrpcClient()->GetProxy<::trpc::http::HttpServiceProxy>(servie_name, option);
    auto ctx = ::trpc::MakeClientContext(proxy);
    std::string rsp_str;
    auto status = proxy->GetString(ctx, "http://example.com/foo", &rsp_str);
    if (!status.OK()) {
      // Error ...
    } else {
      // Ok ...
    }
    // ...

基础用法

HttpServiceProxy 提供了 Head Get Post Put Delete Options 等接口,为了使用方便,还封装了一些获取特定对象的接口,比如常用的 StringJSON 对象。

这些接口一般适用于简单的场景,比如 GET 或者 POST 一个 String 或者 JSON。

针对不同编程模型,提供了同步和异步接口。 fiber 协程模式下推荐使用同步接口,在 merge or separate 线程模型下推荐使用异步接口。

下面先快速浏览下接口列表

HttpServiceProxy 接口列表

关于接口命名问题:部分接口命名可能不优雅,会提高理解成本,文档会尽量注明清楚。

GET

Get 接口从服务端获取一个 JSON/字符串,提供同步调用和异步调用接口。

提示:下面的 Get2 仅仅是一个接口名,并非是使用 HTTP2 协议。

类/对象 接口名称 功能 参数 返回值 备注
HttpServiceProxy Status Get(const ClientContextPtr& context, const std::string& url, rapidjson::Document* json) 使用 GET 方法获取一个 JSON 响应消息 context 客户端上下文
url 资源位置
json 存放响应消息
Status 同步接口
HttpServiceProxy Status GetString(const ClientContextPtr& context, const std::string& url, std::string* rspStr) 使用 GET 方法获取一个字符串响应消息 context 客户端上下文
url 资源位置
rspStr 存放响应消息
Status 同步接口
HttpServiceProxy Status Get2(const ClientContextPtr& context, const std::string& url, HttpResponse* rsp) 使用 GET 方法获取 HTTP 响应 context 客户端上下文
url 资源位置
rsp 存放HTTP响应
Status 同步接口
HttpServiceProxy Future<rapidjson::Document> AsyncGet(const ClientContextPtr& context, const std::string& url) 使用 GET 方法获取一个 JSON 响应消息 context 客户端上下文
url 资源位置
Future<rapidjson::Document> 异步接口
HttpServiceProxy Future<std::string> AsyncGetString(const ClientContextPtr& context, const std::string& url) 使用 GET 方法获取一个字符串响应消息 context 客户端上下文
url 资源位置
Future<std::string> 异步接口
HttpServiceProxy Future<HttpResponse> AsyncGet2(const ClientContextPtr& context, const std::string& url) 使用 GET 方法获取 HTTP 响应 context 客户端上下文
url 资源位置
Future<HttpResponse> 异步接口

POST

Post 接口支持发送一个JSON/字符串请求给服务端,然后从服务端获取一个JSON/字符串响应。

提示:下面的 Post2 仅仅是一个接口名,并非是使用 HTTP2 协议。

类/对象 接口名称 功能 参数 返回值 备注
HttpServiceProxy Status Post(const ClientContextPtr& context, const std::string& url, const rapidjson::Document& data, rapidjson::Document* rsp) 使用 POST 方法发送一个 JSON 请求消息,并获取一个 JSON 响应消息 context 客户端上下文
url 资源位置
data 请求消息
rsp 存放响应消息
Status 同步接口
HttpServiceProxy Status Post(const ClientContextPtr& context, const std::string& url, const std::string& data, std::string* rsp) 使用 POST 方法发送一个字符串请求消息,并获取一个字符串响应消息 context 客户端上下文
url 资源位置
data 请求消息
rsp 存放响应消息
Status 同步接口
HttpServiceProxy Status Post(const ClientContextPtr& context, const std::string& url, const std::string&& data, std::string* rsp) 使用 POST 方法发送一个字符串请求消息,并获取一个字符串响应消息 context 客户端上下文
url 资源位置
data 请求消息
rsp 存放响应消息
Status 同步接口,性能优化接口
HttpServiceProxy Status Post2(const ClientContextPtr& context, const std::string& url, const std::string& data, HttpResponse* rsp) 使用 POST 方法发送一个字符串请求消息,并获取一个 HTTP 响应 context 客户端上下文
url 资源位置
data 请求消息
rsp 存放响应消息
Status 同步接口
HttpServiceProxy Status Post2(const ClientContextPtr& context, const std::string& url, std::string&& data, HttpResponse* rsp) 使用 POST 方法发送一个字符串请求消息,并获取一个 HTTP 响应 context 客户端上下文
url 资源位置
data 请求消息
rsp 存放响应消息
Status 同步接口,性能优化接口
HttpServiceProxy Status Post(const ClientContextPtr& context, const std::string& url, NoncontiguousBuffer&& data, NoncontiguousBuffer* body) 使用 POST 方法发送一个字符串请求消息,并获取一个字符串响应消息 context 客户端上下文
url 资源位置
data 请求消息
body 存放响应消息
Status 同步接口,性能优化接口
HttpServiceProxy Future<rapidjson::Document> AsyncPost(const ClientContextPtr& context, const std::string& url, const rapidjson::Document& data) 使用 POST 方法发送一个 JSON 请求消息,并获取一个 JSON 响应消息 context 客户端上下文
url 资源位置
data 请求消息
Future<rapidjson::Document> 异步接口
HttpServiceProxy Future<std::string> AsyncPost(const ClientContextPtr& context, const std::string& url, const std::string& data) 使用 POST 方法发送一个字符串请求消息,并获取一个字符串响应消息 context 客户端上下文
url 资源位置
data 请求消息
Future<std::string> 异步接口
HttpServiceProxy Future<std::string> AsyncPost(const ClientContextPtr& context, const std::string& url, std::string&& data) 使用 POST 方法发送一个字符串请求消息,并获取一个字符串响应消息 context 客户端上下文
url 资源位置
data 请求消息
Future<std::string> 异步接口,性能优化接口
HttpServiceProxy Future<NoncontiguousBuffer> AsyncPost(const ClientContextPtr& context, const std::string& url, NoncontiguousBuffer&& data) 使用 POST 方法发送一个字符串请求消息,并获取一个字符串响应消息 context 客户端上下文
url 资源位置
data 请求消息
Future<NoncontiguousBuffer> 异步接口, 性能优化接口
HttpServiceProxy Future<HttpResponse> AsyncPost2(const ClientContextPtr& context, const std::string& url, const std::string& data) 使用 POST 方法发送一个字符串请求消息,并获取一个字符串响应消息 context 客户端上下文
url 资源位置
data 请求消息
Future<HttpResponse> 异步接口
HttpServiceProxy Future<HttpResponse> AsyncPost2(const ClientContextPtr& context, const std::string& url, std::string&& data) 使用 POST 方法发送一个字符串请求消息,并获取一个字符串响应消息 context 客户端上下文
url 资源位置
data 请求消息
Future<HttpResponse> 异步接口,性能优化接口

HEAD PUT OPTIONS PATCH DELETE

提示:下面的 Put2 仅仅是一个接口名,并非是使用 HTTP2 协议。

/// @brief Gets an HTTP response of an HTTP HEAD method request from HTTP server.
Status Head(const ClientContextPtr& context, const std::string& url, HttpResponse* rsp);

/// @brief Gets an HTTP response of an HTTP OPTIONS method request from HTTP server.
Status Options(const ClientContextPtr& context, const std::string& url, HttpResponse* rsp);

/// @brief Puts a JSON as the request body to HTTP server, then gets the JSON content of response.
Status Put(const ClientContextPtr& context, const std::string& url, const rapidjson::Document& data, rapidjson::Document* rsp);
/// @brief Puts a string as the request body to HTTP server, then gets the string content of response.
Status Put(const ClientContextPtr& context, const std::string& url, const std::string& data, std::string* rsp_str);
Status Put(const ClientContextPtr& context, const std::string& url, std::string&& data, std::string* rsp_str);
Status Put(const ClientContextPtr& context, const std::string& url, NoncontiguousBuffer&& data, NoncontiguousBuffer* body);
/// @brief Puts a string as the request body to HTTP server, then gets the HTTP response.
Status Put2(const ClientContextPtr& context, const std::string& url, const std::string& data, HttpResponse* rsp);
Status Put2(const ClientContextPtr& context, const std::string& url, std::string&& data, HttpResponse* rsp);

/// @brief Sends an HTTP PATCH request with a string as the request body to HTTP server, then gets the HTTP response.
Status Patch(const ClientContextPtr& context, const std::string& url, const std::string& data, HttpResponse* rsp);
Status Patch(const ClientContextPtr& context, const std::string& url, std::string&& data, HttpResponse* rsp);

/// @brief Sends an HTTP DELETE request with a string as the request body to HTTP server, then gets the HTTP response.
Status Delete(const ClientContextPtr& context, const std::string& url, const std::string& data, HttpResponse* rsp);
Status Delete(const ClientContextPtr& context, const std::string& url, std::string&& data, HttpResponse* rsp);

// 与之对应的异步接口:
Future<HttpResponse> AsyncHead(const ClientContextPtr& context, const std::string& url);

Future<HttpResponse> AsyncOptions(const ClientContextPtr& context, const std::string& url);

Future<rapidjson::Document> AsyncPut(const ClientContextPtr& context, const std::string& url, const rapidjson::Document& data);
Future<std::string> AsyncPut(const ClientContextPtr& context, const std::string& url, const std::string& data);
Future<std::string> AsyncPut(const ClientContextPtr& context, const std::string& url, std::string&& data);
Future<NoncontiguousBuffer> AsyncPut(const ClientContextPtr& context, const std::string& url, NoncontiguousBuffer&& data);
Future<HttpResponse> AsyncPut2(const ClientContextPtr& context, const std::string& url, const std::string& data);
Future<HttpResponse> AsyncPut2(const ClientContextPtr& context, const std::string& url, std::string&& data);

Future<HttpResponse> AsyncPatch(const ClientContextPtr& context, const std::string& url, const std::string& data);
Future<HttpResponse> AsyncPatch(const ClientContextPtr& context, const std::string& url, std::string&& data);
Future<HttpResponse> AsyncDelete(const ClientContextPtr& context, const std::string& url, const std::string& data);
Future<HttpResponse> AsyncDelete(const ClientContextPtr& context, const std::string& url, std::string&& data);

暂未支持 CONNECT 方法

tRPC-Cpp 侧暂未实现 HTTP CONNECT 相关逻辑。

接口返回值 Status

HttpServiceProxy 提供的同步接口返回 Status 对象,习惯使用 status.OK() 快速判断访问成功或失败状态,然后再进行下一步处理。

类/对象 接口名称 功能 参数 返回值
Status bool Status::OK() 调用接口是否成功 void bool, true: 成功,false: 出错
Status std::string ToString() const 以字符格式返回错误码、错误消息 void std::string

HTTP Version

tRPC 当前支持 HTTP/1.1HTTP 1.0, 默认使用 HTTP/1.1。暂未支持 HTTP/2.0,在准备中。

如果使用 1.0 ,可以使用如下方法设置。

request.SetVersion("1.0");

Host 字段

tRPC 在解析 URL 时,会将 URL 中的 host:port 字段,设置进 HTTP 请求头部中。

提示: URL 中的 host 字段(Domain)并未用作 DNS 查询,或者 host:port 字段(IP:Port) 未用作 TCP 创建连接使用,仅用做 HTTP 协议填充使用。

限制:单个 HttpServiceProxy 对象实例不支持访问动态 URL。比如,不支持 HTTP 代理转发场景下需要动态访问不同站点。 解决办法:需要针对不同站点创建不同 HttpServiceProxy 实例。

HTTP Client 选择目标 IP:Port 是通过 target: ip:portselector: $naming 两个配置项来选路的。

常用方式:

  • 直连方式。selector: direct, 配置单个 IP:Port :target: ip:port,或者 IP:Port 列表 target: ip:port,ip:port,ip:port,...
  • DNS 解析。selector: domaintarget: github.com:80 (提示:此处的 target 是 IP:Port 格式,需要补充具体端口)。
  • 其他名字服务。selector: $naming_plugintarget: $name

那 URL 参数如何填写? 一般情况下,URL 按规范方式填写即可。其中 "host:port",可以采取占位符方式填写,"host" 和 "port" 可以填写成你期望发送给服务器端的值。 比如:

  • 填写 xx.example.com,完整 URL:http://xx.example.com/to/path ,则 HTTP 请求头部会填充:Host: xx.example.com
  • 填写 xx.example.com:8080, 完整 URL:http://xx.example.com:8080/to/path , 则 HTTP 请求头部会填充:Host: xx.example.com:8080

设置/获取 HTTP 请求头

Get/Post 接口中并没有直接提供设置 HTTP Request Header 入口,如果要设置请求头,可通过 ClientContext 提供的接口来设置。

类/对象 接口名称 功能 参数 返回值
ClientContext void SetHttpHeader(const std::string& h, const std::string& v) 设置 HTTP 请求头 h: 请求头名称
请求头取值
void
ClientContext const std::string& GetHttpHeader(const std::string& h) 获取指定 HTTP 请求头对应值 h: 请求头名称 const std::string&
ClientContext const auto &GetHttpHeaders(); 获取 HTTP 请求头列表 void google::protobuf::Map<std::string, std::string>

进阶用法

发送和接收完整 HTTP 请求和响应

在前面的章节中提到的 Get Post 等接口方法中一般是传递 Client Context + URL + Request Body 等参数,没有提供请求头部相关参数。

如果需要:

  • 设置请求对象更多参数
  • 获取响应对象更多参数

推荐使用 HttpUnaryInvoke 接口,可以传递完整的请求对象,或者获取完整的响应对象。

Status HttpUnaryInvoke(const ClientContextPtr& context, const HttpRequest& req, HttpRespnose* rsp);
Future<HttpResponse> AsyncHttpUnaryInvoke(const ClientContextPtr& context, const HttpRequest& req);

使用这个接口需要调用者完成如下操作:

  • 设置 HTTP Method
  • 设置 URL (相对路径的 Request-URI,比如:"/hello?name=tom")。
  • 建议设置 Host 头部(某些反向代理服务器可能需要此值做转发,比如 nginx)。

举个例子:

bool HttpPost(const HttpServiceProxyPtr& proxy) {
  auto ctx = ::trpc::MakeClientContext(proxy);
  ::trpc::http::Request http_req;
  http_req.SetMethod("POST");
  http_req.SetUrl("/foo");

  std::string req_content = R"({"msg": "hello world!"})";
  http_req.SetHeader("Content-Type", "application/json");
  http_req.SetHeader("Content-Length", std::to_string(req_content.size()));
  http_req.SetContent(req_content);

  ::trpc::http::Response http_rsp;
  auto status = proxy->HttpUnaryInvoke<::trpc::http::Request, ::trpc::http::Response>(ctx, http_req, &http_rsp);
  if (!status.OK()) {
    TRPC_FMT_ERROR("status: {}", status.ToString());
    return false;
  }
  // ...
  return true;
}

压缩或者解压缩消息体

tRPC-Cpp 当前不会自动压缩或者解压缩消息体,主要基于如下考虑:

  • 通用性,这个操作交由用户自行处理会更灵活。
  • 压缩、解压缩代码不是很复杂,tRPC 提供了压缩和解压缩工具,当前支持 gzip,lz4, snappy,zlib 等 compressor

发送 HTTPS 请求

HTTPS 是 HTTP over SSL 的简称,可以通过如下方式开启 SSL。

  • 编译代码时开启 SSL 编译选项。

    使用 bazel build 时,增加 --define trpc_include_ssl=true 编译参数。 提示:也可以加到 .bazelrc 文件中。

    提示:tRPC-Cpp 基于 OpenSSL 支持 HTTPS,请确保编译、运行环境正确安装 OpenSSL 。

    // e.g. 
    bazel build --define trpc_include_ssl=true //https/http_client/...
  • client 配置中,service 配置项中新增 ssl 配置项,具体配置如下:

    名称 功能 取值范围 默认值 可选状态 说明
    ciphers 加密套件 不限 null required 在启用SSL时,如果不正确设置,服务会启动失败
    enable 是否启用SSL {true, false} false optional 建议在配置项明确指定,明确意图
    sni_name 设置 SSL 协议中 SNI 扩展字段,也可简单理解为在 SSL 中设置 Host 不限 null optional 建议设置成 URL 中 Host 值,一般可简单理解为 HTTP 中 Host 值,即域名
    ca_cert_path CA 证书路径 不限,xx/path/to/ca.pem null optional 在自签证书场景使用较多
    cert_path 证书路径 不限,xx/path/to/server.pem null optional 双向认证必选,其他情况无效
    private_key_path 私钥路径 不限,xx/path/to/server.key null optional 双向认证必选,其他情况无效
    protocols SSL协议版本 {SSLv2, SSLv3, TLSv1, TLSv1.1, TLSv1.2} TLSv1.1 + TLSv1.2 optional -
    insecure 是否校验对方证书合法性 {true, false} false optional 默认校验对方证书合法性。在调试场景中,一般使用自签证书,证书不一定能够通过校验,将此参数设置成 true 可以跳过证书校验环节

    举个例子:

    # @file: trpc_cpp.yaml
    # ...
    client:
      service:
        - name: http_client
          selector_name: direct
          target: 127.0.0.1:24756
          protocol: http
          network: tcp
          conn_type: long
          ## <-- 新增的 SSL 配置项
          ssl:
            enable: true # 可选参数(默认为 false ,禁用 SSL)
            ciphers: HIGH:!aNULL:!kRSA:!SRP:!PSK:!CAMELLIA:!RC4:!MD5:!DSS # 必选参数
            # 下面可选参数按需配置,这里简要列举下
            # sni_name: www.xxops.com # 可选参数
            # ca_cert_path: ./https/cert/xxops-com-chain.pem # 可选参数
            # cert_path: xx_cert.pem # 可选参数,双向认证必选
            # private_key_path: xx_key.pem # 可选参数,双向认证必选
            # insecure: true # 可选参数(默认为 false,禁用非安全模式)
            # protocols: # 可选参数
            #   - SSLv2
            #   - SSLv3
            #   - TLSv1
            #   - TLSv1.1
            #   - TLSv1.2
            ## --> 新增的SSL配置项
    # ...

获取非 2xx 响应的响应内容

tRPC-Cpp 对 HTTP 响应码做了过滤处理:

  • 响应码为 2xx 时,调用者可以获取对应的响应消息。
  • 响应码非 2xx 时,调用者仅可以获取到响应码,但无响应消息。

解决办法:override CheckResponse(...) 直接返回 true 即可,举个例子:

class MyHttpServiceProxy : public ::trpc::http::HttpSeriveProxy {
  public:
   bool CheckHttpResponse(const ClientContextPtr& context, const ProtocolPtr& http_rsp) override { return true; }
};

大文件上传 + 下载

在 HTTP 服务中,有部分场景需要读取或者发送大文件的场景,将文件完整读入内存压力较大且效率较低,对于大文件的上传可行性不高。 tRPC-Cpp 提供一套 HTTP 流式读取/写入数据分片的接口,可以分片接收/发送大文件。

  • 对于已经知晓长度的大文件,设置 Content-Length: $length 后分块发送(当然也可以使用 chunked 分块发送,如果对端支持的话)。
  • 对于未知长度的大文件,设置 Transfer-Encoding: chunked 后分块发送。

具体可以参考 HTTP 上传 下载

访问 HTTP RPC 服务

示例:client.cc

如果某个 tRPC RPC 服务在服务端支持 HTTP 协议的客户端访问,那客户端也可以使用 HTTP 协议访问这个 RPC 服务。

具体方法:

  • 调用 UnaryInvoke(...)
  • 设置配置项 protocol: trpc_over_http
// 模版参数为 protobuf message 对象。
template <class RequestMessage, class ResponseMessage>
Status UnaryInvoke(const ClientContextPtr& context, const RequestMessage& req, ResponseMessage* rsp);
template <class RequestMessage, class ResponseMessage>
Future<ResponseMessage> AsyncUnaryInvoke(const ClientContextPtr& context, const RequestMessage& req);

举个例子:

bool HttpRpcCall(const HttpServiceProxyPtr& proxy) {
  auto ctx = ::trpc::MakeClientContext(proxy);
  ctx->SetTimeout(5000);
  // 设置被调用的 RPC 方法名称。
  ctx->SetFuncName("/trpc.test.helloworld.Greeter/SayHello");
  ::trpc::test::helloworld::HelloRequest req;
  ::trpc::test::helloworld::HelloReply rsp;

  req.set_msg("hello world!");
  auto status =
      proxy->UnaryInvoke<::trpc::test::helloworld::HelloRequest, ::trpc::test::helloworld::HelloReply>(ctx, req, &rsp);
  if (!status.OK()) {
    TRPC_FMT_ERROR("status: {}", status.ToString());
    return false;
  }
  // ...
  return true;
}

设置 trpc-trans-info

如果服务端希望使用 HTTP 协议透传 tRPC 协议 trans_info,客户端如何处理 ? 设置方法:把 trpc-trans-info: {"k1": "v1", "k2": "v2"} 当做一个 HTTP Header, 其中 HTTP Header 名称为:trpc-trans-info , 值为 {"k1": "v1", "k2": "v2"} 是一个 JSON 串。 并使用 ClientContext::SetHttpHeader('trpc-trans-info', 'json_string') 设置。

和如下 curl 命令行类似:

curl -H 'trpc-trans-info: {"k1": "v1", "k2": "v2" }'  -T xx.seriealized.pb $url

如果待透传 Key-Value Pairs 包含二进制数据,如何处理? 方法:可以尝试将二进制数据进行 Base64 Decode/Encode 处理,客户端和服务端约定好,保证数据可以正确传递。

FAQ

如何获取 HTTP 响应状态码,比如 200,404?

如果只需要获取 2xx 的状态码,可直接使用返回为 HttpResponse* 的接口。 如果需要获取非 2xx 的状态码,请 override CheckHttpResponse(...) 方法。

配置文件中的 target 配置项是否支持 domain:port 格式?

支持的,需要:

  • target 设置成 xx.example.com:8080
  • selector_name 设置成 domain

同步接口执行过程中是阻塞线程?

  • 如果使用了 fiber 协程,同步接口执行过程是同步调用,异步执行,不阻塞线程。
  • 如果使用了 merge or separate 线程模型,同步接口调用会阻塞调用者线程,但是网络相关操作是异步执行的。

如何使用 curl 命令发送 Protobuf 数据给 HTTP Service?

参考如下命令(替换你自己的数据 + IP:Port + RPC 方法名):

## 其中 http_rpc_hello_request.pb 是 PB 消息序列化后的内容。
curl -T http_rpc_hello_request.pb -H "Content-Type:application/pb" 'http://127.0.0.1:24756/trpc.test.httpserver.Greeter/SayHello'

## 发送 JSON 数据
curl -T http_rpc_hello_request.json -H "Content-Type:application/json" 'http://127.0.0.1:24756/trpc.test.httpserver.Greeter/SayHello'

使用自签证书调试时,客户端校验证书不通过,如何处理?

ssl 配置项:insecure :是否校验对方证书合法性,默认校验对方证书合法性。在调试场景中,使用自签证书时,可以将此参数设置成 true 可以跳过证书校验环节。

调用 HttpUnaryInvoke 等接口时,提示错误:... err=unmatched codec ...,如何处理?

尝试设置 HttpServiceProxy 使用的 codec 配置项:procotol: http

通过 HTTP 调用 tRPC RPC 服务时,被调方通过 @alias 设置了一个别名如何设置 URL Path ?

方法:client_context->SetFuncName("${your-alias-name}") ,替换下参数值。