/** * Precondition: m_rewrittenURL is set * Postcondition: Output is true and m_path and m_absolutePath are set OR * output is false and no file was found */ bool RequestURI::resolveURL(const VirtualHost *vhost, const string &pathTranslation, const string &sourceRoot) { m_resolvedURL = m_rewrittenURL; while (!virtualFileExists(vhost, sourceRoot, pathTranslation, m_resolvedURL)) { int pos = m_resolvedURL.rfind('/'); if (pos <= 0) { // when none of the <subpath> exists, we give up, and try default doc m_resolvedURL = m_rewrittenURL; if (!m_resolvedURL.empty() && m_resolvedURL.charAt(m_resolvedURL.length() - 1) != '/') { m_resolvedURL += "/"; } m_resolvedURL += String(RuntimeOption::DefaultDocument); m_pathInfo.reset(); if (virtualFileExists(vhost, sourceRoot, pathTranslation, m_resolvedURL)) { m_defaultDoc = true; PrependSlash(m_resolvedURL); return true; } return false; } m_resolvedURL = m_rewrittenURL.substr(0, pos); m_pathInfo = m_rewrittenURL.substr(pos); } PrependSlash(m_resolvedURL); 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 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; }
bool RequestURI::process(const VirtualHost *vhost, Transport *transport, const string &sourceRoot, const string &pathTranslation, const char *url) { splitURL(url, m_originalURL, m_queryString); m_originalURL = StringUtil::UrlDecode(m_originalURL, false); // Fast path for files that exist String canon = Util::canonicalize(string(m_originalURL.c_str(), m_originalURL.size())); String relUrl(canon.charAt(0) == '/' ? canon.substr(1) : canon); if (virtualFileExists(vhost, sourceRoot, pathTranslation, relUrl)) { m_rewrittenURL = relUrl; m_resolvedURL = relUrl; PrependSlash(m_resolvedURL); return true; } if (!rewriteURL(vhost, transport, pathTranslation, sourceRoot)) { // Redirection m_done = true; return true; } if (!resolveURL(vhost, pathTranslation, sourceRoot)) { // Can't find 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; }