bool HttpRequestHandler::executePHPRequest(Transport *transport, RequestURI &reqURI, SourceRootInfo &sourceRootInfo, bool cachableDynamicContent) { ExecutionContext *context = hphp_context_init(); if (RuntimeOption::ImplicitFlush) { context->obSetImplicitFlush(true); } if (RuntimeOption::EnableOutputBuffering) { if (RuntimeOption::OutputHandler.empty()) { context->obStart(); } else { context->obStart(String(RuntimeOption::OutputHandler)); } } context->setTransport(transport); string file = reqURI.absolutePath().c_str(); { ServerStatsHelper ssh("input"); HttpProtocol::PrepareSystemVariables(transport, reqURI, sourceRootInfo); Extension::RequestInitModules(); if (RuntimeOption::EnableDebugger) { Eval::DSandboxInfo sInfo = sourceRootInfo.getSandboxInfo(); Eval::Debugger::RegisterSandbox(sInfo); context->setSandboxId(sInfo.id()); } reqURI.clear(); sourceRootInfo.clear(); } int code; bool ret = true; if (RuntimeOption::EnableDebugger) { Eval::Debugger::InterruptRequestStarted(transport->getUrl()); } bool error = false; std::string errorMsg = "Internal Server Error"; ret = hphp_invoke(context, file, false, Array(), uninit_null(), RuntimeOption::RequestInitFunction, RuntimeOption::RequestInitDocument, error, errorMsg); if (ret) { String content = context->obDetachContents(); if (cachableDynamicContent && !content.empty()) { assert(transport->getUrl()); string key = file + transport->getUrl(); DynamicContentCache::TheCache.store(key, content.data(), content.size()); } transport->sendRaw((void*)content.data(), content.size()); code = transport->getResponseCode(); } else if (error) { code = 500; string errorPage = context->getErrorPage().data(); if (errorPage.empty()) { errorPage = RuntimeOption::ErrorDocument500; } if (!errorPage.empty()) { context->obProtect(false); context->obEndAll(); context->obStart(); context->obProtect(true); ret = hphp_invoke(context, errorPage, false, Array(), uninit_null(), RuntimeOption::RequestInitFunction, RuntimeOption::RequestInitDocument, error, errorMsg); if (ret) { String content = context->obDetachContents(); transport->sendRaw((void*)content.data(), content.size()); code = transport->getResponseCode(); } else { Logger::Error("Unable to invoke error page %s", errorPage.c_str()); errorPage.clear(); // so we fall back to 500 return } } if (errorPage.empty()) { if (RuntimeOption::ServerErrorMessage) { transport->sendString(errorMsg, 500, false, false, "hphp_invoke"); } else { transport->sendString(RuntimeOption::FatalErrorMessage, 500, false, false, "hphp_invoke"); } } } else { code = 404; transport->sendString("Not Found", 404); } if (RuntimeOption::EnableDebugger) { Eval::Debugger::InterruptRequestEnded(transport->getUrl()); } transport->onSendEnd(); hphp_context_exit(context, true, true, transport->getUrl()); ServerStats::LogPage(file, code); return ret; }
bool HttpRequestHandler::executePHPRequest(Transport *transport, RequestURI &reqURI, SourceRootInfo &sourceRootInfo, bool cachableDynamicContent) { ExecutionContext *context = hphp_context_init(); if (RuntimeOption::ImplicitFlush) { context->obSetImplicitFlush(true); } if (RuntimeOption::EnableOutputBuffering) { if (RuntimeOption::OutputHandler.empty()) { context->obStart(); } else { context->obStart(String(RuntimeOption::OutputHandler)); } } context->setTransport(transport); string file = reqURI.absolutePath().c_str(); { ServerStatsHelper ssh("input"); HttpProtocol::PrepareSystemVariables(transport, reqURI, sourceRootInfo); Extension::RequestInitModules(); if (RuntimeOption::EnableDebugger) { Eval::DSandboxInfo sInfo = sourceRootInfo.getSandboxInfo(); Eval::Debugger::RegisterSandbox(sInfo); context->setSandboxId(sInfo.id()); } reqURI.clear(); sourceRootInfo.clear(); } int code; bool ret = true; // Let the debugger initialize. // FIXME: hphpd can be initialized this way as well DEBUGGER_ATTACHED_ONLY(phpDebuggerRequestInitHook()); if (RuntimeOption::EnableDebugger) { Eval::Debugger::InterruptRequestStarted(transport->getUrl()); } bool error = false; std::string errorMsg = "Internal Server Error"; ret = hphp_invoke(context, file, false, Array(), uninit_null(), RuntimeOption::RequestInitFunction, RuntimeOption::RequestInitDocument, error, errorMsg, true /* once */, false /* warmupOnly */, false /* richErrorMessage */); if (ret) { String content = context->obDetachContents(); if (cachableDynamicContent && !content.empty()) { assert(transport->getUrl()); string key = file + transport->getUrl(); DynamicContentCache::TheCache.store(key, content.data(), content.size()); } transport->sendRaw((void*)content.data(), content.size()); code = transport->getResponseCode(); } else if (error) { code = 500; string errorPage = context->getErrorPage().data(); if (errorPage.empty()) { errorPage = RuntimeOption::ErrorDocument500; } if (!errorPage.empty()) { context->obProtect(false); context->obEndAll(); context->obStart(); context->obProtect(true); ret = hphp_invoke(context, errorPage, false, Array(), uninit_null(), RuntimeOption::RequestInitFunction, RuntimeOption::RequestInitDocument, error, errorMsg, true /* once */, false /* warmupOnly */, false /* richErrorMessage */); if (ret) { String content = context->obDetachContents(); transport->sendRaw((void*)content.data(), content.size()); code = transport->getResponseCode(); } else { Logger::Error("Unable to invoke error page %s", errorPage.c_str()); errorPage.clear(); // so we fall back to 500 return } } if (errorPage.empty()) { if (RuntimeOption::ServerErrorMessage) { transport->sendString(errorMsg, 500, false, false, "hphp_invoke"); } else { transport->sendString(RuntimeOption::FatalErrorMessage, 500, false, false, "hphp_invoke"); } } } else { code = 404; transport->sendString("Not Found", 404); } if (RuntimeOption::EnableDebugger) { Eval::Debugger::InterruptRequestEnded(transport->getUrl()); } // If we have registered post-send shutdown functions, end the request before // executing them. If we don't, be compatible with Zend by allowing usercode // in hphp_context_shutdown to run before we end the request. bool hasPostSend = context->hasShutdownFunctions(ExecutionContext::ShutdownType::PostSend); if (hasPostSend) { transport->onSendEnd(); } context->onShutdownPostSend(); Eval::Debugger::InterruptPSPEnded(transport->getUrl()); hphp_context_shutdown(); if (!hasPostSend) { transport->onSendEnd(); } hphp_context_exit(false); ServerStats::LogPage(file, code); return ret; }