Example #1
0
void Transport::sendRawLocked(void *data, int size, int code /* = 200 */,
                              bool compressed /* = false */,
                              bool chunked /* = false */,
                              const char *codeInfo /* = "" */
                              ) {
  if (!compressed && RuntimeOption::ForceChunkedEncoding) {
    chunked = true;
  }
  if (m_chunkedEncoding) {
    chunked = true;
    assert(!compressed);
  } else if (chunked) {
    m_chunkedEncoding = true;
    assert(!compressed);
  }

  // I don't think there is any need to send an empty chunk, other than sending
  // out headers earlier, which seems to be a useless feature.
  if (chunked && size == 0) {
    return;
  }

  if (!m_headerCallbackDone && !m_headerCallback.isNull()) {
    // We could use m_headerSent here, however it seems we can still
    // end up in an infinite loop when:
    // m_headerCallback calls flush()
    // flush() triggers php's recursion guard
    // the recursion guard calls back into m_headerCallback
    m_headerCallbackDone = true;
    vm_call_user_func(m_headerCallback, null_array);
  }

  // compression handling
  ServerStatsHelper ssh("send");
  String response = prepareResponse(data, size, compressed, !chunked);

  if (m_responseCode < 0) {
    m_responseCode = code;
    m_responseCodeInfo = codeInfo ? codeInfo: "";
  }

  // HTTP header handling
  if (!m_headerSent) {
    String orig_response((const char *)data, size, CopyString);
    prepareHeaders(compressed, chunked, response, orig_response);
    m_headerSent = true;
  }

  m_responseSize += response.size();
  ServerStats::SetThreadMode(ServerStats::ThreadMode::Writing);
  sendImpl(response.data(), response.size(), m_responseCode, chunked);
  ServerStats::SetThreadMode(ServerStats::ThreadMode::Processing);

  ServerStats::LogBytes(size);
  if (RuntimeOption::EnableStats && RuntimeOption::EnableWebStats) {
    ServerStats::Log("network.uncompressed", size);
    ServerStats::Log("network.compressed", response.size());
  }
}
Example #2
0
void Transport::onSendEnd() {
  if (m_compressor && m_chunkedEncoding) {
    bool compressed = false;
    String response = prepareResponse("", 0, compressed, true);
    sendImpl(response.data(), response.size(), m_responseCode, true);
  }
  onSendEndImpl();
}
Example #3
0
void Transport::sendRaw(void *data, int size, int code /* = 200 */,
                        bool compressed /* = false */,
                        bool chunked /* = false */,
                        const char *codeInfo /* = "" */
                       ) {
    ASSERT(data || size == 0);
    ASSERT(size >= 0);
    FiberWriteLock lock(this);

    if (!compressed && RuntimeOption::ForceChunkedEncoding) {
        chunked = true;
    }
    if (m_chunkedEncoding) {
        chunked = true;
        ASSERT(!compressed);
    } else if (chunked) {
        m_chunkedEncoding = true;
        ASSERT(!compressed);
    }

    // I don't think there is any need to send an empty chunk, other than sending
    // out headers earlier, which seems to be a useless feature.
    if (chunked && size == 0) {
        return;
    }

    // compression handling
    ServerStatsHelper ssh("send");
    String response = prepareResponse(data, size, compressed, !chunked);

    if (m_responseCode < 0) {
        m_responseCode = code;
        m_responseCodeInfo = codeInfo ? codeInfo: "";
    }

    // HTTP header handling
    if (!m_headerSent) {
        prepareHeaders(compressed, data, size);
        m_headerSent = true;
    }

    m_responseSize += response.size();
    ServerStats::SetThreadMode(ServerStats::Writing);
    sendImpl(response.data(), response.size(), m_responseCode, chunked);
    ServerStats::SetThreadMode(ServerStats::Processing);

    ServerStats::LogBytes(size);
    if (RuntimeOption::EnableStats && RuntimeOption::EnableWebStats) {
        ServerStats::Log("network.uncompressed", size);
        ServerStats::Log("network.compressed", response.size());
    }
}