UNPKG

6.41 kBMarkdownView Raw
1# file-server
2
3**A LAN server with auth, upload and multithreaded download**
4
5---
6
7<img src="https://raw.github.com/edfus/file-server/master/img/terminal.gif">
8
9This package is developed as an easy and quick mean to share files across my LAN with some more abilities like authorization / client upload / client range request.
10
11## Features
12
13- User-friendly interactive prompts powered by [prompts](https://github.com/terkelg/prompts#-prompts)
14- Multithreaded download based on [StreamSaver.js](https://github.com/jimmywarting/StreamSaver.js)
15- Composing router logic & cascading middlewares in [Koa](https://koajs.com/) style
16- HTTPS & HTTP over the same port
17
18## CMD Usage
19
20The one-line way:
21```bash
22npx @edfus/file-server
23```
24
25Alternatively, you can install this package either globally or locally
26```bash
27npm install @edfus/file-server -g
28```
29
30```bash
31npm install @edfus/file-server
32cd node_modules/@edfus/file-server
33```
34
35```bash
36git clone --depth 1 https://github.com/edfus/file-server
37cd file-server
38npm install
39```
40
41And then run:
42```bash
43# global
44serve
45# local
46npm run serve
47```
48
49Available command-line options:
50
51- `--config config_path`: The path to your preferred config location for retriving/creating/updating settings.
52- `folder_name`: The first unpaired, non-option command line argument will be treated as the `folder_name`, if exists.
53
54Specifying `folder_name` will skip the prompts, serve what you want directly using previous config (or config you provided via `--config`)
55
56Example:
57```bash
58npx @edfus/file-server /var/www/localhost/ --config /var/www/docker_volume/config
59npx @edfus/file-server --config ./configs/$(LANG=en_us_88591; date "+%B").cache ./
60
61npm run serve -- --config localconfig
62```
63
64## Env Settings
65
66See files in folder [./env/](https://github.com/edfus/file-server/tree/master/env) for behaviors that you can customize.
67
68## API
69
70A quick start snippet:
71
72```js
73
74import { App, Serve } from "@edfus/file-server";
75
76const app = new App();
77const services = new Serve().mount("./");
78for (const service of services) app.use(service);
79
80// simply sugar for http.createServer(app.callback()).listen();
81app.listen(0, "localhost", function () {
82 console.info(`File server is running at http://localhost:${this.address().port}`);
83});
84
85app.on("error", console.error);
86```
87
88This package has two named exports:
89
90### `App`
91
92Class `App` is a minimal implementation of [Koa](https://koajs.com/).
93
94Following properties are available in ctx for middlewares:
95
96```ts
97/**
98 * The prototype from which ctx is created.
99 * You may add additional properties to ctx by editing App#context
100 */
101type BasicContext = {
102 app: App,
103 /* parameter `properties` not supported */
104 throw (status?: number, message?: string): void;
105 /* parameter `properties` not supported */
106 assert (shouldBeTruthy: any, status?: number, message?: string): void;
107}
108
109type Context = BasicContext & {
110 req: IncomingMessage,
111 res: ServerResponse,
112 state: {
113 pathname: string,
114 uriObject: URL
115 },
116 url: string,
117 secure: boolean,
118 ip: string
119}
120```
121
122See <https://github.com/edfus/file-server/master/file-server.d.ts> for more details.
123
124### `Serve`
125
126class `Serve` is the core of this package, highly decoupled.
127
128```ts
129class Serve {
130 constructor();
131 implementedMethods: ["GET", "PUT", "HEAD"];
132
133 /**
134 * sugar for
135 * MUST this.implementedMethods.includes(ctx.req.method)
136 *
137 * ROUTER
138 * if (ctx.state.pathname === "/api") {
139 * switch (ctx.state.uriObject.searchParams.get("action")) {
140 * case "list":
141 * case "get-list": return this.getList(ctx);
142 * case "upload": return this.uploadFile(ctx);
143 * }
144 * }
145 *
146 * ROUTER
147 * this.serveFile(ctx);
148 */
149 [Symbol.iterator] (): IterableIterator<Middleware>;
150
151 /**
152 * will send stringified JSON {
153 * { type: "file", value: "xxx" },
154 * { type: "folder", value: "xxx" }
155 * }
156 */
157 getList (ctx: Context): Promise<void>;
158 uploadFile (ctx: Context): Promise<void>;
159 serveFile (ctx: Context): Promise<void>;
160
161 /**
162 * sugar for
163 * this.pathnameRouter.dir.push(pathname => join(directory, normalize(pathname)));
164 *
165 * this.pathnameRouter.file.push(pathname => join(directory, normalize(pathname)));
166 */
167 mount(directory: string): this
168
169 pathnameRouter: object;
170 fileResHeadersRouter: object;
171 routeThrough<T>(input: T, ...routers: Array<((input: T) => T)>): T;
172
173 etag (stats: Stats): string;
174 listCache: Map<string, object>;
175 mimeCache: Map<string, string>;
176}
177```
178
179Serve#pathnameRouter is where you can customize the routing logic:
180
181```js
182 pathnameRouter = {
183 map: [
184 pathname => pathMap.has(pathname) ? pathMap.get(pathname) : pathname,
185 ],
186 filter: [
187 // hide all files starting with . in their names
188 pathname => basename(pathname).startsWith(".") ? false : pathname
189 ],
190 fs: [
191 pathname => pathname.replace(/<|>|:|"|\||\?|\*/g, "-")
192 ],
193 file: [
194 pathname => pathname.endsWith("/") ? pathname.concat("index.html") : pathname,
195 pathname => {
196 if (/\/index.html?$/.test(pathname))
197 return {
198 done: true,
199 value: indexHTML
200 };
201 return pathname;
202 },
203 pathname => {
204 if (/^\/_lib_\//.test(pathname))
205 return {
206 done: true,
207 value: local("./lib/", pathname.replace(/^\/_lib_\//, ""))
208 };
209 return { done: false, value: pathname };
210 }
211 ],
212 dir: [
213 pathname => pathname.endsWith("/") ? pathname : pathname.concat("/")
214 ]
215 };
216```
217
218## Notes
219
220./lib/stream-saver is a modified version of [StreamSaver.js](https://github.com/jimmywarting/StreamSaver.js), only browsers compatible with [Transferable Streams](https://github.com/whatwg/streams/blob/main/transferable-streams-explainer.md) are supported and a valid SSL certificate is required for service worker registration when serving via https (http is ok, though)
221
222Strict [CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) rules is applied for $indexHTML. Delete lines in `Serve#fileResHeadersRouter.CSP` if needed.
223
224App#callback trust `proxy set headers` by default (e.g. X-Forwarded-Host, X-Forwarded-For)
225
226HTTP/2 is not supported.
\No newline at end of file