brpc icon indicating copy to clipboard operation
brpc copied to clipboard

Invalid host in HTTP header if setting host via service_name for channel inited by list or file

Open thorneliu opened this issue 1 year ago • 3 comments

Describe the bug (描述bug) In brpc::PROTOCOL_HTTP, we will set the host field by service_name when

  • host is not explicitly set
  • host is not set in the url
    if (_options.protocol == brpc::PROTOCOL_HTTP) {
        URI& uri = cntl->http_request().uri();
        if (uri.host().empty() && !_service_name.empty()) {
            uri.SetHostAndPort(_service_name);
        }
    }

However, when the channel is inited via na_url shceme = list or file, such _service_name is not valid host field which results in 400 BadRequest

To Reproduce (复现方法) Init a channel with ipport list and http_request uri with relative path, eg:

    brpc::Channel channel;
    brpc::ChannelOptions opt;
    opt.protocol = brpc::PROTOCOL_HTTP;

    std::string server("list://127.0.0.1:8000,127.0.0.1:8001");
    std::string lb("rr");
    const int ret = channel.Init(server.c_str(), lb.c_str(), &opt);

    brpc::Controller cntl;
    cntl.http_request().uri() = "/dummy";
    channel.CallMethod(nullptr, &cntl, nullptr, nullptr, nullptr);

In the http request, the host field will be set as : host: 127.0.0.1:8000,127.0.0.1:8001

Similarly, when the ns_url is a file://conf/hosts, the host field in HTTP requeset will be: host: conf

Expected behavior (期望行为) host should be set as remote_side IP+Port in the senarios above

Versions (各种版本) OS: Ubuntu 20.04 Compiler: g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0 brpc: latest 59f5d772db2ec3d280ee3fbd881e078544590f3b protobuf: 3.6.1

Additional context/screenshots (更多上下文/截图) issue

thorneliu avatar Sep 30 '22 23:09 thorneliu

We could

  • A: check if service name a valid host for HTTP
  • B: set host field by remote_side

option B would revert some changes dab62e476 by @guodongxiaren

thorneliu avatar Sep 30 '22 23:09 thorneliu

We could

  • A: check if service name a valid host for HTTP
  • B: set host field by remote_side

option B would revert some changes dab62e4 by @guodongxiaren

I think we can check if ns_url shceme is 'http' or 'https', if true, set host field by service_name

wwbmmm avatar Oct 14 '22 08:10 wwbmmm

We could

  • A: check if service name a valid host for HTTP
  • B: set host field by remote_side

option B would revert some changes dab62e4 by @guodongxiaren

I think we can check if ns_url shceme is 'http' or 'https', if true, set host field by service_name

hmm. looks good. I can provide a patch based on this

thorneliu avatar Oct 15 '22 03:10 thorneliu

Is it possible that we fix the host field after a server has been selected?

B: set host field by remote_side

If schema is not http(s), but protocol is HTTP.

wasphin avatar Oct 28 '22 15:10 wasphin

Is it possible that we fix the host field after a server has been selected?

B: set host field by remote_side

If schema is not http(s), but protocol is HTTP.

Currently the host is set by remote side iff the host is not set. however such scheme info is not available when host is updated by remote_side inside http impl

thorneliu avatar Oct 30 '22 03:10 thorneliu

correction merged 3f8e1cc4e23d36094d0a631a499f89f5ad2c4fb4

thorneliu avatar Nov 14 '22 02:11 thorneliu