Skip to content

Commit f598add

Browse files
committed
feat: enhance static asset handling and improve request processing
- Refactored StaticAssetService to remove unnecessary request options, simplifying the handleRequest method. - Introduced resolveRequestHost method to streamline host resolution logic. - Updated StaticBaseController and StaticShareController to align with the new request handling approach. - Added I18nProvider to tenant missing and restricted entry points for improved localization support. Signed-off-by: Innei <tukon479@gmail.com>
1 parent 9095bb0 commit f598add

File tree

7 files changed

+53
-59
lines changed

7 files changed

+53
-59
lines changed

AGENTS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,7 @@ This project contains multiple web applications with distinct design systems. Fo
217217

218218
- **`apps/web`**: Contains the "Glassmorphic Depth Design System" for the main user-facing photo gallery. See `apps/web/AGENTS.md` for details.
219219
- **`be/apps/dashboard`**: Contains guidelines for the functional, data-driven UI of the administration panel. See `be/apps/dashboard/AGENTS.md` for details.
220+
221+
## IMPORTANT
222+
223+
Avoid feature gates/flags and any backwards compability changes - since our app is still unreleased" is really helpful.

be/apps/core/src/modules/infrastructure/static-web/static-asset.service.ts

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { extname, isAbsolute, join, normalize, relative, resolve } from 'node:pa
55
import { Readable } from 'node:stream'
66

77
import type { PrettyLogger } from '@afilmory/framework'
8-
import { createLogger } from '@afilmory/framework'
8+
import { createLogger, HttpContext } from '@afilmory/framework'
99
import { DOMParser } from 'linkedom'
1010
import { lookup as lookupMimeType } from 'mime-types'
1111

@@ -34,10 +34,6 @@ export interface StaticAssetServiceOptions {
3434
staticAssetHostResolver?: (requestHost?: string | null) => Promise<string | null>
3535
}
3636

37-
export interface StaticAssetRequestOptions {
38-
requestHost?: string | null
39-
}
40-
4137
export interface ResolvedStaticAsset {
4238
absolutePath: string
4339
relativePath: string
@@ -61,11 +57,7 @@ export abstract class StaticAssetService {
6157
this.staticAssetHostResolver = options.staticAssetHostResolver
6258
}
6359

64-
async handleRequest(
65-
fullPath: string,
66-
headOnly: boolean,
67-
options?: StaticAssetRequestOptions,
68-
): Promise<Response | null> {
60+
async handleRequest(fullPath: string, headOnly: boolean): Promise<Response | null> {
6961
const staticRoot = await this.resolveStaticRoot()
7062
if (!staticRoot) {
7163
return null
@@ -78,7 +70,7 @@ export abstract class StaticAssetService {
7870
return null
7971
}
8072

81-
return await this.createResponse(target, headOnly, options)
73+
return await this.createResponse(target, headOnly)
8274
}
8375

8476
protected get routeSegment(): string {
@@ -364,13 +356,9 @@ export abstract class StaticAssetService {
364356
return relativePath !== '' && !relativePath.startsWith('..') && !isAbsolute(relativePath)
365357
}
366358

367-
private async createResponse(
368-
file: ResolvedStaticAsset,
369-
headOnly: boolean,
370-
options?: StaticAssetRequestOptions,
371-
): Promise<Response> {
359+
private async createResponse(file: ResolvedStaticAsset, headOnly: boolean): Promise<Response> {
372360
if (this.isHtml(file.relativePath)) {
373-
return await this.createHtmlResponse(file, headOnly, options)
361+
return await this.createHtmlResponse(file, headOnly)
374362
}
375363

376364
const mimeType = lookupMimeType(file.absolutePath) || 'application/octet-stream'
@@ -390,13 +378,9 @@ export abstract class StaticAssetService {
390378
return new Response(body, { headers, status: 200 })
391379
}
392380

393-
private async createHtmlResponse(
394-
file: ResolvedStaticAsset,
395-
headOnly: boolean,
396-
options?: StaticAssetRequestOptions,
397-
): Promise<Response> {
381+
private async createHtmlResponse(file: ResolvedStaticAsset, headOnly: boolean): Promise<Response> {
398382
const html = await readFile(file.absolutePath, 'utf-8')
399-
const transformed = await this.transformIndexHtml(html, file, options)
383+
const transformed = await this.transformIndexHtml(html, file)
400384
const headers = new Headers()
401385
headers.set('content-type', 'text/html; charset=utf-8')
402386
headers.set('content-length', `${Buffer.byteLength(transformed, 'utf-8')}`)
@@ -410,16 +394,12 @@ export abstract class StaticAssetService {
410394
return new Response(transformed, { headers, status: 200 })
411395
}
412396

413-
private async transformIndexHtml(
414-
html: string,
415-
file: ResolvedStaticAsset,
416-
options?: StaticAssetRequestOptions,
417-
): Promise<string> {
397+
private async transformIndexHtml(html: string, file: ResolvedStaticAsset): Promise<string> {
418398
try {
419399
const document = DOM_PARSER.parseFromString(html, 'text/html') as unknown as StaticAssetDocument
420400
await this.decorateDocument(document, file)
421401
if (this.shouldRewriteAssetReferences(file)) {
422-
const staticAssetHost = await this.getStaticAssetHost(options?.requestHost)
402+
const staticAssetHost = await this.getStaticAssetHost(this.resolveRequestHost())
423403
this.rewriteStaticAssetReferences(document, staticAssetHost)
424404
}
425405
return document.documentElement.outerHTML
@@ -458,6 +438,29 @@ export abstract class StaticAssetService {
458438
return requestHost.trim().toLowerCase()
459439
}
460440

441+
private resolveRequestHost(): string | null {
442+
const context = HttpContext.getValue('hono')
443+
if (!context) {
444+
return null
445+
}
446+
const forwardedHost = context.req.header('x-forwarded-host')?.trim()
447+
if (forwardedHost) {
448+
return forwardedHost
449+
}
450+
451+
const host = context.req.header('host')?.trim()
452+
if (host) {
453+
return host
454+
}
455+
456+
try {
457+
const url = new URL(context.req.url)
458+
return url.hostname
459+
} catch {
460+
return null
461+
}
462+
}
463+
461464
private shouldTreatAsImmutable(relativePath: string): boolean {
462465
if (this.isHtml(relativePath)) {
463466
return false

be/apps/core/src/modules/infrastructure/static-web/static-base.controller.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { Context } from 'hono'
22

33
import type { StaticAssetService } from './static-asset.service'
4-
import { StaticControllerUtils } from './static-controller.utils'
54
import type { StaticDashboardService } from './static-dashboard.service'
65
import { STATIC_DASHBOARD_BASENAME } from './static-dashboard.service'
76
import type { StaticWebService } from './static-web.service'
@@ -20,9 +19,7 @@ export abstract class StaticBaseController {
2019
protected async serve(context: Context, service: StaticAssetService, headOnly: boolean): Promise<Response> {
2120
const pathname = context.req.path
2221
const normalizedPath = this.normalizeRequestPath(pathname, service)
23-
const response = await service.handleRequest(normalizedPath, headOnly, {
24-
requestHost: StaticControllerUtils.resolveRequestHost(context),
25-
})
22+
const response = await service.handleRequest(normalizedPath, headOnly)
2623

2724
if (response) {
2825
return response

be/apps/core/src/modules/infrastructure/static-web/static-controller.utils.ts

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { isTenantSlugReserved } from '@afilmory/utils'
22
import { BizException, ErrorCode } from 'core/errors'
33
import { ROOT_TENANT_SLUG } from 'core/modules/platform/tenant/tenant.constants'
44
import { getTenantContext, isPlaceholderTenantContext } from 'core/modules/platform/tenant/tenant.context'
5-
import type { Context } from 'hono'
65

76
import type { StaticDashboardService } from './static-dashboard.service'
87
import { STATIC_DASHBOARD_BASENAME } from './static-dashboard.service'
@@ -11,25 +10,6 @@ const TENANT_MISSING_ENTRY_PATH = `${STATIC_DASHBOARD_BASENAME}/tenant-missing.h
1110
const TENANT_RESTRICTED_ENTRY_PATH = `${STATIC_DASHBOARD_BASENAME}/tenant-restricted.html`
1211

1312
export const StaticControllerUtils = {
14-
resolveRequestHost(context: Context): string | null {
15-
const forwardedHost = context.req.header('x-forwarded-host')?.trim()
16-
if (forwardedHost) {
17-
return forwardedHost
18-
}
19-
20-
const host = context.req.header('host')?.trim()
21-
if (host) {
22-
return host
23-
}
24-
25-
try {
26-
const url = new URL(context.req.url)
27-
return url.host
28-
} catch {
29-
return null
30-
}
31-
},
32-
3313
cloneResponseWithStatus(response: Response, status: number): Response {
3414
const headers = new Headers(response.headers)
3515
return new Response(response.body, {

be/apps/core/src/modules/infrastructure/static-web/static-share.controller.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { z } from 'zod'
55

66
import { StaticControllerUtils } from './static-controller.utils'
77
import { StaticDashboardService } from './static-dashboard.service'
8-
import { STATIC_SHARE_ENTRY_PATH,StaticShareService } from './static-share.service'
8+
import { STATIC_SHARE_ENTRY_PATH, StaticShareService } from './static-share.service'
99

1010
const shareQuerySchema = z.object({
1111
id: z.string().min(1, 'Photo ID(s) required'),
@@ -28,9 +28,7 @@ export class StaticShareController {
2828
return await StaticControllerUtils.renderTenantMissingPage(this.staticDashboardService)
2929
}
3030

31-
const response = await this.staticShareService.handleRequest(STATIC_SHARE_ENTRY_PATH, false, {
32-
requestHost: StaticControllerUtils.resolveRequestHost(context),
33-
})
31+
const response = await this.staticShareService.handleRequest(STATIC_SHARE_ENTRY_PATH, false)
3432

3533
if (!response || response.status === 404) {
3634
throw new BizException(ErrorCode.COMMON_NOT_FOUND, {

be/apps/dashboard/src/entries/tenant-missing.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import '../styles/index.css'
22

33
import { createRoot } from 'react-dom/client'
44

5+
import { I18nProvider } from '~/providers/i18n-provider'
6+
57
import { TenantMissingStandalone } from '../modules/welcome/components/TenantMissingStandalone'
68

79
const root = document.querySelector('#root')
@@ -10,4 +12,8 @@ if (!root) {
1012
throw new Error('Root element not found for tenant missing entry.')
1113
}
1214

13-
createRoot(root).render(<TenantMissingStandalone />)
15+
createRoot(root).render(
16+
<I18nProvider>
17+
<TenantMissingStandalone />
18+
</I18nProvider>,
19+
)

be/apps/dashboard/src/entries/tenant-restricted.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import '../styles/index.css'
22

33
import { createRoot } from 'react-dom/client'
44

5+
import { I18nProvider } from '~/providers/i18n-provider'
6+
57
import { TenantRestrictedStandalone } from '../modules/welcome/components/TenantRestrictedStandalone'
68

79
const root = document.querySelector('#root')
@@ -10,4 +12,8 @@ if (!root) {
1012
throw new Error('Root element not found for tenant restricted entry.')
1113
}
1214

13-
createRoot(root).render(<TenantRestrictedStandalone />)
15+
createRoot(root).render(
16+
<I18nProvider>
17+
<TenantRestrictedStandalone />
18+
</I18nProvider>,
19+
)

0 commit comments

Comments
 (0)