Skip to content

Commit c4de41d

Browse files
committed
Add static file serve for resources inside of data-directory (#19)
1 parent 520aca5 commit c4de41d

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

packages/server/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
"@oclif/errors": "^1.2.2",
1818
"@oclif/plugin-help": "^2.1.4",
1919
"express": "^4.16.4",
20+
"mime-types": "^2.1.21",
2021
"nexe": "^2.0.0-rc.34",
2122
"node-pty": "^0.8.1",
2223
"spdlog": "^0.7.2",
2324
"ws": "^6.1.2"
2425
},
2526
"devDependencies": {
2627
"@types/express": "^4.16.0",
28+
"@types/mime-types": "^2.1.0",
2729
"@types/ws": "^6.0.1",
2830
"string-replace-webpack-plugin": "^0.1.3",
2931
"ts-node": "^7.0.1",

packages/server/src/server.ts

+40
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import { Server, ServerOptions } from "@coder/protocol/src/node/server";
44
import { NewSessionMessage } from '@coder/protocol/src/proto';
55
import { ChildProcess } from "child_process";
66
import * as express from "express";
7+
import * as fs from "fs";
78
import * as http from "http";
9+
import * as mime from "mime-types";
810
import * as path from "path";
11+
import * as util from "util";
912
import * as ws from "ws";
1013
import { forkModule } from "./vscode/bootstrapFork";
1114

@@ -63,6 +66,43 @@ export const createApp = (registerMiddleware?: (app: express.Application) => voi
6366

6467
app.use(express.static(path.join(__dirname, "../build/web")));
6568

69+
app.get("/resource/:url(*)", async (req, res) => {
70+
try {
71+
const fullPath = `/${req.params.url}`;
72+
const relative = path.relative(options!.dataDirectory, fullPath);
73+
if (relative.startsWith("..")) {
74+
return res.status(403).end();
75+
}
76+
const exists = await util.promisify(fs.exists)(fullPath);
77+
if (!exists) {
78+
res.status(404).end();
79+
return;
80+
}
81+
const stat = await util.promisify(fs.stat)(fullPath);
82+
if (!stat.isFile()) {
83+
res.write("Resource must be a file.");
84+
res.status(422);
85+
res.end();
86+
87+
return;
88+
}
89+
let mimeType = mime.lookup(fullPath);
90+
if (mimeType === false) {
91+
mimeType = "application/octet-stream";
92+
}
93+
const content = await util.promisify(fs.readFile)(fullPath);
94+
95+
res.header("Content-Type", mimeType as string);
96+
res.write(content);
97+
res.status(200);
98+
res.end();
99+
} catch (ex) {
100+
res.write(ex.toString());
101+
res.status(500);
102+
res.end();
103+
}
104+
});
105+
66106
return {
67107
express: app,
68108
server,

packages/server/yarn.lock

+6-1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@
107107
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
108108
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
109109

110+
"@types/mime-types@^2.1.0":
111+
version "2.1.0"
112+
resolved "https://registry.yarnpkg.com/@types/mime-types/-/mime-types-2.1.0.tgz#9ca52cda363f699c69466c2a6ccdaad913ea7a73"
113+
integrity sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM=
114+
110115
"@types/mime@*":
111116
version "2.0.0"
112117
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.0.tgz#5a7306e367c539b9f6543499de8dd519fac37a8b"
@@ -2224,7 +2229,7 @@ mime-db@^1.28.0, mime-db@~1.37.0:
22242229
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8"
22252230
integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==
22262231

2227-
mime-types@^2.1.12, mime-types@~2.1.18, mime-types@~2.1.19:
2232+
mime-types@^2.1.12, mime-types@^2.1.21, mime-types@~2.1.18, mime-types@~2.1.19:
22282233
version "2.1.21"
22292234
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96"
22302235
integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==

0 commit comments

Comments
 (0)