Ejemplo n.º 1
0
void FastCGITransport::sendResponseHeaders(IOBufQueue& queue, int code) {
  CHECK(!m_headersSent);
  m_headersSent = true;

  if (code != 200) {
    queue.append(s_status);
    queue.append(std::to_string(code));
    auto reasonStr = getResponseInfo();
    if (reasonStr.empty()) {
      reasonStr = HttpProtocol::GetReasonString(code);
    }
    queue.append(s_space);
    queue.append(reasonStr);
    queue.append(s_newline);
  }

  for (auto& header : m_responseHeaders) {
    for (auto& value : header.second) {
      queue.append(header.first);
      queue.append(s_colon);
      queue.append(value);
      queue.append(s_newline);
    }
  }
  queue.append(s_newline);
}
Ejemplo n.º 2
0
TEST_F(BroadcastHandlerTest, OnCompleted) {
  // Test with EOF on the handler
  EXPECT_CALL(*decoder, decode(_, _, _, _))
      .WillRepeatedly(
          Invoke([&](MockByteToMessageDecoder<std::string>::Context*,
                     IOBufQueue& q, std::string& data, size_t&) {
            auto buf = q.move();
            if (buf) {
              buf->coalesce();
              data = buf->moveToFbString().toStdString();
              return true;
            }
            return false;
          }));

  InSequence dummy;

  // Add a subscriber
  EXPECT_EQ(handler->subscribe(&subscriber0), 0);

  EXPECT_CALL(subscriber0, onNext("data1")).Times(1);

  // Push some data
  IOBufQueue q;
  q.append(IOBuf::copyBuffer("data1"));
  pipeline->read(q);
  q.clear();

  // Add another subscriber
  EXPECT_EQ(handler->subscribe(&subscriber1), 1);

  EXPECT_CALL(subscriber0, onNext("data2")).Times(1);
  EXPECT_CALL(subscriber1, onNext("data2")).Times(1);

  // Push more data
  q.append(IOBuf::copyBuffer("data2"));
  pipeline->read(q);
  q.clear();

  // Unsubscribe one of the subscribers
  handler->unsubscribe(0);

  EXPECT_CALL(subscriber1, onCompleted()).Times(1);

  EXPECT_CALL(*handler, close(_))
      .WillOnce(InvokeWithoutArgs([this] {
        pipeline.reset();
        return makeFuture();
      }));

  // The handler should be deleted now
  handler->readEOF(nullptr);
}
Ejemplo n.º 3
0
void FastCGITransport::sendResponseHeaders(IOBufQueue& queue) {
  CHECK(!m_headersSent);
  m_headersSent = true;

  for (auto header : m_responseHeaders) {
    for (auto value : header.second) {
      queue.append(header.first);
      queue.append(": ");
      queue.append(value);
      queue.append("\r\n");
    }
  }
  queue.append("\r\n");
}
Ejemplo n.º 4
0
void helper<ProtocolReader, ProtocolWriter>::process_exn(
    const char* func,
    const string& msg,
    unique_ptr<ResponseChannel::Request> req,
    Cpp2RequestContext* ctx,
    EventBase* eb,
    int32_t protoSeqId) {
  ProtocolWriter oprot;
  if (req) {
    LOG(ERROR) << msg << " in function " << func;
    TApplicationException x(msg);
    IOBufQueue queue = helper_w<ProtocolWriter>::write_exn(
        func, &oprot, protoSeqId, nullptr, x);
    queue.append(THeader::transform(
          queue.move(),
          ctx->getHeader()->getWriteTransforms(),
          ctx->getHeader()->getMinCompressBytes()));
    auto queue_mw = makeMoveWrapper(move(queue));
    auto req_mw = makeMoveWrapper(move(req));
    eb->runInEventBaseThread([=]() mutable {
      (*req_mw)->sendReply(queue_mw->move());
    });
  } else {
    LOG(ERROR) << msg << " in oneway function " << func;
  }
}
Ejemplo n.º 5
0
void FastCGITransport::sendResponseHeaders(IOBufQueue& queue, int code) {
  auto appender = [&](folly::StringPiece sp) mutable { queue.append(sp); };
  if (code != 200) {
    auto info = getResponseInfo();
    auto reason = !info.empty() ? info : HttpProtocol::GetReasonString(code);

    folly::format("Status: {} {}\r\n", code, reason)(appender);
  }

  for (auto& header : m_responseHeaders) {
    for (auto& value : header.second) {
      folly::format("{}: {}\r\n", header.first, value)(appender);
    }
  }

  queue.append("\r\n", 2);
}
Ejemplo n.º 6
0
bool KVParser::parseKeyValueContent(Cursor& cursor,
                                    size_t& available,
                                    size_t& length,
                                    IOBufQueue& queue) {
  std::unique_ptr<IOBuf> buf;
  size_t len = cursor.cloneAtMost(buf, length);
  queue.append(std::move(buf));
  assert(length >= len);
  length -= len;
  assert(available >= len);
  available -= len;
  return (length == 0);
}
Ejemplo n.º 7
0
void FastCGITransport::sendImpl(const void *data, int size, int code,
                                bool chunked) {
  IOBufQueue queue;
  if (!m_headersSent) {
    sendResponseHeaders(queue, code);
  }
  queue.append(IOBuf::copyBuffer(data, size));
  folly::MoveWrapper<std::unique_ptr<IOBuf>> chain_wrapper(queue.move());
  Callback* callback = m_callback;
  auto fn = [callback, chain_wrapper]() mutable {
    if (callback) {
      callback->onStdOut(std::move(*chain_wrapper));
    }
  };
  m_connection->getEventBase()->runInEventBaseThread(fn);
}
Ejemplo n.º 8
0
void FastCGITransport::sendResponseHeaders(IOBufQueue& queue, int code) {
  CHECK(!m_headersSent);
  m_headersSent = true;

  if (code != 200) {
    queue.append(s_status);
    queue.append(std::to_string(code));
    queue.append(s_newline);
  }

  for (auto& header : m_responseHeaders) {
    for (auto& value : header.second) {
      queue.append(header.first);
      queue.append(s_colon);
      queue.append(value);
      queue.append(s_newline);
    }
  }
  queue.append(s_newline);
}
Ejemplo n.º 9
0
TEST(CommunicateSubprocessTest, Duplex2) {
  checkFdLeak([] {
    // Pipe 200,000 lines through sed
    const size_t numCopies = 100000;
    auto iobuf = IOBuf::copyBuffer("this is a test\nanother line\n");
    IOBufQueue input;
    for (size_t n = 0; n < numCopies; ++n) {
      input.append(iobuf->clone());
    }

    std::vector<std::string> cmd({
      "sed", "-u",
      "-e", "s/a test/a successful test/",
      "-e", "/^another line/w/dev/stderr",
    });
    auto options = Subprocess::pipeStdin().pipeStdout().pipeStderr().usePath();
    Subprocess proc(cmd, options);
    auto out = proc.communicateIOBuf(std::move(input));
    proc.waitChecked();

    // Convert stdout and stderr to strings so we can call split() on them.
    fbstring stdoutStr;
    if (out.first.front()) {
      stdoutStr = out.first.move()->moveToFbString();
    }
    fbstring stderrStr;
    if (out.second.front()) {
      stderrStr = out.second.move()->moveToFbString();
    }

    // stdout should be a copy of stdin, with "a test" replaced by
    // "a successful test"
    std::vector<StringPiece> stdoutLines;
    split('\n', stdoutStr, stdoutLines);
    EXPECT_EQ(numCopies * 2 + 1, stdoutLines.size());
    // Strip off the trailing empty line
    if (!stdoutLines.empty()) {
      EXPECT_EQ("", stdoutLines.back());
      stdoutLines.pop_back();
    }
    size_t linenum = 0;
    for (const auto& line : stdoutLines) {
      if ((linenum & 1) == 0) {
        EXPECT_EQ("this is a successful test", line);
      } else {
        EXPECT_EQ("another line", line);
      }
      ++linenum;
    }

    // stderr should only contain the lines containing "another line"
    std::vector<StringPiece> stderrLines;
    split('\n', stderrStr, stderrLines);
    EXPECT_EQ(numCopies + 1, stderrLines.size());
    // Strip off the trailing empty line
    if (!stderrLines.empty()) {
      EXPECT_EQ("", stderrLines.back());
      stderrLines.pop_back();
    }
    for (const auto& line : stderrLines) {
      EXPECT_EQ("another line", line);
    }
  });
}
Ejemplo n.º 10
0
TEST_F(BroadcastHandlerTest, BufferedRead) {
  // Test with decoder that buffers data based on some local logic
  // before pushing to subscribers
  IOBufQueue bufQueue{IOBufQueue::cacheChainLength()};
  EXPECT_CALL(*decoder, decode(_, _, _, _))
      .WillRepeatedly(
          Invoke([&](MockByteToMessageDecoder<std::string>::Context*,
                     IOBufQueue& q, std::string& data, size_t&) {
            bufQueue.append(q);
            if (bufQueue.chainLength() < 5) {
              return false;
            }
            auto buf = bufQueue.move();
            buf->coalesce();
            data = buf->moveToFbString().toStdString();
            return true;
          }));

  InSequence dummy;

  // Add a subscriber
  EXPECT_EQ(handler->subscribe(&subscriber0), 0);

  EXPECT_CALL(subscriber0, onNext("data1")).Times(1);

  // Push some fragmented data
  IOBufQueue q;
  q.append(IOBuf::copyBuffer("da"));
  pipeline->read(q);
  q.clear();
  q.append(IOBuf::copyBuffer("ta1"));
  pipeline->read(q);
  q.clear();

  // Push more fragmented data. onNext shouldn't be called yet.
  q.append(IOBuf::copyBuffer("dat"));
  pipeline->read(q);
  q.clear();
  q.append(IOBuf::copyBuffer("a"));
  pipeline->read(q);
  q.clear();

  // Add another subscriber
  EXPECT_EQ(handler->subscribe(&subscriber1), 1);

  EXPECT_CALL(subscriber0, onNext("data3data4")).Times(1);
  EXPECT_CALL(subscriber1, onNext("data3data4")).Times(1);

  // Push rest of the fragmented data. The entire data should be pushed
  // to both subscribers.
  q.append(IOBuf::copyBuffer("3data4"));
  pipeline->read(q);
  q.clear();

  EXPECT_CALL(subscriber0, onNext("data2")).Times(1);
  EXPECT_CALL(subscriber1, onNext("data2")).Times(1);

  // Push some unfragmented data
  q.append(IOBuf::copyBuffer("data2"));
  pipeline->read(q);
  q.clear();

  EXPECT_CALL(*handler, close(_))
      .WillOnce(InvokeWithoutArgs([this] {
        pipeline.reset();
        return makeFuture();
      }));

  // Unsubscribe all subscribers. The handler should be deleted now.
  handler->unsubscribe(0);
  handler->unsubscribe(1);
}