+19
-7
proxy.js
+19
-7
proxy.js
···
54
54
process.stdout.write(`${req.method} ${req.url} `);
55
55
const start = performance.now();
56
56
57
+
let err;
57
58
try {
58
59
if (req.method !== "GET") return error(res, 405, "Method not supported");
59
60
queueMicrotask(updateRecord);
60
61
61
62
let asset = record.value.assets[req.url.slice(1)];
63
+
let status = 200;
64
+
65
+
// if there's no matching file, try to treat it as a folder and use an index.html inside it
62
66
if (!asset) {
63
-
const path = req.url.slice(1).split("/"),
64
-
filename = path.pop();
65
-
if (!/^.+\..+$/.test(filename)) {
66
-
asset = record.value.assets[path.concat("index.html").join("/")];
67
-
}
67
+
const path = req.url.slice(1).split("/").concat("index.html").join("/");
68
+
asset = record.value.assets[path];
68
69
}
69
70
71
+
// if there's still no matching file and a fallback is defined, try to use it
72
+
if (!asset && record.value.fallback) {
73
+
asset = record.value.assets[record.value.fallback.path];
74
+
if (record.value.fallback.status) status = record.value.fallback.status;
75
+
}
76
+
77
+
// if there's *still* no matching file, return a generic 404
70
78
if (!asset) return error(res, 404, "Not found");
71
79
80
+
// fetch the file's blob
72
81
try {
73
82
const blob = await getBlob(pds, did, asset.ref.$link);
74
83
···
77
86
78
87
const contentType = blob.headers.get("content-type") || asset.file.mimeType;
79
88
res.setHeader("content-type", contentType);
89
+
res.statusCode = status;
80
90
81
91
const reader = blob.body.getReader();
82
92
while (true) {
···
84
94
if (done) break;
85
95
res.write(value);
86
96
}
97
+
87
98
res.end();
88
-
} catch (error) {
89
-
console.error(error);
99
+
} catch (e) {
100
+
err = e;
90
101
return error(res, 502, "Bad gateway");
91
102
}
92
103
} finally {
93
104
const ms = performance.now() - start;
94
105
process.stdout.write(`${res.statusCode} - ${Math.round(ms)}ms\n`);
106
+
if (err) console.error(err);
95
107
}
96
108
});
97
109
+19
-2
src/routes/~/sites/[name]/+page.svelte
+19
-2
src/routes/~/sites/[name]/+page.svelte
···
45
45
const form = e.currentTarget;
46
46
const formdata = new FormData(form);
47
47
48
-
// todo: implement me
48
+
let fallback: { path: string; status?: number } | undefined;
49
+
50
+
const fallbackPath = formdata.get("fallback_path");
51
+
if (fallbackPath && typeof fallbackPath === "string") {
52
+
fallback = { path: fallbackPath };
53
+
54
+
const fallbackStatus = formdata.get("fallback_status");
55
+
if (fallbackStatus && typeof fallbackStatus === "string") {
56
+
const status = Number.parseInt(fallbackStatus);
57
+
if (!Number.isNaN(status) && status !== 404) fallback.status = status;
58
+
}
59
+
}
60
+
61
+
await atp.updateBundle(rkey, { ...(data.record.value as any), fallback });
62
+
invalidate(`rkey:${rkey}`);
63
+
form.reset();
49
64
}
65
+
66
+
$inspect(data.record.value.fallback?.status);
50
67
</script>
51
68
52
69
<div class="detail">
···
106
123
<legend>Fallback</legend>
107
124
<label>
108
125
<span>path</span>
109
-
<input name="fallback_path" group={data.record.value.fallback?.path} />
126
+
<input name="fallback_path" value={data.record.value.fallback?.path} />
110
127
</label>
111
128
<label>
112
129
<span>200</span>