From 3f8e1cc4e23d36094d0a631a499f89f5ad2c4fb4 Mon Sep 17 00:00:00 2001 From: LiuQiang Date: Thu, 10 Nov 2022 17:30:38 +0800 Subject: [PATCH] fix HTTP invalid host issue for channel not inited by http(s) (#1973) --- docs/cn/http_client.md | 2 +- docs/en/http_client.md | 2 +- src/brpc/channel.cpp | 12 +++++------- src/brpc/channel.h | 1 + 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/cn/http_client.md b/docs/cn/http_client.md index 66d3292c45..ebc55af6c8 100644 --- a/docs/cn/http_client.md +++ b/docs/cn/http_client.md @@ -114,7 +114,7 @@ URL的一般形式如下图: 若用户没有填且URL中包含host,比如http://www.foo.com/path,则http request中会包含"Host: www.foo.com"。 -若用户没有填且URL不包含host,比如"/index.html?name=value",但如果Channel初始化的地址包含域名,则框架会以域名作为Host,比如"http://www.foo.com",该http server将会看到"Host: www.foo.com"。如果地址是"http://www.foo.com:8989",则该http server将会看到"Host: www.foo.com:8989"。 +若用户没有填且URL不包含host,比如"/index.html?name=value",但如果Channel初始化的地址scheme为http(s)且包含域名,则框架会以域名作为Host,比如"http://www.foo.com",该http server将会看到"Host: www.foo.com"。如果地址是"http://www.foo.com:8989",则该http server将会看到"Host: www.foo.com:8989"。 若用户没有填且URL不包含host,比如"/index.html?name=value",如果Channel初始化的地址也不包含域名,则框架会以目标server的ip和port为Host,地址为10.46.188.39:8989的http server将会看到"Host: 10.46.188.39:8989"。 diff --git a/docs/en/http_client.md b/docs/en/http_client.md index a6e0e34aba..f83478d558 100644 --- a/docs/en/http_client.md +++ b/docs/en/http_client.md @@ -115,7 +115,7 @@ If user already sets `Host` header(case insensitive), framework makes no change. If user does not set `Host` header and the URL has host, for example http://www.foo.com/path, the http request contains "Host: www.foo.com". -If user does not set host header and the URL does not have host as well, for example "/index.html?name=value", but if the address initialized by the channel contains domain name. framework sets `Host` header with domain name of the target server. if this address is "http://www.foo.com", this http server should see `Host: www.foo.com`, if this address is "http://www.foo.com:8989", this http server should be see `Host: www.foo.com:8989`. +If user does not set host header and the URL does not have host either, for example "/index.html?name=value", but if the channel is initlized by a http(s) address with valid domain name. framework sets `Host` header with domain name of the target server. if this address is "http://www.foo.com", this http server should see `Host: www.foo.com`, if this address is "http://www.foo.com:8989", this http server should be see `Host: www.foo.com:8989`. If user does not set host header and the URL does not have host as well, for example "/index.html?name=value", and the address initialized by the channel doesn't contain domain name. framework sets `Host` header with IP and port of the target server. A http server at 10.46.188.39:8989 should see `Host: 10.46.188.39:8989`. diff --git a/src/brpc/channel.cpp b/src/brpc/channel.cpp index 2de1de10dd..a94c09b5b8 100644 --- a/src/brpc/channel.cpp +++ b/src/brpc/channel.cpp @@ -322,13 +322,12 @@ int Channel::InitSingle(const butil::EndPoint& server_addr_and_port, if (InitChannelOptions(options) != 0) { return -1; } - std::string scheme; int* port_out = raw_port == -1 ? &raw_port: NULL; - ParseURL(raw_server_address, &scheme, &_service_name, port_out); + ParseURL(raw_server_address, &_scheme, &_service_name, port_out); if (raw_port != -1) { _service_name.append(":").append(std::to_string(raw_port)); } - if (_options.protocol == brpc::PROTOCOL_HTTP && scheme == "https") { + if (_options.protocol == brpc::PROTOCOL_HTTP && _scheme == "https") { if (_options.mutable_ssl_options()->sni_name.empty()) { _options.mutable_ssl_options()->sni_name = _service_name; } @@ -363,13 +362,12 @@ int Channel::Init(const char* ns_url, if (InitChannelOptions(options) != 0) { return -1; } - std::string scheme; int raw_port = -1; - ParseURL(ns_url, &scheme, &_service_name, &raw_port); + ParseURL(ns_url, &_scheme, &_service_name, &raw_port); if (raw_port != -1) { _service_name.append(":").append(std::to_string(raw_port)); } - if (_options.protocol == brpc::PROTOCOL_HTTP && scheme == "https") { + if (_options.protocol == brpc::PROTOCOL_HTTP && _scheme == "https") { if (_options.mutable_ssl_options()->sni_name.empty()) { _options.mutable_ssl_options()->sni_name = _service_name; } @@ -429,7 +427,7 @@ void Channel::CallMethod(const google::protobuf::MethodDescriptor* method, CHECK(cntl->protocol_param().empty()); cntl->protocol_param() = _options.protocol.param(); } - if (_options.protocol == brpc::PROTOCOL_HTTP) { + if (_options.protocol == brpc::PROTOCOL_HTTP && (_scheme == "https" || _scheme == "http")) { URI& uri = cntl->http_request().uri(); if (uri.host().empty() && !_service_name.empty()) { uri.SetHostAndPort(_service_name); diff --git a/src/brpc/channel.h b/src/brpc/channel.h index 6600fcf25c..8e888f4554 100644 --- a/src/brpc/channel.h +++ b/src/brpc/channel.h @@ -221,6 +221,7 @@ friend class SelectiveChannel; int raw_port = -1); std::string _service_name; + std::string _scheme; butil::EndPoint _server_address; SocketId _server_id; Protocol::SerializeRequest _serialize_request;