Skip to content

Commit 4a8335f

Browse files
committed
Ability to do SSR request without a bundle
1 parent b732a5c commit 4a8335f

File tree

6 files changed

+158
-7
lines changed

6 files changed

+158
-7
lines changed

config/inertia.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
'url' => env('INERTIA_SSR_URL', 'http://127.0.0.1:13714'),
2727

28+
'dispatch_without_bundle' => false,
29+
2830
// 'bundle' => base_path('bootstrap/ssr/ssr.mjs'),
2931

3032
],

src/Ssr/HttpGateway.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Inertia\Ssr;
44

55
use Exception;
6+
use Illuminate\Http\Client\StrayRequestException;
67
use Illuminate\Support\Facades\Http;
78

89
class HttpGateway implements Gateway
@@ -12,15 +13,25 @@ class HttpGateway implements Gateway
1213
*/
1314
public function dispatch(array $page): ?Response
1415
{
15-
if (! config('inertia.ssr.enabled', true) || ! (new BundleDetector)->detect()) {
16+
if (! config('inertia.ssr.enabled', true)) {
1617
return null;
1718
}
1819

19-
$url = str_replace('/render', '', rtrim(config('inertia.ssr.url', 'http://127.0.0.1:13714'), '/')).'/render';
20+
if (! $this->shouldDispatchWithoutBundle() && ! $this->bundleExists()) {
21+
return null;
22+
}
23+
24+
if (! $url = $this->getHttpUrl()) {
25+
return null;
26+
}
2027

2128
try {
2229
$response = Http::post($url, $page)->throw()->json();
2330
} catch (Exception $e) {
31+
if ($e instanceof StrayRequestException) {
32+
throw $e;
33+
}
34+
2435
return null;
2536
}
2637

@@ -33,4 +44,28 @@ public function dispatch(array $page): ?Response
3344
$response['body']
3445
);
3546
}
47+
48+
/**
49+
* Determine if dispatch should proceed even if no bundle is detected.
50+
*/
51+
protected function shouldDispatchWithoutBundle(): bool
52+
{
53+
return config('inertia.ssr.dispatch_without_bundle', false);
54+
}
55+
56+
/**
57+
* Check if an SSR bundle exists.
58+
*/
59+
protected function bundleExists(): bool
60+
{
61+
return (new BundleDetector)->detect() !== null;
62+
}
63+
64+
/**
65+
* Get the SSR URL from the configuration, ensuring it ends with '/render'.
66+
*/
67+
public function getHttpUrl(): ?string
68+
{
69+
return str_replace('/render', '', rtrim(config('inertia.ssr.url', 'http://127.0.0.1:13714'), '/')).'/render';
70+
}
3671
}

tests/DirectiveTest.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ class DirectiveTest extends TestCase
2727
*/
2828
protected $compiler;
2929

30-
/**
31-
* Example Page Objects.
32-
*/
33-
protected const EXAMPLE_PAGE_OBJECT = ['component' => 'Foo/Bar', 'props' => ['foo' => 'bar'], 'url' => '/test', 'version' => '', 'encryptHistory' => false, 'clearHistory' => false];
34-
3530
protected function setUp(): void
3631
{
3732
parent::setUp();

tests/HttpGatewayTest.php

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
namespace Inertia\Tests;
4+
5+
use Illuminate\Support\Facades\Http;
6+
use Inertia\Ssr\HttpGateway;
7+
8+
class HttpGatewayTest extends TestCase
9+
{
10+
protected HttpGateway $gateway;
11+
12+
protected function setUp(): void
13+
{
14+
parent::setUp();
15+
16+
$this->gateway = new HttpGateway;
17+
18+
Http::preventStrayRequests();
19+
}
20+
21+
public function test_it_returns_null_when_ssr_is_disabled()
22+
{
23+
config([
24+
'inertia.ssr.enabled' => false,
25+
'inertia.ssr.bundle' => __DIR__.'/Stubs/ssr-bundle.js',
26+
]);
27+
28+
$this->assertNull($this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT]));
29+
}
30+
31+
public function test_it_returns_null_when_no_bundle_file_is_detected()
32+
{
33+
config([
34+
'inertia.ssr.enabled' => true,
35+
'inertia.ssr.bundle' => null,
36+
]);
37+
38+
$this->assertNull($this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT]));
39+
}
40+
41+
public function test_it_uses_the_configured_http_url_when_the_bundle_file_is_detected()
42+
{
43+
config([
44+
'inertia.ssr.enabled' => true,
45+
'inertia.ssr.bundle' => __DIR__.'/Stubs/ssr-bundle.js',
46+
]);
47+
48+
Http::fake([
49+
$this->gateway->getHttpUrl() => Http::response(json_encode([
50+
'head' => ['<title>SSR Test</title>', '<style></style>'],
51+
'body' => '<div id="app">SSR Response</div>',
52+
])),
53+
]);
54+
55+
$this->assertNotNull(
56+
$response = $this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT])
57+
);
58+
59+
$this->assertEquals("<title>SSR Test</title>\n<style></style>", $response->head);
60+
$this->assertEquals('<div id="app">SSR Response</div>', $response->body);
61+
}
62+
63+
public function test_it_uses_the_configured_http_url__when_bundle_file_detection_is_disabled()
64+
{
65+
config([
66+
'inertia.ssr.enabled' => true,
67+
'inertia.ssr.dispatch_without_bundle' => true,
68+
'inertia.ssr.bundle' => null,
69+
]);
70+
71+
Http::fake([
72+
$this->gateway->getHttpUrl() => Http::response(json_encode([
73+
'head' => ['<title>SSR Test</title>', '<style></style>'],
74+
'body' => '<div id="app">SSR Response</div>',
75+
])),
76+
]);
77+
78+
$this->assertNotNull(
79+
$response = $this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT])
80+
);
81+
82+
$this->assertEquals("<title>SSR Test</title>\n<style></style>", $response->head);
83+
$this->assertEquals('<div id="app">SSR Response</div>', $response->body);
84+
}
85+
86+
public function test_it_returns_null_when_the_http_request_fails()
87+
{
88+
config([
89+
'inertia.ssr.enabled' => true,
90+
'inertia.ssr.bundle' => __DIR__.'/Stubs/ssr-bundle.js',
91+
]);
92+
93+
Http::fake([
94+
$this->gateway->getHttpUrl() => Http::response(null, 500),
95+
]);
96+
97+
$this->assertNull($this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT]));
98+
}
99+
100+
public function test_it_returns_null_when_invalid_json_is_returned()
101+
{
102+
config([
103+
'inertia.ssr.enabled' => true,
104+
'inertia.ssr.bundle' => __DIR__.'/Stubs/ssr-bundle.js',
105+
]);
106+
107+
Http::fake([
108+
$this->gateway->getHttpUrl() => Http::response('invalid json'),
109+
]);
110+
111+
$this->assertNull($this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT]));
112+
}
113+
}

tests/Stubs/ssr-bundle.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log("This is a stub for SSR bundle.");

tests/TestCase.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010

1111
abstract class TestCase extends Orchestra
1212
{
13+
/**
14+
* Example Page Objects.
15+
*/
16+
protected const EXAMPLE_PAGE_OBJECT = ['component' => 'Foo/Bar', 'props' => ['foo' => 'bar'], 'url' => '/test', 'version' => '', 'encryptHistory' => false, 'clearHistory' => false];
17+
1318
protected function getPackageProviders($app): array
1419
{
1520
return [

0 commit comments

Comments
 (0)