bool HttpRequestHandler::executePHPRequest(Transport *transport,
                                           RequestURI &reqURI,
                                           SourceRootInfo &sourceRootInfo,
                                           bool cachableDynamicContent) {
  ExecutionContext *context = hphp_context_init();
  context->setTransport(transport);

  string file = reqURI.absolutePath().c_str();
  {
    ServerStatsHelper ssh("input");
    HttpProtocol::PrepareSystemVariables(transport, reqURI, sourceRootInfo);
    reqURI.clear();
    sourceRootInfo.clear();
  }

  bool error = false;
  std::string errorMsg = "Internal Server Error";
  bool ret = hphp_invoke(context, file, false, Array(), null,
                         RuntimeOption::WarmupDocument,
                         RuntimeOption::RequestInitFunction,
                         error, errorMsg);

  int code;
  if (ret) {
    std::string content = context->getContents();
    if (cachableDynamicContent && !content.empty()) {
      ASSERT(transport->getUrl());
      string key = file + transport->getUrl();
      DynamicContentCache::TheCache.store(key, content.data(), content.size());
    }
    code = 200;
    transport->sendRaw((void*)content.data(), content.size());
  } else if (error) {
    code = 500;

    string errorPage = context->getErrorPage();
    if (errorPage.empty()) {
      errorPage = RuntimeOption::ErrorDocument500;
    }
    if (!errorPage.empty()) {
      context->obEndAll();
      context->obStart();
      context->obProtect(true);
      ret = hphp_invoke(context, errorPage, false, Array(), null,
                        RuntimeOption::WarmupDocument,
                        RuntimeOption::RequestInitFunction,
                        error, errorMsg);
      if (ret) {
        std::string content = context->getContents();
        transport->sendRaw((void*)content.data(), content.size());
      } else {
        errorPage.clear(); // so we fall back to 500 return
      }
    }
    if (errorPage.empty()) {
      if (RuntimeOption::ServerErrorMessage) {
        transport->sendString(errorMsg, 500);
      } else {
        transport->sendString(RuntimeOption::FatalErrorMessage, 500);
      }
    }
  } else {
    code = 404;
    transport->sendString("Not Found", 404);
  }
  transport->onSendEnd();
  ServerStats::LogPage(file, code);
  hphp_context_exit(context, true);
  return ret;
}