From 3748adf2fda4f547da278400c44d4a9771023e94 Mon Sep 17 00:00:00 2001
From: Hypolite Petovan <hypolite@mrpetovan.com>
Date: Sun, 9 Jul 2023 22:44:40 -0400
Subject: [PATCH] Fix exception module not setting the HTTP response code

- Page->run now returns an updated response for use with Page->exit
- Remove now duplicated header setting in Page->run
- Remove now obsolete (and ineffective) HTTP return code setting from Module\Special\HTTPException->content
- Add HTTP response code and reason setting in BaseModule->run
---
 src/App.php                          |  8 +++++---
 src/App/Page.php                     | 19 +++++--------------
 src/BaseModule.php                   |  1 +
 src/Module/Special/HTTPException.php |  2 --
 4 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/src/App.php b/src/App.php
index a48e21571d..db3e644c2f 100644
--- a/src/App.php
+++ b/src/App.php
@@ -706,11 +706,13 @@ class App
 			$timestamp = microtime(true);
 			$response = $module->run($httpException, $input);
 			$this->profiler->set(microtime(true) - $timestamp, 'content');
+
+			// Wrapping HTML responses in the theme template
 			if ($response->getHeaderLine(ICanCreateResponses::X_HEADER) === ICanCreateResponses::TYPE_HTML) {
-				$page->run($this, $this->baseURL, $this->args, $this->mode, $response, $this->l10n, $this->profiler, $this->config, $pconfig, $nav, $this->session->getLocalUserId());
-			} else {
-				$page->exit($response);
+				$response = $page->run($this, $this->baseURL, $this->args, $this->mode, $response, $this->l10n, $this->profiler, $this->config, $pconfig, $nav, $this->session->getLocalUserId());
 			}
+
+			$page->exit($response);
 		} catch (HTTPException $e) {
 			$httpException->rawContent($e);
 		}
diff --git a/src/App/Page.php b/src/App/Page.php
index 6252d9a88a..96bb59425e 100644
--- a/src/App/Page.php
+++ b/src/App/Page.php
@@ -39,6 +39,7 @@ use Friendica\Network\HTTPException;
 use Friendica\Util\Network;
 use Friendica\Util\Profiler;
 use Friendica\Util\Strings;
+use GuzzleHttp\Psr7\Utils;
 use Psr\Http\Message\ResponseInterface;
 
 /**
@@ -499,20 +500,6 @@ class Page implements ArrayAccess
 			$this->page['nav']      = $nav->getHtml();
 		}
 
-		foreach ($response->getHeaders() as $key => $header) {
-			if (is_array($header)) {
-				$header_str = implode(',', $header);
-			} else {
-				$header_str = $header;
-			}
-
-			if (empty($key)) {
-				header($header_str);
-			} else {
-				header("$key: $header_str");
-			}
-		}
-
 		// Build the page - now that we have all the components
 		if (isset($_GET["mode"]) && (($_GET["mode"] == "raw") || ($_GET["mode"] == "minimal"))) {
 			$doc = new DOMDocument();
@@ -583,6 +570,10 @@ class Page implements ArrayAccess
 		// Used as is in view/php/default.php
 		$lang = $l10n->getCurrentLang();
 
+		ob_start();
 		require_once $template;
+		$body = ob_get_clean();
+
+		return $response->withBody(Utils::streamFor($body));
 	}
 }
diff --git a/src/BaseModule.php b/src/BaseModule.php
index b43e984772..619095dfb6 100644
--- a/src/BaseModule.php
+++ b/src/BaseModule.php
@@ -251,6 +251,7 @@ abstract class BaseModule implements ICanHandleRequests
 				throw $e;
 			}
 
+			$this->response->setStatus($e->getCode(), $e->getMessage());
 			$this->response->addContent($httpException->content($e));
 		} finally {
 			$this->profiler->set(microtime(true) - $timestamp, 'content');
diff --git a/src/Module/Special/HTTPException.php b/src/Module/Special/HTTPException.php
index 8a8cc30ebb..2cac142fca 100644
--- a/src/Module/Special/HTTPException.php
+++ b/src/Module/Special/HTTPException.php
@@ -126,8 +126,6 @@ class HTTPException
 	 */
 	public function content(\Friendica\Network\HTTPException $e): string
 	{
-		header($this->server['SERVER_PROTOCOL'] ?? 'HTTP/1.0' . ' ' . $e->getCode() . ' ' . $e->getDescription());
-
 		if ($e->getCode() >= 400) {
 			$this->logger->debug('Exit with error',
 				[
-- 
2.39.5