Request format Request = Request-Line ; Section 5.1 (( general-header ; Section 4.5 | request-header ; Section 5.3 | entity-header ) CRLF) ; Section 7.1 CRLF [ message-body ] ; Section 4.3 Request-Line = Method SP Request-URI SP HTTP-Version CRLF Method = "OPTIONS" ; Section 9.2 | "GET" ; Section 9.3 | "HEAD"
| 588 | // | extension-method |
| 589 | // extension-method = token |
| 590 | void MakeRawHttpRequest(butil::IOBuf* request, |
| 591 | HttpHeader* h, |
| 592 | const butil::EndPoint& remote_side, |
| 593 | const butil::IOBuf* content) { |
| 594 | butil::IOBufBuilder os; |
| 595 | os << HttpMethod2Str(h->method()) << ' '; |
| 596 | const URI& uri = h->uri(); |
| 597 | uri.PrintWithoutHost(os); // host is sent by "Host" header. |
| 598 | os << " HTTP/" << h->major_version() << '.' |
| 599 | << h->minor_version() << BRPC_CRLF; |
| 600 | // Never use "Content-Length" set by user. |
| 601 | h->RemoveHeader("Content-Length"); |
| 602 | const std::string* transfer_encoding = h->GetHeader("Transfer-Encoding"); |
| 603 | if (h->method() == HTTP_METHOD_GET) { |
| 604 | h->RemoveHeader("Transfer-Encoding"); |
| 605 | } else if (!transfer_encoding) { |
| 606 | // https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2 |
| 607 | // A sender MUST NOT send a Content-Length header field in any message |
| 608 | // that contains a Transfer-Encoding header field. |
| 609 | os << "Content-Length: " << (content ? content->length() : 0) |
| 610 | << BRPC_CRLF; |
| 611 | } |
| 612 | // `Expect: 100-continue' is not supported, remove it. |
| 613 | const std::string* expect = h->GetHeader("Expect"); |
| 614 | if (expect && *expect == "100-continue") { |
| 615 | h->RemoveHeader("Expect"); |
| 616 | } |
| 617 | //rfc 7230#section-5.4: |
| 618 | //A client MUST send a Host header field in all HTTP/1.1 request |
| 619 | //messages. If the authority component is missing or undefined for |
| 620 | //the target URI, then a client MUST send a Host header field with an |
| 621 | //empty field-value. |
| 622 | //rfc 7231#sec4.3: |
| 623 | //the request-target consists of only the host name and port number of |
| 624 | //the tunnel destination, separated by a colon. For example, |
| 625 | //Host: server.example.com:80 |
| 626 | if (h->GetHeader("host") == NULL) { |
| 627 | os << "Host: "; |
| 628 | if (!uri.host().empty()) { |
| 629 | os << uri.host(); |
| 630 | if (uri.port() >= 0) { |
| 631 | os << ':' << uri.port(); |
| 632 | } |
| 633 | } else if (remote_side.port != 0) { |
| 634 | os << remote_side; |
| 635 | } |
| 636 | os << BRPC_CRLF; |
| 637 | } |
| 638 | if (!h->content_type().empty()) { |
| 639 | os << "Content-Type: " << h->content_type() |
| 640 | << BRPC_CRLF; |
| 641 | } |
| 642 | for (HttpHeader::HeaderIterator it = h->HeaderBegin(); |
| 643 | it != h->HeaderEnd(); ++it) { |
| 644 | os << it->first << ": " << it->second << BRPC_CRLF; |
| 645 | } |
| 646 | if (h->GetHeader("Accept") == NULL) { |
| 647 | os << "Accept: */*" BRPC_CRLF; |