http_message.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. // Copyright (c) 2014 Baidu, Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Authors: Zhangyi Chen (chenzhangyi01@baidu.com)
  15. // Ge,Jun (gejun@baidu.com)
  16. #include <cstdlib>
  17. #include <string> // std::string
  18. #include <iostream>
  19. #include <gflags/gflags.h>
  20. #include "butil/macros.h"
  21. #include "butil/logging.h" // LOG
  22. #include "butil/scoped_lock.h"
  23. #include "butil/endpoint.h"
  24. #include "butil/base64.h"
  25. #include "bthread/bthread.h" // bthread_usleep
  26. #include "brpc/log.h"
  27. #include "brpc/reloadable_flags.h"
  28. #include "brpc/details/http_message.h"
  29. namespace brpc {
  30. DEFINE_bool(http_verbose, false,
  31. "[DEBUG] Print EVERY http request/response to stderr");
  32. DEFINE_int32(http_verbose_max_body_length, 512,
  33. "[DEBUG] Max body length printed when -http_verbose is on");
  34. DECLARE_int64(socket_max_unwritten_bytes);
  35. // Implement callbacks for http parser
  36. int HttpMessage::on_message_begin(http_parser *parser) {
  37. HttpMessage *http_message = (HttpMessage *)parser->data;
  38. http_message->_stage = HTTP_ON_MESSAGE_BEGIN;
  39. return 0;
  40. }
  41. // For request
  42. int HttpMessage::on_url(http_parser *parser,
  43. const char *at, const size_t length) {
  44. HttpMessage *http_message = (HttpMessage *)parser->data;
  45. http_message->_stage = HTTP_ON_URL;
  46. http_message->_url.append(at, length);
  47. return 0;
  48. }
  49. // For response
  50. int HttpMessage::on_status(http_parser *parser, const char *, const size_t) {
  51. HttpMessage *http_message = (HttpMessage *)parser->data;
  52. http_message->_stage = HTTP_ON_STATUS;
  53. // According to https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html
  54. // Client is not required to examine or display the Reason-Phrase
  55. return 0;
  56. }
  57. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
  58. // Multiple message-header fields with the same field-name MAY be present in a
  59. // message if and only if the entire field-value for that header field is
  60. // defined as a comma-separated list [i.e., #(values)]. It MUST be possible to
  61. // combine the multiple header fields into one "field-name: field-value" pair,
  62. // without changing the semantics of the message, by appending each subsequent
  63. // field-value to the first, each separated by a comma. The order in which
  64. // header fields with the same field-name are received is therefore significant
  65. // to the interpretation of the combined field value, and thus a proxy MUST NOT
  66. // change the order of these field values when a message is forwarded.
  67. int HttpMessage::on_header_field(http_parser *parser,
  68. const char *at, const size_t length) {
  69. HttpMessage *http_message = (HttpMessage *)parser->data;
  70. if (http_message->_stage != HTTP_ON_HEADER_FIELD) {
  71. http_message->_stage = HTTP_ON_HEADER_FIELD;
  72. http_message->_cur_header.clear();
  73. }
  74. http_message->_cur_header.append(at, length);
  75. return 0;
  76. }
  77. int HttpMessage::on_header_value(http_parser *parser,
  78. const char *at, const size_t length) {
  79. HttpMessage *http_message = (HttpMessage *)parser->data;
  80. bool first_entry = false;
  81. if (http_message->_stage != HTTP_ON_HEADER_VALUE) {
  82. http_message->_stage = HTTP_ON_HEADER_VALUE;
  83. first_entry = true;
  84. if (http_message->_cur_header.empty()) {
  85. LOG(ERROR) << "Header name is empty";
  86. return -1;
  87. }
  88. http_message->_cur_value =
  89. &http_message->header().GetOrAddHeader(http_message->_cur_header);
  90. if (http_message->_cur_value && !http_message->_cur_value->empty()) {
  91. http_message->_cur_value->push_back(',');
  92. }
  93. }
  94. if (http_message->_cur_value) {
  95. http_message->_cur_value->append(at, length);
  96. }
  97. if (FLAGS_http_verbose) {
  98. butil::IOBufBuilder* vs = http_message->_vmsgbuilder;
  99. if (vs == NULL) {
  100. vs = new butil::IOBufBuilder;
  101. http_message->_vmsgbuilder = vs;
  102. if (parser->type == HTTP_REQUEST) {
  103. *vs << "[HTTP REQUEST @" << butil::my_ip() << "]\n< "
  104. << HttpMethod2Str((HttpMethod)parser->method) << ' '
  105. << http_message->_url << " HTTP/" << parser->http_major
  106. << '.' << parser->http_minor;
  107. } else {
  108. *vs << "[HTTP RESPONSE @" << butil::my_ip() << "]\n< HTTP/"
  109. << parser->http_major
  110. << '.' << parser->http_minor << ' ' << parser->status_code
  111. << ' ' << http_message->header().reason_phrase();
  112. }
  113. }
  114. if (first_entry) {
  115. *vs << "\n< " << http_message->_cur_header << ": ";
  116. }
  117. vs->write(at, length);
  118. }
  119. return 0;
  120. }
  121. int HttpMessage::on_headers_complete(http_parser *parser) {
  122. HttpMessage *http_message = (HttpMessage *)parser->data;
  123. http_message->_stage = HTTP_ON_HEADERS_COMPLELE;
  124. // Move content-type into the member field.
  125. const std::string* content_type = http_message->header().GetHeader("content-type");
  126. if (content_type) {
  127. http_message->header().set_content_type(*content_type);
  128. http_message->header().RemoveHeader("content-type");
  129. }
  130. if (parser->http_major > 1) {
  131. // NOTE: this checking is a MUST because ProcessHttpResponse relies
  132. // on it to cast InputMessageBase* into different types.
  133. LOG(WARNING) << "Invalid major_version=" << parser->http_major;
  134. parser->http_major = 1;
  135. }
  136. http_message->header().set_version(parser->http_major, parser->http_minor);
  137. // Only for response
  138. // http_parser may set status_code to 0 when the field is not needed,
  139. // e.g. in a request. In principle status_code is undefined in a request,
  140. // but to be consistent and not surprise users, we set it to OK as well.
  141. http_message->header().set_status_code(
  142. !parser->status_code ? HTTP_STATUS_OK : parser->status_code);
  143. // Only for request
  144. // method is 0(which is DELETE) for response as well. Since users are
  145. // unlikely to check method of a response, we don't do anything.
  146. http_message->header().set_method(static_cast<HttpMethod>(parser->method));
  147. if (parser->type == HTTP_REQUEST &&
  148. http_message->header().uri().SetHttpURL(http_message->_url) != 0) {
  149. LOG(ERROR) << "Fail to parse url=`" << http_message->_url << '\'';
  150. return -1;
  151. }
  152. //rfc2616-sec5.2
  153. //1. If Request-URI is an absoluteURI, the host is part of the Request-URI.
  154. //Any Host header field value in the request MUST be ignored.
  155. //2. If the Request-URI is not an absoluteURI, and the request includes a
  156. //Host header field, the host is determined by the Host header field value.
  157. //3. If the host as determined by rule 1 or 2 is not a valid host on the
  158. //server, the responce MUST be a 400 error messsage.
  159. URI & uri = http_message->header().uri();
  160. if (uri._host.empty()) {
  161. const std::string* host_header = http_message->header().GetHeader("host");
  162. if (host_header != NULL) {
  163. uri.SetHostAndPort(*host_header);
  164. }
  165. }
  166. return 0;
  167. }
  168. int HttpMessage::UnlockAndFlushToBodyReader(std::unique_lock<butil::Mutex>& mu) {
  169. if (_body.empty()) {
  170. mu.unlock();
  171. return 0;
  172. }
  173. butil::IOBuf body_seen = _body.movable();
  174. ProgressiveReader* r = _body_reader;
  175. mu.unlock();
  176. for (size_t i = 0; i < body_seen.backing_block_num(); ++i) {
  177. butil::StringPiece blk = body_seen.backing_block(i);
  178. butil::Status st = r->OnReadOnePart(blk.data(), blk.size());
  179. if (!st.ok()) {
  180. mu.lock();
  181. _body_reader = NULL;
  182. mu.unlock();
  183. r->OnEndOfMessage(st);
  184. return -1;
  185. }
  186. }
  187. return 0;
  188. }
  189. int HttpMessage::on_body_cb(http_parser *parser,
  190. const char *at, const size_t length) {
  191. return static_cast<HttpMessage*>(parser->data)->OnBody(at, length);
  192. }
  193. int HttpMessage::on_message_complete_cb(http_parser *parser) {
  194. return static_cast<HttpMessage*>(parser->data)->OnMessageComplete();
  195. }
  196. int HttpMessage::OnBody(const char *at, const size_t length) {
  197. if (_vmsgbuilder) {
  198. if (_stage != HTTP_ON_BODY) {
  199. // only add prefix at first entry.
  200. *_vmsgbuilder << "\n<\n";
  201. }
  202. if (_read_body_progressively) {
  203. std::cerr << _vmsgbuilder->buf() << std::endl;
  204. delete _vmsgbuilder;
  205. _vmsgbuilder = NULL;
  206. } else {
  207. if (_body_length < (size_t)FLAGS_http_verbose_max_body_length) {
  208. int plen = std::min(length, (size_t)FLAGS_http_verbose_max_body_length
  209. - _body_length);
  210. _vmsgbuilder->write(at, plen);
  211. }
  212. _body_length += length;
  213. }
  214. }
  215. if (_stage != HTTP_ON_BODY) {
  216. _stage = HTTP_ON_BODY;
  217. }
  218. if (!_read_body_progressively) {
  219. // Normal read.
  220. // TODO: The input data is from IOBuf as well, possible to append
  221. // data w/o copying.
  222. _body.append(at, length);
  223. return 0;
  224. }
  225. // Progressive read.
  226. std::unique_lock<butil::Mutex> mu(_body_mutex);
  227. ProgressiveReader* r = _body_reader;
  228. while (r == NULL) {
  229. // When _body is full, the sleep-waiting may block parse handler
  230. // of the protocol. A more efficient solution is to remove the
  231. // socket from epoll and add it back when the _body is not full,
  232. // which requires a set of complicated "pause" and "unpause"
  233. // asynchronous API. We just leave the job to bthread right now
  234. // to make everything work.
  235. if ((int64_t)_body.size() <= FLAGS_socket_max_unwritten_bytes) {
  236. _body.append(at, length);
  237. return 0;
  238. }
  239. mu.unlock();
  240. bthread_usleep(10000/*10ms*/);
  241. mu.lock();
  242. r = _body_reader;
  243. }
  244. // Safe to operate _body_reader outside lock because OnBody() is
  245. // guaranteed to be called by only one thread.
  246. if (UnlockAndFlushToBodyReader(mu) != 0) {
  247. return -1;
  248. }
  249. butil::Status st = r->OnReadOnePart(at, length);
  250. if (st.ok()) {
  251. return 0;
  252. }
  253. mu.lock();
  254. _body_reader = NULL;
  255. mu.unlock();
  256. r->OnEndOfMessage(st);
  257. return -1;
  258. }
  259. int HttpMessage::OnMessageComplete() {
  260. if (_vmsgbuilder) {
  261. if (_body_length > (size_t)FLAGS_http_verbose_max_body_length) {
  262. *_vmsgbuilder << "\n<skipped " << _body_length
  263. - (size_t)FLAGS_http_verbose_max_body_length << " bytes>";
  264. }
  265. std::cerr << _vmsgbuilder->buf() << std::endl;
  266. delete _vmsgbuilder;
  267. _vmsgbuilder = NULL;
  268. }
  269. _cur_header.clear();
  270. _cur_value = NULL;
  271. if (!_read_body_progressively) {
  272. // Normal read.
  273. _stage = HTTP_ON_MESSAGE_COMPLELE;
  274. return 0;
  275. }
  276. // Progressive read.
  277. std::unique_lock<butil::Mutex> mu(_body_mutex);
  278. _stage = HTTP_ON_MESSAGE_COMPLELE;
  279. if (_body_reader != NULL) {
  280. // Solve the case: SetBodyReader quit at ntry=MAX_TRY with non-empty
  281. // _body and the remaining _body is just the last part.
  282. // Make sure _body is emptied.
  283. if (UnlockAndFlushToBodyReader(mu) != 0) {
  284. return -1;
  285. }
  286. mu.lock();
  287. ProgressiveReader* r = _body_reader;
  288. _body_reader = NULL;
  289. mu.unlock();
  290. r->OnEndOfMessage(butil::Status());
  291. }
  292. return 0;
  293. }
  294. class FailAllRead : public ProgressiveReader {
  295. public:
  296. // @ProgressiveReader
  297. butil::Status OnReadOnePart(const void* /*data*/, size_t /*length*/) {
  298. return butil::Status(-1, "Trigger by FailAllRead at %s:%d",
  299. __FILE__, __LINE__);
  300. }
  301. void OnEndOfMessage(const butil::Status&) {}
  302. };
  303. static FailAllRead* s_fail_all_read = NULL;
  304. static pthread_once_t s_fail_all_read_once = PTHREAD_ONCE_INIT;
  305. static void CreateFailAllRead() { s_fail_all_read = new FailAllRead; }
  306. void HttpMessage::SetBodyReader(ProgressiveReader* r) {
  307. if (!_read_body_progressively) {
  308. return r->OnEndOfMessage(
  309. butil::Status(EPERM, "Call SetBodyReader on HttpMessage with"
  310. " read_body_progressively=false"));
  311. }
  312. const int MAX_TRY = 3;
  313. int ntry = 0;
  314. do {
  315. std::unique_lock<butil::Mutex> mu(_body_mutex);
  316. if (_body_reader != NULL) {
  317. mu.unlock();
  318. return r->OnEndOfMessage(
  319. butil::Status(EPERM, "SetBodyReader is called more than once"));
  320. }
  321. if (_body.empty()) {
  322. if (_stage <= HTTP_ON_BODY) {
  323. _body_reader = r;
  324. return;
  325. } else { // The body is complete and successfully consumed.
  326. mu.unlock();
  327. return r->OnEndOfMessage(butil::Status());
  328. }
  329. } else if (_stage <= HTTP_ON_BODY && ++ntry >= MAX_TRY) {
  330. // Stop making _body empty after we've tried several times.
  331. // If _stage is greater than HTTP_ON_BODY, neither OnBody() nor
  332. // OnMessageComplete() will be called in future, we have to spin
  333. // another time to empty _body.
  334. _body_reader = r;
  335. return;
  336. }
  337. butil::IOBuf body_seen = _body.movable();
  338. mu.unlock();
  339. for (size_t i = 0; i < body_seen.backing_block_num(); ++i) {
  340. butil::StringPiece blk = body_seen.backing_block(i);
  341. butil::Status st = r->OnReadOnePart(blk.data(), blk.size());
  342. if (!st.ok()) {
  343. r->OnEndOfMessage(st);
  344. // Make OnBody() or OnMessageComplete() fail on next call to
  345. // close the socket. If the message was already complete, the
  346. // socket will not be closed.
  347. pthread_once(&s_fail_all_read_once, CreateFailAllRead);
  348. r = s_fail_all_read;
  349. ntry = MAX_TRY;
  350. break;
  351. }
  352. }
  353. } while (true);
  354. }
  355. const http_parser_settings g_parser_settings = {
  356. &HttpMessage::on_message_begin,
  357. &HttpMessage::on_url,
  358. &HttpMessage::on_status,
  359. &HttpMessage::on_header_field,
  360. &HttpMessage::on_header_value,
  361. &HttpMessage::on_headers_complete,
  362. &HttpMessage::on_body_cb,
  363. &HttpMessage::on_message_complete_cb
  364. };
  365. HttpMessage::HttpMessage(bool read_body_progressively)
  366. : _parsed_length(0)
  367. , _stage(HTTP_ON_MESSAGE_BEGIN)
  368. , _read_body_progressively(read_body_progressively)
  369. , _body_reader(NULL)
  370. , _cur_value(NULL)
  371. , _vmsgbuilder(NULL)
  372. , _body_length(0) {
  373. http_parser_init(&_parser, HTTP_BOTH);
  374. _parser.data = this;
  375. }
  376. HttpMessage::~HttpMessage() {
  377. if (_body_reader) {
  378. ProgressiveReader* saved_body_reader = _body_reader;
  379. _body_reader = NULL;
  380. // Successfully ended message is ended in OnMessageComplete() or
  381. // SetBodyReader() and _body_reader should be null-ed. Non-null
  382. // _body_reader here just means the socket is broken before completion
  383. // of the message.
  384. saved_body_reader->OnEndOfMessage(
  385. butil::Status(ECONNRESET, "The socket was broken"));
  386. }
  387. }
  388. ssize_t HttpMessage::ParseFromArray(const char *data, const size_t length) {
  389. if (Completed()) {
  390. if (length == 0) {
  391. return 0;
  392. }
  393. LOG(ERROR) << "Append data(len=" << length
  394. << ") to already-completed message";
  395. return -1;
  396. }
  397. const size_t nprocessed =
  398. http_parser_execute(&_parser, &g_parser_settings, data, length);
  399. if (_parser.http_errno != 0) {
  400. // May try HTTP on other formats, failure is norm.
  401. RPC_VLOG << "Fail to parse http message, parser=" << _parser
  402. << ", buf=`" << butil::StringPiece(data, length) << '\'';
  403. return -1;
  404. }
  405. _parsed_length += nprocessed;
  406. return nprocessed;
  407. }
  408. ssize_t HttpMessage::ParseFromIOBuf(const butil::IOBuf &buf) {
  409. if (Completed()) {
  410. if (buf.empty()) {
  411. return 0;
  412. }
  413. LOG(ERROR) << "Append data(len=" << buf.size()
  414. << ") to already-completed message";
  415. return -1;
  416. }
  417. size_t nprocessed = 0;
  418. for (size_t i = 0; i < buf.backing_block_num(); ++i) {
  419. butil::StringPiece blk = buf.backing_block(i);
  420. if (blk.empty()) {
  421. // length=0 will be treated as EOF by http_parser, must skip.
  422. continue;
  423. }
  424. nprocessed += http_parser_execute(
  425. &_parser, &g_parser_settings, blk.data(), blk.size());
  426. if (_parser.http_errno != 0) {
  427. // May try HTTP on other formats, failure is norm.
  428. RPC_VLOG << "Fail to parse http message, parser=" << _parser
  429. << ", buf=`" << buf << '\'';
  430. return -1;
  431. }
  432. if (Completed()) {
  433. break;
  434. }
  435. }
  436. _parsed_length += nprocessed;
  437. return (ssize_t)nprocessed;
  438. }
  439. static void DescribeHttpParserFlags(std::ostream& os, unsigned int flags) {
  440. if (flags & F_CHUNKED) {
  441. os << "F_CHUNKED|";
  442. }
  443. if (flags & F_CONNECTION_KEEP_ALIVE) {
  444. os << "F_CONNECTION_KEEP_ALIVE|";
  445. }
  446. if (flags & F_CONNECTION_CLOSE) {
  447. os << "F_CONNECTION_CLOSE|";
  448. }
  449. if (flags & F_TRAILING) {
  450. os << "F_TRAILING|";
  451. }
  452. if (flags & F_UPGRADE) {
  453. os << "F_UPGRADE|";
  454. }
  455. if (flags & F_SKIPBODY) {
  456. os << "F_SKIPBODY|";
  457. }
  458. }
  459. std::ostream& operator<<(std::ostream& os, const http_parser& parser) {
  460. os << "{type=" << http_parser_type_name((http_parser_type)parser.type)
  461. << " flags=`";
  462. DescribeHttpParserFlags(os, parser.flags);
  463. os << "' state=" << http_parser_state_name(parser.state)
  464. << " header_state=" << http_parser_header_state_name(
  465. parser.header_state)
  466. << " http_errno=`" << http_errno_description(
  467. (http_errno)parser.http_errno)
  468. << "' index=" << parser.index
  469. << " nread=" << parser.nread
  470. << " content_length=" << parser.content_length
  471. << " http_major=" << parser.http_major
  472. << " http_minor=" << parser.http_minor;
  473. if (parser.type == HTTP_RESPONSE || parser.type == HTTP_BOTH) {
  474. os << " status_code=" << parser.status_code;
  475. }
  476. if (parser.type == HTTP_REQUEST || parser.type == HTTP_BOTH) {
  477. os << " method=" << HttpMethod2Str((HttpMethod)parser.method);
  478. }
  479. os << " upgrade=" << parser.upgrade
  480. << " data=" << parser.data
  481. << '}';
  482. return os;
  483. }
  484. #define BRPC_CRLF "\r\n"
  485. // Request format
  486. // Request = Request-Line ; Section 5.1
  487. // *(( general-header ; Section 4.5
  488. // | request-header ; Section 5.3
  489. // | entity-header ) CRLF) ; Section 7.1
  490. // CRLF
  491. // [ message-body ] ; Section 4.3
  492. // Request-Line = Method SP Request-URI SP HTTP-Version CRLF
  493. // Method = "OPTIONS" ; Section 9.2
  494. // | "GET" ; Section 9.3
  495. // | "HEAD" ; Section 9.4
  496. // | "POST" ; Section 9.5
  497. // | "PUT" ; Section 9.6
  498. // | "DELETE" ; Section 9.7
  499. // | "TRACE" ; Section 9.8
  500. // | "CONNECT" ; Section 9.9
  501. // | extension-method
  502. // extension-method = token
  503. void SerializeHttpRequest(butil::IOBuf* request,
  504. HttpHeader* h,
  505. const butil::EndPoint& remote_side,
  506. const butil::IOBuf* content) {
  507. butil::IOBufBuilder os;
  508. os << HttpMethod2Str(h->method()) << ' ';
  509. const URI& uri = h->uri();
  510. uri.PrintWithoutHost(os); // host is sent by "Host" header.
  511. os << " HTTP/" << h->major_version() << '.'
  512. << h->minor_version() << BRPC_CRLF;
  513. if (h->method() != HTTP_METHOD_GET) {
  514. h->RemoveHeader("Content-Length");
  515. // Never use "Content-Length" set by user.
  516. os << "Content-Length: " << (content ? content->length() : 0)
  517. << BRPC_CRLF;
  518. }
  519. //rfc 7230#section-5.4:
  520. //A client MUST send a Host header field in all HTTP/1.1 request
  521. //messages. If the authority component is missing or undefined for
  522. //the target URI, then a client MUST send a Host header field with an
  523. //empty field-value.
  524. //rfc 7231#sec4.3:
  525. //the request-target consists of only the host name and port number of
  526. //the tunnel destination, seperated by a colon. For example,
  527. //Host: server.example.com:80
  528. if (h->GetHeader("host") == NULL) {
  529. os << "Host: ";
  530. if (!uri.host().empty()) {
  531. os << uri.host();
  532. if (uri.port() >= 0) {
  533. os << ':' << uri.port();
  534. }
  535. } else if (remote_side.port != 0) {
  536. os << remote_side;
  537. }
  538. os << BRPC_CRLF;
  539. }
  540. if (!h->content_type().empty()) {
  541. os << "Content-Type: " << h->content_type()
  542. << BRPC_CRLF;
  543. }
  544. for (HttpHeader::HeaderIterator it = h->HeaderBegin();
  545. it != h->HeaderEnd(); ++it) {
  546. os << it->first << ": " << it->second << BRPC_CRLF;
  547. }
  548. if (h->GetHeader("Accept") == NULL) {
  549. os << "Accept: */*" BRPC_CRLF;
  550. }
  551. // The fake "curl" user-agent may let servers return plain-text results.
  552. if (h->GetHeader("User-Agent") == NULL) {
  553. os << "User-Agent: brpc/1.0 curl/7.0" BRPC_CRLF;
  554. }
  555. const std::string& user_info = h->uri().user_info();
  556. if (!user_info.empty() && h->GetHeader("Authorization") == NULL) {
  557. // NOTE: just assume user_info is well formatted, namely
  558. // "<user_name>:<password>". Users are very unlikely to add extra
  559. // characters in this part and even if users did, most of them are
  560. // invalid and rejected by http_parser_parse_url().
  561. std::string encoded_user_info;
  562. butil::Base64Encode(user_info, &encoded_user_info);
  563. os << "Authorization: Basic " << encoded_user_info << BRPC_CRLF;
  564. }
  565. os << BRPC_CRLF; // CRLF before content
  566. os.move_to(*request);
  567. if (h->method() != HTTP_METHOD_GET && content) {
  568. request->append(*content);
  569. }
  570. }
  571. // Response format
  572. // Response = Status-Line ; Section 6.1
  573. // *(( general-header ; Section 4.5
  574. // | response-header ; Section 6.2
  575. // | entity-header ) CRLF) ; Section 7.1
  576. // CRLF
  577. // [ message-body ] ; Section 7.2
  578. // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
  579. void SerializeHttpResponse(butil::IOBuf* response,
  580. HttpHeader* h,
  581. butil::IOBuf* content) {
  582. butil::IOBufBuilder os;
  583. os << "HTTP/" << h->major_version() << '.'
  584. << h->minor_version() << ' ' << h->status_code()
  585. << ' ' << h->reason_phrase() << BRPC_CRLF;
  586. if (content) {
  587. h->RemoveHeader("Content-Length");
  588. // Never use "Content-Length" set by user.
  589. // Always set Content-Length since lighttpd requires the header to be
  590. // set to 0 for empty content.
  591. os << "Content-Length: " << content->length() << BRPC_CRLF;
  592. }
  593. if (!h->content_type().empty()) {
  594. os << "Content-Type: " << h->content_type()
  595. << BRPC_CRLF;
  596. }
  597. for (HttpHeader::HeaderIterator it = h->HeaderBegin();
  598. it != h->HeaderEnd(); ++it) {
  599. os << it->first << ": " << it->second << BRPC_CRLF;
  600. }
  601. os << BRPC_CRLF; // CRLF before content
  602. os.move_to(*response);
  603. if (content) {
  604. response->append(butil::IOBuf::Movable(*content));
  605. }
  606. }
  607. #undef BRPC_CRLF
  608. } // namespace brpc