@kirschbaum-development/sst-laravel 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/docs/api.md +32 -1
- package/laravel-sst.ts +99 -36
- package/package.json +1 -1
- package/src/load-balancer.ts +60 -0
package/README.md
CHANGED
|
@@ -88,6 +88,36 @@ const app = new LaravelService('MyLaravelApp', {
|
|
|
88
88
|
|
|
89
89
|
Check all the `web` options [here](https://github.com/kirschbaum-development/sst-laravel/blob/main/docs/api.md#web).
|
|
90
90
|
|
|
91
|
+
#### Load balancer health check
|
|
92
|
+
|
|
93
|
+
Laravel ships a built-in `/up` health endpoint. Point the load balancer at it via `web.healthCheck` — a shortcut over `loadBalancer.health` that targets the default forward port for you:
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
const app = new LaravelService('MyLaravelApp', {
|
|
97
|
+
web: {
|
|
98
|
+
domain: { name: 'app.example.com' },
|
|
99
|
+
healthCheck: { path: '/up' },
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
All [`loadBalancer.health` options](https://sst.dev/docs/component/aws/service/#loadbalancer-health) are supported (`interval`, `timeout`, `healthyThreshold`, `unhealthyThreshold`, `successCodes`). If you set `web.loadBalancer` explicitly, `healthCheck` is ignored — configure `loadBalancer.health` directly there.
|
|
105
|
+
|
|
106
|
+
#### HTTP to HTTPS redirect
|
|
107
|
+
|
|
108
|
+
When you configure a `domain` (which provisions an SSL certificate and an HTTPS listener), HTTP (port 80) traffic is redirected to HTTPS (port 443) by default. To keep forwarding HTTP traffic straight to your application instead, set `httpsRedirect: false`:
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
const app = new LaravelService('MyLaravelApp', {
|
|
112
|
+
web: {
|
|
113
|
+
domain: { name: 'app.example.com' },
|
|
114
|
+
httpsRedirect: false,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
This has no effect when no `domain` is set, or when you provide an explicit `web.loadBalancer` (configure `loadBalancer.ports` yourself in that case).
|
|
120
|
+
|
|
91
121
|
### Reverb
|
|
92
122
|
|
|
93
123
|
You can deploy a dedicated Laravel Reverb service for WebSocket traffic. Reverb runs as a worker-style container using `php artisan reverb:start`, but SST Laravel also attaches a load balancer so you can give it its own public domain.
|
package/docs/api.md
CHANGED
|
@@ -259,7 +259,38 @@ web: {
|
|
|
259
259
|
|
|
260
260
|
#### `web.health`
|
|
261
261
|
- **Type:** `ServiceArgs["health"]`
|
|
262
|
-
- **Description:**
|
|
262
|
+
- **Description:** ECS container-level health check for the web service. Distinct from `web.healthCheck` (load balancer).
|
|
263
|
+
|
|
264
|
+
#### `web.healthCheck`
|
|
265
|
+
- **Type:** `Input<LaravelHealthCheck>`
|
|
266
|
+
- **Description:** Load balancer health check applied to the default forward port (`8080/http`). Shorthand so you don't have to override the full `loadBalancer` config just to set a path. Ignored when `loadBalancer` is provided — configure `loadBalancer.health` directly in that case.
|
|
267
|
+
|
|
268
|
+
**Example:**
|
|
269
|
+
```typescript
|
|
270
|
+
web: {
|
|
271
|
+
domain: { name: 'app.example.com' },
|
|
272
|
+
healthCheck: {
|
|
273
|
+
path: '/up',
|
|
274
|
+
successCodes: '200',
|
|
275
|
+
interval: '30 seconds',
|
|
276
|
+
healthyThreshold: 2,
|
|
277
|
+
unhealthyThreshold: 3,
|
|
278
|
+
},
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### `web.httpsRedirect`
|
|
283
|
+
- **Type:** `boolean`
|
|
284
|
+
- **Default:** `true`
|
|
285
|
+
- **Description:** When a `domain` is configured, redirect HTTP (port 80) traffic to the HTTPS (port 443) listener instead of forwarding it straight to the application. Set to `false` to keep forwarding HTTP traffic to the app. Has no effect when no `domain` is set (there is no HTTPS listener to redirect to) or when an explicit `loadBalancer` is provided.
|
|
286
|
+
|
|
287
|
+
**Example:**
|
|
288
|
+
```typescript
|
|
289
|
+
web: {
|
|
290
|
+
domain: { name: 'app.example.com' },
|
|
291
|
+
httpsRedirect: false,
|
|
292
|
+
}
|
|
293
|
+
```
|
|
263
294
|
|
|
264
295
|
#### `web.executionRole`
|
|
265
296
|
- **Type:** `ServiceArgs["executionRole"]`
|
package/laravel-sst.ts
CHANGED
|
@@ -27,18 +27,11 @@ import { getPackagePath } from './src/config';
|
|
|
27
27
|
import { RemoteEnvFile } from './src/remote-env-file';
|
|
28
28
|
import { buildReverbEnvironmentVariables } from './src/reverb';
|
|
29
29
|
import { getSecretsFingerprint } from './src/secrets-manager';
|
|
30
|
+
import { buildDefaultPublicPorts, Port } from './src/load-balancer';
|
|
30
31
|
|
|
31
32
|
// Re-export RemoteEnvVault for external use
|
|
32
33
|
export { RemoteEnvVault, RemoteEnvVaultArgs };
|
|
33
34
|
|
|
34
|
-
// duplicate from cluster.ts
|
|
35
|
-
type Port = `${number}/${'http' | 'https' | 'tcp' | 'udp' | 'tcp_udp' | 'tls'}`;
|
|
36
|
-
|
|
37
|
-
type Ports = {
|
|
38
|
-
listen: Port;
|
|
39
|
-
forward: Port;
|
|
40
|
-
}[];
|
|
41
|
-
|
|
42
35
|
enum ImageType {
|
|
43
36
|
Web = 'web',
|
|
44
37
|
Worker = 'worker',
|
|
@@ -132,11 +125,93 @@ export interface LaravelServiceArgs {
|
|
|
132
125
|
>;
|
|
133
126
|
}
|
|
134
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Shorthand for the load balancer health check applied to the default forward
|
|
130
|
+
* port. Mirrors the inner shape of SST's `loadBalancer.health` entry, minus the
|
|
131
|
+
* per-port keying which the package fills in for you.
|
|
132
|
+
*
|
|
133
|
+
* Not used when {@link LaravelWebArgs.loadBalancer} is provided — in that case
|
|
134
|
+
* configure `loadBalancer.health` directly.
|
|
135
|
+
*/
|
|
136
|
+
export interface LaravelHealthCheck {
|
|
137
|
+
/**
|
|
138
|
+
* The URL path the load balancer pings for health checks.
|
|
139
|
+
* @default `"/"`
|
|
140
|
+
*/
|
|
141
|
+
path?: Input<string>;
|
|
142
|
+
/**
|
|
143
|
+
* Time between health check requests. Between `5 seconds` and `300 seconds`.
|
|
144
|
+
* @default `"30 seconds"`
|
|
145
|
+
*/
|
|
146
|
+
interval?: Input<`${number} ${'second' | 'seconds' | 'minute' | 'minutes'}`>;
|
|
147
|
+
/**
|
|
148
|
+
* Per-request timeout. Between `2 seconds` and `120 seconds`.
|
|
149
|
+
* @default `"5 seconds"`
|
|
150
|
+
*/
|
|
151
|
+
timeout?: Input<`${number} ${'second' | 'seconds' | 'minute' | 'minutes'}`>;
|
|
152
|
+
/**
|
|
153
|
+
* Consecutive successes required to mark a target healthy. Between 2 and 10.
|
|
154
|
+
* @default `5`
|
|
155
|
+
*/
|
|
156
|
+
healthyThreshold?: Input<number>;
|
|
157
|
+
/**
|
|
158
|
+
* Consecutive failures required to mark a target unhealthy. Between 2 and 10.
|
|
159
|
+
* @default `2`
|
|
160
|
+
*/
|
|
161
|
+
unhealthyThreshold?: Input<number>;
|
|
162
|
+
/**
|
|
163
|
+
* HTTP response codes treated as successful (e.g. `"200"`, `"200-299"`).
|
|
164
|
+
* @default `"200"`
|
|
165
|
+
*/
|
|
166
|
+
successCodes?: Input<string>;
|
|
167
|
+
}
|
|
168
|
+
|
|
135
169
|
export interface LaravelWebArgs extends LaravelServiceArgs {
|
|
136
170
|
/**
|
|
137
171
|
* Custom domain for the web layer. (if you don't provide a domain name, you will be able to use the load balancer domain for testing (http only))
|
|
138
172
|
*/
|
|
139
173
|
domain?: LaravelDomain;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Load balancer health check for the web service. The package wires this
|
|
177
|
+
* to the default forward port (`8080/http`), so you only specify the
|
|
178
|
+
* check itself — not the per-port key.
|
|
179
|
+
*
|
|
180
|
+
* Distinct from {@link LaravelServiceArgs.health}, which is the ECS
|
|
181
|
+
* container-level health check.
|
|
182
|
+
*
|
|
183
|
+
* Ignored when `loadBalancer` is set — configure `loadBalancer.health`
|
|
184
|
+
* yourself in that case.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```js
|
|
188
|
+
* web: {
|
|
189
|
+
* healthCheck: { path: '/up' },
|
|
190
|
+
* }
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
healthCheck?: Input<LaravelHealthCheck>;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* When a `domain` is configured, redirect HTTP (port 80) traffic to the
|
|
197
|
+
* HTTPS (port 443) listener instead of forwarding it straight to the
|
|
198
|
+
* application. Set to `false` to keep forwarding HTTP traffic to the app.
|
|
199
|
+
*
|
|
200
|
+
* Has no effect when no `domain` is set (there is no HTTPS listener to
|
|
201
|
+
* redirect to) or when an explicit `loadBalancer` is provided (configure
|
|
202
|
+
* `loadBalancer.ports` yourself in that case).
|
|
203
|
+
*
|
|
204
|
+
* @default `true`
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```js
|
|
208
|
+
* web: {
|
|
209
|
+
* domain: 'example.com',
|
|
210
|
+
* httpsRedirect: false,
|
|
211
|
+
* }
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
httpsRedirect?: boolean;
|
|
140
215
|
}
|
|
141
216
|
|
|
142
217
|
export interface LaravelReverbArgs extends LaravelServiceArgs {
|
|
@@ -412,9 +487,18 @@ export class LaravelService extends Component {
|
|
|
412
487
|
? args.web.loadBalancer
|
|
413
488
|
: {
|
|
414
489
|
domain: args.web?.domain,
|
|
415
|
-
ports:
|
|
416
|
-
args.web?.domain,
|
|
417
|
-
|
|
490
|
+
ports: buildDefaultPublicPorts({
|
|
491
|
+
hasDomain: Boolean(args.web?.domain),
|
|
492
|
+
httpsRedirect:
|
|
493
|
+
args.web?.httpsRedirect ?? true,
|
|
494
|
+
}),
|
|
495
|
+
...(args.web?.healthCheck
|
|
496
|
+
? {
|
|
497
|
+
health: {
|
|
498
|
+
'8080/http': args.web.healthCheck,
|
|
499
|
+
},
|
|
500
|
+
}
|
|
501
|
+
: {}),
|
|
418
502
|
},
|
|
419
503
|
|
|
420
504
|
dev: {
|
|
@@ -577,10 +661,10 @@ export class LaravelService extends Component {
|
|
|
577
661
|
name: 'reverb',
|
|
578
662
|
loadBalancer: reverbConfig.loadBalancer ?? {
|
|
579
663
|
domain: reverbConfig.domain,
|
|
580
|
-
ports:
|
|
581
|
-
reverbConfig.domain,
|
|
582
|
-
reverbConfig.port,
|
|
583
|
-
),
|
|
664
|
+
ports: buildDefaultPublicPorts({
|
|
665
|
+
hasDomain: Boolean(reverbConfig.domain),
|
|
666
|
+
forwardPort: reverbConfig.port,
|
|
667
|
+
}),
|
|
584
668
|
health: {
|
|
585
669
|
[reverbPort]: {
|
|
586
670
|
path: '/apps',
|
|
@@ -660,27 +744,6 @@ export class LaravelService extends Component {
|
|
|
660
744
|
};
|
|
661
745
|
}
|
|
662
746
|
|
|
663
|
-
function getDefaultPublicPorts(
|
|
664
|
-
domain?: LaravelDomain,
|
|
665
|
-
forwardPortNumber = 8080,
|
|
666
|
-
): Ports {
|
|
667
|
-
let ports;
|
|
668
|
-
const forwardPort: Port = `${forwardPortNumber}/http`;
|
|
669
|
-
const portHttp: Port = '80/http';
|
|
670
|
-
const portHttps: Port = '443/https';
|
|
671
|
-
|
|
672
|
-
if (domain) {
|
|
673
|
-
ports = [
|
|
674
|
-
{ listen: portHttp, forward: forwardPort },
|
|
675
|
-
{ listen: portHttps, forward: forwardPort },
|
|
676
|
-
];
|
|
677
|
-
} else {
|
|
678
|
-
ports = [{ listen: portHttp, forward: forwardPort }];
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
return ports;
|
|
682
|
-
}
|
|
683
|
-
|
|
684
747
|
// TODO: We have to test if it works when a custom image is provided in sst.config.js
|
|
685
748
|
function getImage(imgType: ImageType, extraArgs: object = {}) {
|
|
686
749
|
const img = getDefaultImage(imgType, extraArgs);
|
package/package.json
CHANGED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type Port = `${number}/${'http' | 'https' | 'tcp' | 'udp' | 'tcp_udp' | 'tls'}`;
|
|
2
|
+
|
|
3
|
+
export type Ports = {
|
|
4
|
+
listen: Port;
|
|
5
|
+
forward?: Port;
|
|
6
|
+
redirect?: Port;
|
|
7
|
+
}[];
|
|
8
|
+
|
|
9
|
+
export interface DefaultPublicPortsOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Whether a custom domain (and therefore an HTTPS listener) is configured.
|
|
12
|
+
*/
|
|
13
|
+
hasDomain: boolean;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Container port the load balancer forwards application traffic to.
|
|
17
|
+
*
|
|
18
|
+
* @default 8080
|
|
19
|
+
*/
|
|
20
|
+
forwardPort?: number;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* When a domain is configured, redirect the HTTP (port 80) listener to the
|
|
24
|
+
* HTTPS (port 443) listener instead of forwarding it to the application.
|
|
25
|
+
* Ignored when no domain is configured, since there is no HTTPS listener to
|
|
26
|
+
* redirect to.
|
|
27
|
+
*
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
httpsRedirect?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Builds the default load balancer port mapping for a public service.
|
|
35
|
+
*
|
|
36
|
+
* Without a domain, only an HTTP listener is created (forwarding to the app).
|
|
37
|
+
* With a domain, both HTTP and HTTPS listeners are created; the HTTP listener
|
|
38
|
+
* redirects to HTTPS by default, or forwards to the app when
|
|
39
|
+
* `httpsRedirect` is disabled.
|
|
40
|
+
*/
|
|
41
|
+
export function buildDefaultPublicPorts({
|
|
42
|
+
hasDomain,
|
|
43
|
+
forwardPort = 8080,
|
|
44
|
+
httpsRedirect = true,
|
|
45
|
+
}: DefaultPublicPortsOptions): Ports {
|
|
46
|
+
const forward: Port = `${forwardPort}/http`;
|
|
47
|
+
const portHttp: Port = '80/http';
|
|
48
|
+
const portHttps: Port = '443/https';
|
|
49
|
+
|
|
50
|
+
if (!hasDomain) {
|
|
51
|
+
return [{ listen: portHttp, forward }];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return [
|
|
55
|
+
httpsRedirect
|
|
56
|
+
? { listen: portHttp, redirect: portHttps }
|
|
57
|
+
: { listen: portHttp, forward },
|
|
58
|
+
{ listen: portHttps, forward },
|
|
59
|
+
];
|
|
60
|
+
}
|