Skip to content

Commit aba62ab

Browse files
authored
Merge pull request #4 from maplephp/develop
Add default Content-Type
2 parents 6ccf2d1 + 8a39409 commit aba62ab

File tree

2 files changed

+184
-175
lines changed

2 files changed

+184
-175
lines changed

src/AbstractKernel.php

Lines changed: 180 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
use MaplePHP\Emitron\Emitters\CliEmitter;
2323
use MaplePHP\Emitron\Emitters\HttpEmitter;
2424
use MaplePHP\Http\Interfaces\PathInterface;
25-
use MaplePHP\Http\ResponseFactory;
2625
use MaplePHP\Http\Stream;
2726
use Psr\Container\ContainerInterface;
2827
use Psr\Http\Message\ResponseInterface;
@@ -32,178 +31,184 @@
3231

3332
abstract class AbstractKernel implements KernelInterface
3433
{
35-
public const CONFIG_FILE_PATH = __DIR__ . '/../emitron.config.php';
36-
protected static ?string $configFilePath = null;
37-
protected static ?string $routerFilePath = null;
38-
protected ContainerInterface $container;
39-
protected array $userMiddlewares;
40-
protected ?DispatchConfigInterface $dispatchConfig = null;
41-
protected array $config = [];
42-
43-
/**
44-
* @param ContainerInterface $container
45-
* @param array $userMiddlewares
46-
* @param DispatchConfigInterface|null $dispatchConfig
47-
* @throws \Exception
48-
*/
49-
public function __construct(
50-
ContainerInterface $container,
51-
array $userMiddlewares = [],
52-
?DispatchConfigInterface $dispatchConfig = null,
53-
) {
54-
$this->userMiddlewares = $userMiddlewares;
55-
$this->container = $container;
56-
$this->dispatchConfig = ($dispatchConfig === null) ?
57-
new DispatchConfig(static::getConfigFilePath()) : $dispatchConfig;
58-
}
59-
60-
/**
61-
* Makes it easy to specify a config file inside a custom kernel file
62-
*
63-
* @param string|null $path
64-
* @return void
65-
*/
66-
public static function setConfigFilePath(?string $path): void
67-
{
68-
static::$configFilePath = $path;
69-
}
70-
71-
/**
72-
* Get expected config file
73-
*
74-
* @return string
75-
*/
76-
public static function getConfigFilePath(): string
77-
{
78-
if (static::$configFilePath === null) {
79-
return static::CONFIG_FILE_PATH;
80-
}
81-
return static::$configFilePath;
82-
}
83-
84-
/**
85-
* Set router path
86-
*
87-
* @param string|null $path
88-
* @return void
89-
*/
90-
public static function setRouterFilePath(?string $path): void
91-
{
92-
static::$routerFilePath = $path;
93-
}
94-
95-
/**
96-
* Get router path
97-
*
98-
* @return string
99-
*/
100-
public static function getRouterFilePath(): string
101-
{
102-
if(static::$routerFilePath === null) {
103-
return realpath(dirname(self::getConfigFilePath()));
104-
}
105-
return static::$routerFilePath;
106-
}
107-
108-
/**
109-
* Get config instance for configure dispatch result
110-
*
111-
* @return DispatchConfigInterface
112-
*/
113-
public function getDispatchConfig(): DispatchConfigInterface
114-
{
115-
return $this->dispatchConfig;
116-
}
117-
118-
/**
119-
* Will initialize the request handler with default
120-
* functionality that you would want.
121-
*
122-
* @param ServerRequestInterface $request
123-
* @param StreamInterface $stream
124-
* @param RequestHandlerInterface $finalHandler
125-
* @param array $middlewares
126-
* @return ResponseInterface
127-
* @throws \ReflectionException
128-
*/
129-
protected function initRequestHandler(
130-
ServerRequestInterface $request,
131-
StreamInterface $stream,
132-
PathInterface $path,
133-
RequestHandlerInterface $finalHandler,
134-
array $middlewares = []
135-
): ResponseInterface {
136-
137-
$this->bindInterfaces([
138-
"ContainerInterface" => $this->container,
139-
"RequestInterface" => $request,
140-
"ServerRequestInterface" => $request,
141-
"StreamInterface" => $stream,
142-
"PathInterface" => $path
143-
]);
144-
145-
$middlewares = array_merge($this->userMiddlewares, $middlewares);
146-
$handler = new RequestHandler($middlewares, $finalHandler);
147-
$app = $this->container->has("app") ? $this->container->get("app") : null;
148-
149-
ob_start();
150-
$response = $handler->handle($request);
151-
$output = ob_get_clean();
152-
153-
if((string)$output !== "" && ($app instanceof AppInterface && !$app->isProd())) {
154-
throw new \RuntimeException(
155-
'Unexpected output detected during request dispatch. Controllers must write to the response body instead of using echo.'
156-
);
157-
}
158-
159-
return $response;
160-
}
161-
162-
/**
163-
* Bind instances (singletons) to interface classes so they can be resolved
164-
* through the dependency injector.
165-
*
166-
* @param array<string, object> $bindings
167-
* @return void
168-
*/
169-
protected function bindInterfaces(array $bindings): void
170-
{
171-
Reflection::interfaceFactory(function (string $className) use ($bindings) {
172-
return $bindings[$className] ?? null;
173-
});
174-
}
175-
176-
/**
177-
* Get the expected body (stream)
178-
*
179-
* @param StreamInterface|null $stream
180-
* @return StreamInterface
181-
*/
182-
protected function getBody(?StreamInterface $stream): StreamInterface
183-
{
184-
if($stream === null) {
185-
return new Stream($this->isCli() ? Stream::STDOUT : Stream::TEMP);
186-
}
187-
return $stream;
188-
}
189-
190-
/**
191-
* Check if is inside a command line interface (CLI)
192-
*
193-
* @return bool
194-
*/
195-
protected function isCli(): bool
196-
{
197-
return PHP_SAPI === 'cli';
198-
}
199-
200-
/**
201-
* Get emitter based on a platform
202-
*
203-
* @return EmitterInterface
204-
*/
205-
protected function createEmitter(): EmitterInterface
206-
{
207-
return $this->isCli() ? new CliEmitter() : new HttpEmitter();
208-
}
34+
public const CONFIG_FILE_PATH = __DIR__ . '/../emitron.config.php';
35+
protected static ?string $configFilePath = null;
36+
protected static ?string $routerFilePath = null;
37+
protected ContainerInterface $container;
38+
protected array $userMiddlewares;
39+
protected ?DispatchConfigInterface $dispatchConfig = null;
40+
protected array $config = [];
41+
42+
/**
43+
* @param ContainerInterface $container
44+
* @param array $userMiddlewares
45+
* @param DispatchConfigInterface|null $dispatchConfig
46+
* @throws \Exception
47+
*/
48+
public function __construct(
49+
ContainerInterface $container,
50+
array $userMiddlewares = [],
51+
?DispatchConfigInterface $dispatchConfig = null,
52+
)
53+
{
54+
$this->userMiddlewares = $userMiddlewares;
55+
$this->container = $container;
56+
$this->dispatchConfig = ($dispatchConfig === null) ?
57+
new DispatchConfig(static::getConfigFilePath()) : $dispatchConfig;
58+
}
59+
60+
/**
61+
* Makes it easy to specify a config file inside a custom kernel file
62+
*
63+
* @param string|null $path
64+
* @return void
65+
*/
66+
public static function setConfigFilePath(?string $path): void
67+
{
68+
static::$configFilePath = $path;
69+
}
70+
71+
/**
72+
* Get expected config file
73+
*
74+
* @return string
75+
*/
76+
public static function getConfigFilePath(): string
77+
{
78+
if (static::$configFilePath === null) {
79+
return static::CONFIG_FILE_PATH;
80+
}
81+
return static::$configFilePath;
82+
}
83+
84+
/**
85+
* Set router path
86+
*
87+
* @param string|null $path
88+
* @return void
89+
*/
90+
public static function setRouterFilePath(?string $path): void
91+
{
92+
static::$routerFilePath = $path;
93+
}
94+
95+
/**
96+
* Get router path
97+
*
98+
* @return string
99+
*/
100+
public static function getRouterFilePath(): string
101+
{
102+
if (static::$routerFilePath === null) {
103+
return realpath(dirname(self::getConfigFilePath()));
104+
}
105+
return static::$routerFilePath;
106+
}
107+
108+
/**
109+
* Get config instance for configure dispatch result
110+
*
111+
* @return DispatchConfigInterface
112+
*/
113+
public function getDispatchConfig(): DispatchConfigInterface
114+
{
115+
return $this->dispatchConfig;
116+
}
117+
118+
/**
119+
* Will initialize the request handler with default
120+
* functionality that you would want.
121+
*
122+
* @param ServerRequestInterface $request
123+
* @param StreamInterface $stream
124+
* @param RequestHandlerInterface $finalHandler
125+
* @param array $middlewares
126+
* @return ResponseInterface
127+
* @throws \ReflectionException
128+
*/
129+
protected function initRequestHandler(
130+
ServerRequestInterface $request,
131+
StreamInterface $stream,
132+
PathInterface $path,
133+
RequestHandlerInterface $finalHandler,
134+
array $middlewares = []
135+
): ResponseInterface
136+
{
137+
138+
$this->bindInterfaces([
139+
"ContainerInterface" => $this->container,
140+
"RequestInterface" => $request,
141+
"ServerRequestInterface" => $request,
142+
"StreamInterface" => $stream,
143+
"PathInterface" => fn() => $path
144+
]);
145+
146+
$middlewares = array_merge($this->userMiddlewares, $middlewares);
147+
$handler = new RequestHandler($middlewares, $finalHandler);
148+
$app = $this->container->has("app") ? $this->container->get("app") : null;
149+
150+
ob_start();
151+
$response = $handler->handle($request);
152+
$output = ob_get_clean();
153+
154+
if ((string)$output !== "" && ($app instanceof AppInterface && !$app->isProd())) {
155+
throw new \RuntimeException(
156+
'Unexpected output detected during request dispatch. Controllers must write to the response body instead of using echo.'
157+
);
158+
}
159+
160+
return $response;
161+
}
162+
163+
/**
164+
* Bind instances (singletons) to interface classes so they can be resolved
165+
* through the dependency injector.
166+
*
167+
* @param array<string, object> $bindings
168+
* @return void
169+
*/
170+
protected function bindInterfaces(array $bindings): void
171+
{
172+
Reflection::interfaceFactory(function (string $className) use ($bindings) {
173+
$instance = $bindings[$className] ?? null;
174+
if (is_callable($instance)) {
175+
$instance = $instance();
176+
}
177+
return $instance;
178+
});
179+
}
180+
181+
/**
182+
* Get the expected body (stream)
183+
*
184+
* @param StreamInterface|null $stream
185+
* @return StreamInterface
186+
*/
187+
protected function getBody(?StreamInterface $stream): StreamInterface
188+
{
189+
if ($stream === null) {
190+
return new Stream($this->isCli() ? Stream::STDOUT : Stream::TEMP);
191+
}
192+
return $stream;
193+
}
194+
195+
/**
196+
* Check if is inside a command line interface (CLI)
197+
*
198+
* @return bool
199+
*/
200+
protected function isCli(): bool
201+
{
202+
return PHP_SAPI === 'cli';
203+
}
204+
205+
/**
206+
* Get emitter based on a platform
207+
*
208+
* @return EmitterInterface
209+
*/
210+
protected function createEmitter(): EmitterInterface
211+
{
212+
return $this->isCli() ? new CliEmitter() : new HttpEmitter();
213+
}
209214
}

src/Emitters/HttpEmitter.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ public function emit(ResponseInterface $response, ServerRequestInterface $reques
2929
|| ($status >= 100 && $status < 200)
3030
|| $method === 'HEAD';
3131

32+
if(!$response->hasHeader('Content-Type')) {
33+
$response = $response->withHeader('Content-Type', 'text/html; charset=UTF-8');
34+
}
35+
3236
// Create headers
3337
$this->createHeaders($response);
3438

0 commit comments

Comments
 (0)