void Transport::prepareHeaders(bool compressed, const void *data, int size) { for (HeaderMap::const_iterator iter = m_responseHeaders.begin(); iter != m_responseHeaders.end(); ++iter) { const vector<string> &values = iter->second; for (unsigned int i = 0; i < values.size(); i++) { addHeaderImpl(iter->first.c_str(), values[i].c_str()); } } for (CookieMap::const_iterator iter = m_responseCookies.begin(); iter != m_responseCookies.end(); ++iter) { addHeaderImpl("Set-Cookie", iter->second.c_str()); } if (compressed) { addHeaderImpl("Content-Encoding", "gzip"); removeHeaderImpl("Content-Length"); if (m_responseHeaders.find("Content-MD5") != m_responseHeaders.end()) { String response((const char *)data, size, AttachLiteral); removeHeaderImpl("Content-MD5"); addHeaderImpl("Content-MD5", StringUtil::Base64Encode( StringUtil::MD5(response, true)).c_str()); } } if (m_responseHeaders.find("Content-Type") == m_responseHeaders.end() && m_responseCode != 304) { string contentType = "text/html; charset=" + RuntimeOption::DefaultCharsetName; addHeaderImpl("Content-Type", contentType.c_str()); } if (RuntimeOption::ExposeHPHP) { addHeaderImpl("X-Powered-By", "HPHP"); } if (RuntimeOption::ExposeXFBServer && m_responseHeaders.find("X-FB-Server") == m_responseHeaders.end()) { addHeaderImpl("X-FB-Server", String(RuntimeOption::ServerPrimaryIP)); } // shutting down servers, so need to terminate all Keep-Alive connections if (!RuntimeOption::EnableKeepAlive || isServerStopping()) { addHeaderImpl("Connection", "close"); removeHeaderImpl("Keep-Alive"); // so lower level transports can ignore incoming "Connection: keep-alive" removeRequestHeaderImpl("Connection"); } }
void Transport::prepareHeaders(bool compressed, bool chunked, const String &response, const String& orig_response) { for (HeaderMap::const_iterator iter = m_responseHeaders.begin(); iter != m_responseHeaders.end(); ++iter) { const vector<string> &values = iter->second; for (unsigned int i = 0; i < values.size(); i++) { addHeaderImpl(iter->first.c_str(), values[i].c_str()); } } for (CookieMap::const_iterator iter = m_responseCookies.begin(); iter != m_responseCookies.end(); ++iter) { addHeaderImpl("Set-Cookie", iter->second.c_str()); } if (compressed) { addHeaderImpl("Content-Encoding", "gzip"); removeHeaderImpl("Content-Length"); // Remove the Content-MD5 header coming from PHP if we compressed the data, // as the checksum is going to be invalid. auto it = m_responseHeaders.find("Content-MD5"); if (it != m_responseHeaders.end()) { removeHeaderImpl("Content-MD5"); // Re-add it back unless this is a chunked response. We'd have to buffer // the response completely to compute the MD5, which defeats the purpose // of chunking. if (chunked) { raise_warning("Cannot use chunked HTTP response and Content-MD5 header " "at the same time. Dropping Content-MD5."); } else { string cur_md5 = it->second[0]; String expected_md5 = StringUtil::Base64Encode(StringUtil::MD5( orig_response, true)); // Can never trust these PHP people... if (expected_md5.c_str() != cur_md5) { raise_warning("Content-MD5 mismatch. Expected: %s, Got: %s", expected_md5.c_str(), cur_md5.c_str()); } addHeaderImpl("Content-MD5", StringUtil::Base64Encode(StringUtil::MD5( response, true)).c_str()); } } } if (m_responseHeaders.find("Content-Type") == m_responseHeaders.end() && m_responseCode != 304) { string contentType = "text/html; charset=" + RuntimeOption::DefaultCharsetName; addHeaderImpl("Content-Type", contentType.c_str()); } if (RuntimeOption::ExposeHPHP) { addHeaderImpl("X-Powered-By", "HPHP"); } if ((RuntimeOption::ExposeXFBServer || RuntimeOption::ExposeXFBDebug) && !RuntimeOption::XFBDebugSSLKey.empty() && m_responseHeaders.find("X-FB-Debug") == m_responseHeaders.end()) { String ip = RuntimeOption::ServerPrimaryIP; String key = RuntimeOption::XFBDebugSSLKey; String cipher("AES-256-CBC"); int iv_len = f_openssl_cipher_iv_length(cipher).toInt32(); String iv = f_openssl_random_pseudo_bytes(iv_len); String encrypted = f_openssl_encrypt(ip, cipher, key, k_OPENSSL_RAW_DATA, iv); String output = StringUtil::Base64Encode(iv + encrypted); if (debug) { String decrypted = f_openssl_decrypt(encrypted, cipher, key, k_OPENSSL_RAW_DATA, iv); assert(decrypted->same(ip.get())); } addHeaderImpl("X-FB-Debug", output.c_str()); } // shutting down servers, so need to terminate all Keep-Alive connections if (!RuntimeOption::EnableKeepAlive || isServerStopping()) { addHeaderImpl("Connection", "close"); removeHeaderImpl("Keep-Alive"); // so lower level transports can ignore incoming "Connection: keep-alive" removeRequestHeaderImpl("Connection"); } }
void Transport::prepareHeaders(bool compressed, const void *data, int size) { for (HeaderMap::const_iterator iter = m_responseHeaders.begin(); iter != m_responseHeaders.end(); ++iter) { const vector<string> &values = iter->second; for (unsigned int i = 0; i < values.size(); i++) { addHeaderImpl(iter->first.c_str(), values[i].c_str()); } } for (CookieMap::const_iterator iter = m_responseCookies.begin(); iter != m_responseCookies.end(); ++iter) { addHeaderImpl("Set-Cookie", iter->second.c_str()); } if (compressed) { addHeaderImpl("Content-Encoding", "gzip"); removeHeaderImpl("Content-Length"); if (m_responseHeaders.find("Content-MD5") != m_responseHeaders.end()) { String response((const char *)data, size, AttachLiteral); removeHeaderImpl("Content-MD5"); addHeaderImpl("Content-MD5", StringUtil::Base64Encode( StringUtil::MD5(response, true)).c_str()); } } if (m_responseHeaders.find("Content-Type") == m_responseHeaders.end() && m_responseCode != 304) { string contentType = "text/html; charset=" + RuntimeOption::DefaultCharsetName; addHeaderImpl("Content-Type", contentType.c_str()); } if (RuntimeOption::ExposeHPHP) { addHeaderImpl("X-Powered-By", "HPHP"); } if ((RuntimeOption::ExposeXFBServer || RuntimeOption::ExposeXFBDebug) && !RuntimeOption::XFBDebugSSLKey.empty() && m_responseHeaders.find("X-FB-Debug") == m_responseHeaders.end()) { String ip = RuntimeOption::ServerPrimaryIP; String key = RuntimeOption::XFBDebugSSLKey; String cipher("AES-256-CBC"); int iv_len = f_openssl_cipher_iv_length(cipher); String iv = f_openssl_random_pseudo_bytes(iv_len); String encrypted = f_openssl_encrypt(ip, cipher, key, k_OPENSSL_RAW_DATA, iv); String output = StringUtil::Base64Encode(iv + encrypted); if (debug) { String decrypted = f_openssl_decrypt(encrypted, cipher, key, k_OPENSSL_RAW_DATA, iv); ASSERT(decrypted->same(ip.get())); } addHeaderImpl("X-FB-Debug", output); } // shutting down servers, so need to terminate all Keep-Alive connections if (!RuntimeOption::EnableKeepAlive || isServerStopping()) { addHeaderImpl("Connection", "close"); removeHeaderImpl("Keep-Alive"); // so lower level transports can ignore incoming "Connection: keep-alive" removeRequestHeaderImpl("Connection"); } }