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()); } }
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(); }
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()); } }