Exemple #1
0
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");
  }
}
Exemple #2
0
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");
  }
}
Exemple #3
0
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");
  }
}