Example #1
0
bool Transport::splitHeader(CStrRef header, String &name, const char *&value) {
  int pos = header.find(':');

  if (pos != String::npos) {
    name = header.substr(0, pos);
    value = header.data() + pos;

    do {
      value++;
    } while (*value == ' ');

    return true;
  }

  // header("HTTP/1.0 404 Not Found");
  // header("HTTP/1.0 404");
  if (strncasecmp(header.data(), "http/", 5) == 0) {
    int pos1 = header.find(' ');
    if (pos1 != String::npos) {
      int pos2 = header.find(' ', pos1 + 1);
      if (pos2 == String::npos) pos2 = header.size();
      if (pos2 - pos1 > 1) {
        setResponse(atoi(header.data() + pos1),
                    getResponseInfo().empty() ? "splitHeader"
                                              : getResponseInfo().c_str()
                   );
        return false;
      }
    }
  }

  throw InvalidArgumentException("header", header.c_str());
}
Example #2
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);
}
Example #3
0
void ProxygenTransport::sendImpl(const void *data, int size, int code,
                                 bool chunked, bool eom) {
  assert(data);
  assert(!m_sendStarted || chunked);
  if (m_sendEnded) {
    // This should never happen, but when it does we have to bail out,
    // since there's no sensible way to send data at this point and
    // trying to do so will horribly corrupt memory.
    // TODO #2821803: Figure out whether this is caused by another bug
    // somewhere.
    return;
  }

  VLOG(4) << "sendImpl called with data size=" << size << ", code=" << code
          << ", chunked=" << chunked << ", eom=" << eom;
  eom |= !chunked;
  if (!m_sendStarted) {
    if (!chunked) {
      if (!m_response.getHeaders().exists(HTTP_HEADER_CONTENT_LENGTH)) {
        m_response.getHeaders().add(HTTP_HEADER_CONTENT_LENGTH,
                                    folly::to<std::string>(size));
      }
    } else {
      // Explicitly add Transfer-Encoding: chunked here.  libproxygen will only
      // add it for keep-alive connections
      m_response.getHeaders().set(HTTP_HEADER_TRANSFER_ENCODING, "chunked");
    }
    m_response.setStatusCode(code);
    auto const& reasonStr = getResponseInfo();
    const char* reason = reasonStr.empty() ?
      HTTPMessage::getDefaultReason(code) : reasonStr.c_str();
    m_response.setStatusMessage(reason);
    m_response.setHTTPVersion(1, 1);
    m_response.setIsChunked(chunked);
    m_response.dumpMessage(4);
    m_server->putResponseMessage(
      ResponseMessage(shared_from_this(),
                      ResponseMessage::Type::HEADERS, 0,
                      chunked, data, size, eom));
    m_sendStarted = true;
  } else {
    m_server->putResponseMessage(
      ResponseMessage(shared_from_this(),
                      ResponseMessage::Type::BODY, 0,
                      chunked, data, size, eom));
  }

  if (eom) {
    m_sendEnded = true;
  }

  if (chunked) {
    assert(m_method != Method::HEAD);
    /*
     * Chunked replies are sent async, so there is no way to know the
     * time it took to flush the response, but tracking the bytes sent is
     * very useful.
     */
    onChunkedProgress(size);
  }
}