@simplysm/service-server 14.0.95 → 14.0.97
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-file-handler.d.ts","sourceRoot":"","sources":["../../../src/transport/http/static-file-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK5D,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"static-file-handler.d.ts","sourceRoot":"","sources":["../../../src/transport/http/static-file-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK5D,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAsDf"}
|
|
@@ -34,6 +34,15 @@ export async function handleStaticFile(req, reply, rootPath, urlPath) {
|
|
|
34
34
|
catch (err) {
|
|
35
35
|
const error = err;
|
|
36
36
|
if (error.code === "ENOENT") {
|
|
37
|
+
// SPA 폴백: 확장자 없는 페이지 요청이면 www 루트 방향으로 가장 가까운
|
|
38
|
+
// index.csr.html(SSG 클라이언트의 SPA 셸)을 찾아 반환.
|
|
39
|
+
// 셸 파일이 없는 기존 클라이언트는 지금처럼 404 (동작 불변).
|
|
40
|
+
if (path.extname(targetFilePath) === "") {
|
|
41
|
+
const shellDir = await findSpaShellDir(path.dirname(targetFilePath), allowedRootPath);
|
|
42
|
+
if (shellDir != null) {
|
|
43
|
+
return reply.sendFile("index.csr.html", shellDir);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
37
46
|
const errorMessage = "파일을 찾을 수 없습니다.";
|
|
38
47
|
responseErrorHtml(reply, 404, errorMessage);
|
|
39
48
|
logger.warn(`[404] ${errorMessage} (${targetFilePath})`);
|
|
@@ -45,6 +54,19 @@ export async function handleStaticFile(req, reply, rootPath, urlPath) {
|
|
|
45
54
|
}
|
|
46
55
|
}
|
|
47
56
|
}
|
|
57
|
+
/** startDir 부터 www 루트까지 거슬러 올라가며 index.csr.html 이 있는 디렉토리를 찾음 */
|
|
58
|
+
async function findSpaShellDir(startDir, rootDir) {
|
|
59
|
+
let currentDir = startDir;
|
|
60
|
+
while (currentDir === rootDir || pathx.isChildPath(currentDir, rootDir)) {
|
|
61
|
+
if (await fsx.exists(path.join(currentDir, "index.csr.html"))) {
|
|
62
|
+
return currentDir;
|
|
63
|
+
}
|
|
64
|
+
if (currentDir === rootDir)
|
|
65
|
+
break;
|
|
66
|
+
currentDir = path.dirname(currentDir);
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
48
70
|
function responseErrorHtml(reply, code, message) {
|
|
49
71
|
reply.status(code).type("text/html").send(`
|
|
50
72
|
<!DOCTYPE html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-file-handler.js","sourceRoot":"","sources":["../../../src/transport/http/static-file-handler.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"static-file-handler.js","sourceRoot":"","sources":["../../../src/transport/http/static-file-handler.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/service-server",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.97",
|
|
4
4
|
"description": "심플리즘 패키지 - 서비스 (server)",
|
|
5
5
|
"author": "심플리즘",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -26,14 +26,14 @@
|
|
|
26
26
|
"bufferutil": "^4.1.0",
|
|
27
27
|
"fastify": "^5.8.5",
|
|
28
28
|
"jose": "^6.2.3",
|
|
29
|
-
"semver": "^7.8.
|
|
29
|
+
"semver": "^7.8.4",
|
|
30
30
|
"utf-8-validate": "^6.0.6",
|
|
31
31
|
"ws": "^8.21.0",
|
|
32
|
-
"@simplysm/
|
|
33
|
-
"@simplysm/
|
|
34
|
-
"@simplysm/
|
|
35
|
-
"@simplysm/
|
|
36
|
-
"@simplysm/
|
|
32
|
+
"@simplysm/core-common": "14.0.97",
|
|
33
|
+
"@simplysm/orm-node": "14.0.97",
|
|
34
|
+
"@simplysm/orm-common": "14.0.97",
|
|
35
|
+
"@simplysm/core-node": "14.0.97",
|
|
36
|
+
"@simplysm/service-common": "14.0.97"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/semver": "^7.7.1",
|
|
@@ -46,6 +46,15 @@ export async function handleStaticFile(
|
|
|
46
46
|
} catch (err: unknown) {
|
|
47
47
|
const error = err as { code?: string };
|
|
48
48
|
if (error.code === "ENOENT") {
|
|
49
|
+
// SPA 폴백: 확장자 없는 페이지 요청이면 www 루트 방향으로 가장 가까운
|
|
50
|
+
// index.csr.html(SSG 클라이언트의 SPA 셸)을 찾아 반환.
|
|
51
|
+
// 셸 파일이 없는 기존 클라이언트는 지금처럼 404 (동작 불변).
|
|
52
|
+
if (path.extname(targetFilePath) === "") {
|
|
53
|
+
const shellDir = await findSpaShellDir(path.dirname(targetFilePath), allowedRootPath);
|
|
54
|
+
if (shellDir != null) {
|
|
55
|
+
return reply.sendFile("index.csr.html", shellDir);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
49
58
|
const errorMessage = "파일을 찾을 수 없습니다.";
|
|
50
59
|
responseErrorHtml(reply, 404, errorMessage);
|
|
51
60
|
logger.warn(`[404] ${errorMessage} (${targetFilePath})`);
|
|
@@ -57,6 +66,19 @@ export async function handleStaticFile(
|
|
|
57
66
|
}
|
|
58
67
|
}
|
|
59
68
|
|
|
69
|
+
/** startDir 부터 www 루트까지 거슬러 올라가며 index.csr.html 이 있는 디렉토리를 찾음 */
|
|
70
|
+
async function findSpaShellDir(startDir: string, rootDir: string): Promise<string | undefined> {
|
|
71
|
+
let currentDir = startDir;
|
|
72
|
+
while (currentDir === rootDir || pathx.isChildPath(currentDir, rootDir)) {
|
|
73
|
+
if (await fsx.exists(path.join(currentDir, "index.csr.html"))) {
|
|
74
|
+
return currentDir;
|
|
75
|
+
}
|
|
76
|
+
if (currentDir === rootDir) break;
|
|
77
|
+
currentDir = path.dirname(currentDir);
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
60
82
|
function responseErrorHtml(reply: FastifyReply, code: number, message: string) {
|
|
61
83
|
reply.status(code).type("text/html").send(`
|
|
62
84
|
<!DOCTYPE html>
|