/** * Precondition: m_originalURL and m_queryString are set * Postcondition: Output is false and we are redirecting OR * m_rewrittenURL is set and m_queryString is updated if needed */ bool RequestURI::rewriteURL(const VirtualHost *vhost, Transport *transport, const string &pathTranslation, const string &sourceRoot) { bool qsa = false; int redirect = 0; string host = transport->getHeader("host"); m_rewrittenURL = m_originalURL; if (vhost->rewriteURL(host, m_rewrittenURL, qsa, redirect)) { m_rewritten = true; if (qsa && !m_queryString.empty()) { m_rewrittenURL += (m_rewrittenURL.find('?') < 0) ? "?" : "&"; m_rewrittenURL += m_queryString; } if (redirect) { if (m_rewrittenURL.substr(0, 7) != s_http && m_rewrittenURL.substr(0, 8) != s_https) { PrependSlash(m_rewrittenURL); } transport->redirect(m_rewrittenURL.c_str(), redirect, "rewriteURL"); return false; } splitURL(m_rewrittenURL, m_rewrittenURL, m_queryString); } m_rewrittenURL = String( Util::canonicalize(m_rewrittenURL.c_str(), m_rewrittenURL.size()), AttachString); if (!m_rewritten && m_rewrittenURL.charAt(0) == '/') { // A un-rewritten URL is always relative, so remove prepending / m_rewrittenURL = m_rewrittenURL.substr(1); } // If the URL refers to a folder but does not end // with a slash, then we need to redictect String url = m_rewrittenURL; if (!url.empty() && url.charAt(url.length() - 1) != '/') { if (virtualFolderExists(vhost, sourceRoot, pathTranslation, url)) { url += "/"; m_rewritten = true; String queryStr; m_rewrittenURL = m_originalURL; m_rewrittenURL += "/"; if (!m_queryString.empty()) { m_rewrittenURL += "?"; m_rewrittenURL += m_queryString; } if (m_rewrittenURL.substr(0, 7) != s_http && m_rewrittenURL.substr(0, 8) != s_https) { PrependSlash(m_rewrittenURL); } transport->redirect(m_rewrittenURL.c_str(), 301, "rewriteURL"); return false; } } return true; }
/** * Precondition: m_originalURL and m_queryString are set * Postcondition: Output is false and we are redirecting OR * m_rewrittenURL is set and m_queryString is updated if needed */ bool RequestURI::rewriteURL(const VirtualHost *vhost, Transport *transport, const std::string &pathTranslation, const std::string &sourceRoot) { bool qsa = false; int redirect = 0; std::string host = transport->getHeader("host"); m_rewrittenURL = m_originalURL; if (vhost->rewriteURL(host, m_rewrittenURL, qsa, redirect)) { m_rewritten = true; if (qsa && !m_queryString.empty()) { m_rewrittenURL += (m_rewrittenURL.find('?') < 0) ? "?" : "&"; m_rewrittenURL += m_queryString; } if (redirect) { if (m_rewrittenURL.substr(0, 7) != s_http && m_rewrittenURL.substr(0, 8) != s_https) { PrependSlash(m_rewrittenURL); } if (redirect < 0) { std::string error; StringBuffer response; int code = 0; HttpProtocol::ProxyRequest(transport, true, m_rewrittenURL.toCppString(), code, error, response); if (!code) { transport->sendString(error, 500, false, false, "proxyRequest"); } else { const char* respData = response.data(); if (!respData) respData = ""; transport->sendRaw(const_cast<char*>(respData), response.size(), code); } transport->onSendEnd(); } else { transport->redirect(m_rewrittenURL.c_str(), redirect); } return false; } splitURL(m_rewrittenURL, m_rewrittenURL, m_queryString); } m_rewrittenURL = FileUtil::canonicalize(m_rewrittenURL); if (!m_rewritten && m_rewrittenURL.charAt(0) == '/') { // A un-rewritten URL is always relative, so remove prepending / m_rewrittenURL = m_rewrittenURL.substr(1); } // If the URL refers to a folder but does not end // with a slash, then we need to redictect String url = m_rewrittenURL; if (!url.empty() && url.charAt(url.length() - 1) != '/') { if (virtualFolderExists(vhost, sourceRoot, pathTranslation, url)) { if (m_originalURL.find("..") != String::npos) { transport->sendString(getDefault404(), 404); transport->onSendEnd(); return false; } url += "/"; m_rewritten = true; String queryStr; m_rewrittenURL = m_originalURL; m_rewrittenURL += "/"; if (!m_queryString.empty()) { m_rewrittenURL += "?"; m_rewrittenURL += m_queryString; } if (m_rewrittenURL.substr(0, 7) != s_http && m_rewrittenURL.substr(0, 8) != s_https) { PrependSlash(m_rewrittenURL); } transport->redirect(m_rewrittenURL.c_str(), 301); return false; } } return true; }