Exemplo n.º 1
0
TEST(HTTP1xCodecTest, Test1xxConnectionHeader) {
  HTTP1xCodec upstream(TransportDirection::UPSTREAM);
  HTTP1xCodec downstream(TransportDirection::DOWNSTREAM);
  HTTP1xCodecCallback callbacks;
  upstream.setCallback(&callbacks);
  HTTPMessage resp;
  resp.setStatusCode(100);
  resp.setHTTPVersion(1, 1);
  resp.getHeaders().add(HTTP_HEADER_CONNECTION, "Upgrade");
  folly::IOBufQueue writeBuf(folly::IOBufQueue::cacheChainLength());
  auto streamID = downstream.createStream();
  downstream.generateHeader(writeBuf, streamID, resp);
  upstream.onIngress(*writeBuf.front());
  EXPECT_EQ(callbacks.headersComplete, 1);
  EXPECT_EQ(
    callbacks.msg_->getHeaders().getSingleOrEmpty(HTTP_HEADER_CONNECTION),
    "Upgrade");
  resp.setStatusCode(200);
  resp.getHeaders().remove(HTTP_HEADER_CONNECTION);
  resp.getHeaders().add(HTTP_HEADER_CONTENT_LENGTH, "0");
  writeBuf.move();
  downstream.generateHeader(writeBuf, streamID, resp);
  upstream.onIngress(*writeBuf.front());
  EXPECT_EQ(callbacks.headersComplete, 2);
  EXPECT_EQ(
    callbacks.msg_->getHeaders().getSingleOrEmpty(HTTP_HEADER_CONNECTION),
    "keep-alive");
}
Exemplo n.º 2
0
HTTPMessage getGetRequest(const std::string& url) {
  HTTPMessage req;
  req.setMethod("GET");
  req.setURL(url);
  req.setHTTPVersion(1, 1);
  req.getHeaders().set(HTTP_HEADER_HOST, "www.foo.com");
  return req;
}
Exemplo n.º 3
0
HTTPMessage getPostRequest() {
  HTTPMessage req;
  req.setMethod("POST");
  req.setURL<string>("/");
  req.setHTTPVersion(1, 1);
  req.getHeaders().set(HTTP_HEADER_HOST, "www.foo.com");
  req.getHeaders().set(HTTP_HEADER_CONTENT_LENGTH, "200");
  return req;
}
Exemplo n.º 4
0
HTTPMessage getChunkedPostRequest() {
  HTTPMessage req;
  req.setMethod("POST");
  req.setURL<string>("/");
  req.setHTTPVersion(1, 1);
  req.setIsChunked(true);
  req.getHeaders().set(HTTP_HEADER_HOST, "www.foo.com");
  req.getHeaders().set(HTTP_HEADER_TRANSFER_ENCODING, "chunked");
  return req;
}
Exemplo n.º 5
0
HTTPMessage getPostRequest(uint32_t contentLength) {
  HTTPMessage req;
  req.setMethod("POST");
  req.setURL<string>("/");
  req.setHTTPVersion(1, 1);
  req.getHeaders().set(HTTP_HEADER_HOST, "www.foo.com");
  req.getHeaders().set(HTTP_HEADER_CONTENT_LENGTH,
                       folly::to<string>(contentLength));
  return req;
}
Exemplo n.º 6
0
HTTPMessage getBigGetRequest(const std::string& url) {
  HTTPMessage req;
  req.setMethod("GET");
  req.setURL(url);
  req.setHTTPVersion(1, 1);
  req.getHeaders().set(HTTP_HEADER_HOST, "www.foo.com");
  req.getHeaders().add(HTTP_HEADER_USER_AGENT, "coolio");
  req.getHeaders().add(
      "x-huge-header",
      std::string(http2::kMaxFramePayloadLengthMin, '!'));
  return req;
}
Exemplo n.º 7
0
void ProxygenTransport::sendErrorResponse(uint32_t code) noexcept {
  HTTPMessage response;
  response.setHTTPVersion(1, 1);
  response.setStatusCode(code);
  response.setStatusMessage(HTTPMessage::getDefaultReason(code));
  response.getHeaders().add(HTTP_HEADER_CONNECTION, "close");
  CHECK(!m_sendStarted);
  m_sendStarted = true;
  m_sendEnded = true;
  m_responseCode = code;
  m_responseCodeInfo = response.getStatusMessage();
  m_server->onRequestError(this);
  m_clientTxn->sendHeaders(response);
  m_clientTxn->sendEOM();
}
Exemplo n.º 8
0
bool
HTTPDownstreamSession::onNativeProtocolUpgrade(
  HTTPCodec::StreamID streamID, CodecProtocol protocol,
  const std::string& protocolString,
  HTTPMessage& msg) {
  VLOG(4) << *this << " onNativeProtocolUpgrade streamID=" << streamID <<
    " protocol=" << protocolString;
  auto txn = findTransaction(streamID);
  CHECK(txn);
  if (txn->canSendHeaders()) {
    // Create the new Codec
    auto codec = HTTPCodecFactory::getCodec(protocol,
                                            TransportDirection::DOWNSTREAM);
    CHECK(codec);
    if (!codec->onIngressUpgradeMessage(msg)) {
      VLOG(4) << *this << " codec rejected upgrade";
      return false;
    }

    // Send a 101 Switching Protocols message while we still have HTTP codec
    // Note: it's possible that the client timed out waiting for a
    // 100-continue and ended up here first.  In this case the 100 may go
    // out in the new protocol
    HTTPMessage switchingProtos;
    switchingProtos.setHTTPVersion(1, 1);
    switchingProtos.setStatusCode(101);
    switchingProtos.setStatusMessage("Switching Protocols");
    switchingProtos.getHeaders().set(HTTP_HEADER_UPGRADE, protocolString);
    txn->sendHeaders(switchingProtos);
    // no sendEOM for 1xx

    // This will actually switch the protocol
    bool ret = HTTPSession::onNativeProtocolUpgradeImpl(
      streamID, std::move(codec), protocolString);
    if (ret) {
      codec_->addPriorityNodes(txnEgressQueue_, writeBuf_, 0);
    }
    return ret;
  } else {
    VLOG(4) << *this << " plaintext upgrade failed due to early response";
    return false;
  }
}
Exemplo n.º 9
0
TEST(HTTP1xCodecTest, Test09Resp) {
  HTTP1xCodec codec(TransportDirection::UPSTREAM);
  HTTP1xCodecCallback callbacks;
  HTTPMessage req;
  auto id = codec.createStream();
  req.setHTTPVersion(0, 9);
  req.setMethod(HTTPMethod::GET);
  req.setURL("/");
  codec.setCallback(&callbacks);
  folly::IOBufQueue buf;
  codec.generateHeader(buf, id, req, 0, true);
  auto buffer = folly::IOBuf::copyBuffer(
    string("iamtheverymodelofamodernmajorgeneral"));
  codec.onIngress(*buffer);
  EXPECT_EQ(callbacks.headersComplete, 1);
  EXPECT_EQ(callbacks.bodyLen, buffer->computeChainDataLength());
  EXPECT_EQ(callbacks.messageComplete, 0);
  codec.onIngressEOF();
  EXPECT_EQ(callbacks.messageComplete, 1);
}
Exemplo n.º 10
0
TEST(HTTP1xCodecTest, TestGetRequestChunkedResponse) {
  HTTP1xCodec codec(TransportDirection::DOWNSTREAM);
  HTTP1xCodecCallback callbacks;
  codec.setCallback(&callbacks);
  auto txnID = codec.createStream();

  // Generate a GET request
  auto reqBuf = folly::IOBuf::copyBuffer(
      "GET /www.facebook.com HTTP/1.1\nHost: www.facebook.com\n\n");
  codec.onIngress(*reqBuf);
  EXPECT_EQ(callbacks.headersComplete, 1);

  // Generate chunked response with body
  HTTPMessage resp;
  resp.setHTTPVersion(1, 1);
  resp.setStatusCode(200);
  resp.setIsChunked(true);
  resp.getHeaders().set(HTTP_HEADER_TRANSFER_ENCODING, "chunked");
  folly::IOBufQueue respBuf(folly::IOBufQueue::cacheChainLength());
  codec.generateHeader(respBuf, txnID, resp, 0, false);

  auto headerFromBuf = respBuf.split(respBuf.chainLength());

  string resp1("Hello");
  auto body1 = folly::IOBuf::copyBuffer(resp1);

  string resp2("");
  auto body2 = folly::IOBuf::copyBuffer(resp2);

  codec.generateBody(respBuf, txnID, std::move(body1), HTTPCodec::NoPadding,
                     false);

  auto bodyFromBuf = respBuf.split(respBuf.chainLength());
  ASSERT_EQ("5\r\nHello\r\n", bodyFromBuf->moveToFbString());

  codec.generateBody(respBuf, txnID, std::move(body2), HTTPCodec::NoPadding,
                     true);

  bodyFromBuf = respBuf.split(respBuf.chainLength());
  ASSERT_EQ("0\r\n\r\n", bodyFromBuf->moveToFbString());
}
Exemplo n.º 11
0
TEST(HTTP1xCodecTest, TestHeadRequestChunkedResponse) {
  HTTP1xCodec codec(TransportDirection::DOWNSTREAM);
  HTTP1xCodecCallback callbacks;
  codec.setCallback(&callbacks);
  auto txnID = codec.createStream();

  // Generate a HEAD request
  auto reqBuf = folly::IOBuf::copyBuffer(
      "HEAD /www.facebook.com HTTP/1.1\nHost: www.facebook.com\n\n");
  codec.onIngress(*reqBuf);
  EXPECT_EQ(callbacks.headersComplete, 1);

  // Generate chunked response with no body
  HTTPMessage resp;
  resp.setHTTPVersion(1, 1);
  resp.setStatusCode(200);
  resp.setIsChunked(true);
  resp.getHeaders().set(HTTP_HEADER_TRANSFER_ENCODING, "chunked");
  folly::IOBufQueue respBuf(folly::IOBufQueue::cacheChainLength());
  codec.generateHeader(respBuf, txnID, resp, 0, true);
  auto respStr = respBuf.move()->moveToFbString();
  EXPECT_TRUE(respStr.find("0\r\n") == string::npos);
}
Exemplo n.º 12
0
TEST(HTTP1xCodecTest, TestChunkedUpstream) {
  HTTP1xCodec codec(TransportDirection::UPSTREAM);

  auto txnID = codec.createStream();

  HTTPMessage msg;
  msg.setHTTPVersion(1, 1);
  msg.setURL("https://www.facebook.com/");
  msg.getHeaders().set(HTTP_HEADER_HOST, "www.facebook.com");
  msg.getHeaders().set(HTTP_HEADER_TRANSFER_ENCODING, "chunked");
  msg.setIsChunked(true);

  HTTPHeaderSize size;

  folly::IOBufQueue buf(folly::IOBufQueue::cacheChainLength());
  codec.generateHeader(buf, txnID, msg, 0, false, &size);
  auto headerFromBuf = buf.split(buf.chainLength());

  string req1("Hello");
  auto body1 = folly::IOBuf::copyBuffer(req1);

  string req2("World");
  auto body2 = folly::IOBuf::copyBuffer(req2);

  codec.generateBody(buf, txnID, std::move(body1), HTTPCodec::NoPadding,
                     false);

  auto bodyFromBuf = buf.split(buf.chainLength());
  ASSERT_EQ("5\r\nHello\r\n", bodyFromBuf->moveToFbString());

  codec.generateBody(buf, txnID, std::move(body2), HTTPCodec::NoPadding,
                     true);
  LOG(WARNING) << "len chain" << buf.chainLength();

  auto eomFromBuf = buf.split(buf.chainLength());
  ASSERT_EQ("5\r\nWorld\r\n0\r\n\r\n", eomFromBuf->moveToFbString());
}
Exemplo n.º 13
0
void ProxygenTransport::onHeadersComplete(
  unique_ptr<HTTPMessage> msg) noexcept {

  Timer::GetMonotonicTime(m_requestStart);
  m_request = std::move(msg);
  if (m_request->isSecure()) {
    setSSL();
  }
  m_request->dumpMessage(4);
  auto method = m_request->getMethod();
  const auto& methodStr = m_request->getMethodString();
  if (method == HTTPMethod::GET) {
    m_method = Transport::Method::GET;
  } else if (method == HTTPMethod::POST ||
             s_post_methods.find(methodStr) != s_post_methods.end()) {
    m_method = Transport::Method::POST;
  } else if (method == HTTPMethod::HEAD) {
    m_method = Transport::Method::HEAD;
  } else if (method == HTTPMethod::CONNECT) {
    sendErrorResponse(400 /* Bad Request */);
    return;
  } else {
    // looks like proxygen HTTP parser understands a few more methods
    // than libevent:
    //   TRACE, COPY, MOVE, MKACTIVITY, CHECKOUT, MERGE, MSEARCH, NOTIFY,
    //   SUBSCRIBE, UNSUBSCRIBE, PATCH
    sendErrorResponse(400 /* Bad Request */);
    return;
  }
  m_extended_method = methodStr.c_str();

  const auto& headers = m_request->getHeaders();
  headers.forEach([&] (const std::string &header, const std::string &val) {
      m_requestHeaders[header.c_str()].push_back(val.c_str());
    });

  if (m_method == Transport::Method::POST && m_request->isHTTP1_1()) {
    const std::string& expectation =
      headers.getSingleOrEmpty(HTTP_HEADER_EXPECT);
    if (!expectation.empty()) {
      bool sendEom = false;
      HTTPMessage response;
      if (!boost::iequals(expectation, "100-continue")) {
        response.setStatusCode(417);
        response.setStatusMessage(HTTPMessage::getDefaultReason(417));
        response.getHeaders().add(HTTP_HEADER_CONNECTION, "close");
        sendEom = true;
      } else {
        response.setStatusCode(100);
        response.setStatusMessage(HTTPMessage::getDefaultReason(100));
      }
      response.setHTTPVersion(1, 1);
      response.dumpMessage(4);
      m_clientTxn->sendHeaders(response);
      if (sendEom) {
        m_responseCode = response.getStatusCode();
        m_responseCodeInfo = response.getStatusMessage();
        m_server->onRequestError(this);
        m_clientTxn->sendEOM();
        // this object is no longer valid
        return;
      }
    }
  }

  if (!bufferRequest()) {
    m_enqueued = true;
    m_server->onRequest(shared_from_this());
  } // otherwise we wait for EOM
}
Exemplo n.º 14
0
TEST(HTTPMessage, TestKeepaliveCheck) {
  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 0);
    EXPECT_FALSE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 1);
    EXPECT_TRUE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 1);
    msg.getHeaders().add("Connection", "close");
    EXPECT_FALSE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 1);
    msg.getHeaders().add("Connection", "ClOsE");
    EXPECT_FALSE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 1);
    msg.getHeaders().add("Connection", "foo,bar");
    EXPECT_TRUE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 1);
    msg.getHeaders().add("Connection", "foo,bar");
    msg.getHeaders().add("Connection", "abc,CLOSE,def");
    msg.getHeaders().add("Connection", "xyz");
    EXPECT_FALSE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 1);
    msg.getHeaders().add("Connection", "foo,bar");
    msg.getHeaders().add("Connection", "abc ,  CLOSE , def");
    msg.getHeaders().add("Connection", "xyz");
    EXPECT_FALSE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 1);
    msg.getHeaders().add("Connection", "  close ");
    EXPECT_FALSE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 1);
    msg.getHeaders().add("Connection", ",  close ");
    EXPECT_FALSE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 1);
    msg.getHeaders().add("Connection", "  close , ");
    EXPECT_FALSE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 0);
    msg.getHeaders().add("Connection", "Keep-Alive");
    EXPECT_TRUE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 0);
    msg.getHeaders().add("Connection", "keep-alive");
    EXPECT_TRUE(msg.computeKeepalive());
  }

  {
    HTTPMessage msg;
    msg.setHTTPVersion(1, 0);
    msg.getHeaders().add("Connection", "keep-alive");
    msg.getHeaders().add("Connection", "close");
    EXPECT_FALSE(msg.computeKeepalive());
  }
}