@comapeo/map-server 1.0.0-pre.0 → 1.0.0-pre.2
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.
- package/dist/context.d.ts +1 -1
- package/dist/context.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/map-share.js +1 -1
- package/dist/routes/maps.js +1 -1
- package/dist/types.d.ts +5 -5
- package/dist/types.js +2 -2
- package/node_modules/@fastify/busboy/LICENSE +24 -0
- package/node_modules/@fastify/busboy/README.md +270 -0
- package/node_modules/@fastify/busboy/deps/dicer/LICENSE +19 -0
- package/node_modules/@fastify/busboy/deps/dicer/lib/Dicer.js +213 -0
- package/node_modules/@fastify/busboy/deps/dicer/lib/HeaderParser.js +100 -0
- package/node_modules/@fastify/busboy/deps/dicer/lib/PartStream.js +13 -0
- package/node_modules/@fastify/busboy/deps/dicer/lib/dicer.d.ts +164 -0
- package/node_modules/@fastify/busboy/deps/streamsearch/sbmh.js +230 -0
- package/node_modules/@fastify/busboy/lib/main.d.ts +196 -0
- package/node_modules/@fastify/busboy/lib/main.js +85 -0
- package/node_modules/@fastify/busboy/lib/types/multipart.js +306 -0
- package/node_modules/@fastify/busboy/lib/types/urlencoded.js +190 -0
- package/node_modules/@fastify/busboy/lib/utils/Decoder.js +54 -0
- package/node_modules/@fastify/busboy/lib/utils/basename.js +14 -0
- package/node_modules/@fastify/busboy/lib/utils/decodeText.js +114 -0
- package/node_modules/@fastify/busboy/lib/utils/getLimit.js +16 -0
- package/node_modules/@fastify/busboy/lib/utils/parseParams.js +201 -0
- package/node_modules/@fastify/busboy/package.json +81 -0
- package/node_modules/@whatwg-node/fetch/CHANGELOG.md +941 -0
- package/node_modules/@whatwg-node/fetch/README.md +141 -0
- package/node_modules/@whatwg-node/fetch/dist/create-node-ponyfill.js +100 -0
- package/node_modules/@whatwg-node/fetch/dist/esm-ponyfill.js +71 -0
- package/node_modules/@whatwg-node/fetch/dist/global-ponyfill.js +22 -0
- package/node_modules/@whatwg-node/fetch/dist/index.d.ts +73 -0
- package/node_modules/@whatwg-node/fetch/dist/node-ponyfill.js +35 -0
- package/node_modules/@whatwg-node/fetch/dist/shouldSkipPonyfill.js +17 -0
- package/node_modules/@whatwg-node/fetch/package.json +31 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/AbortError.js +19 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/Blob.js +291 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/Body.js +529 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/CompressionStream.js +34 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/DecompressionStream.js +34 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/File.js +15 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/FormData.js +150 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/Headers.js +309 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/IteratorObject.js +134 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/ReadableStream.js +245 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/Request.js +128 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/Response.js +108 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/TextEncoderDecoder.js +49 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/TextEncoderDecoderStream.js +40 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/TransformStream.js +79 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/URL.js +28 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/URLSearchParams.js +4 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/WritableStream.js +115 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/fetch.js +107 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/fetchCurl.js +142 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/fetchNodeHttp.js +152 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/index.js +42 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/package.json +1 -0
- package/node_modules/@whatwg-node/node-fetch/cjs/utils.js +125 -0
- package/node_modules/@whatwg-node/node-fetch/esm/AbortError.js +15 -0
- package/node_modules/@whatwg-node/node-fetch/esm/Blob.js +279 -0
- package/node_modules/@whatwg-node/node-fetch/esm/Body.js +525 -0
- package/node_modules/@whatwg-node/node-fetch/esm/CompressionStream.js +29 -0
- package/node_modules/@whatwg-node/node-fetch/esm/DecompressionStream.js +29 -0
- package/node_modules/@whatwg-node/node-fetch/esm/File.js +11 -0
- package/node_modules/@whatwg-node/node-fetch/esm/FormData.js +145 -0
- package/node_modules/@whatwg-node/node-fetch/esm/Headers.js +304 -0
- package/node_modules/@whatwg-node/node-fetch/esm/IteratorObject.js +130 -0
- package/node_modules/@whatwg-node/node-fetch/esm/ReadableStream.js +241 -0
- package/node_modules/@whatwg-node/node-fetch/esm/Request.js +124 -0
- package/node_modules/@whatwg-node/node-fetch/esm/Response.js +104 -0
- package/node_modules/@whatwg-node/node-fetch/esm/TextEncoderDecoder.js +43 -0
- package/node_modules/@whatwg-node/node-fetch/esm/TextEncoderDecoderStream.js +35 -0
- package/node_modules/@whatwg-node/node-fetch/esm/TransformStream.js +75 -0
- package/node_modules/@whatwg-node/node-fetch/esm/URL.js +24 -0
- package/node_modules/@whatwg-node/node-fetch/esm/URLSearchParams.js +1 -0
- package/node_modules/@whatwg-node/node-fetch/esm/WritableStream.js +111 -0
- package/node_modules/@whatwg-node/node-fetch/esm/fetch.js +104 -0
- package/node_modules/@whatwg-node/node-fetch/esm/fetchCurl.js +139 -0
- package/node_modules/@whatwg-node/node-fetch/esm/fetchNodeHttp.js +148 -0
- package/node_modules/@whatwg-node/node-fetch/esm/index.js +18 -0
- package/node_modules/@whatwg-node/node-fetch/esm/utils.js +110 -0
- package/node_modules/@whatwg-node/node-fetch/package.json +46 -0
- package/node_modules/@whatwg-node/node-fetch/typings/AbortError.d.cts +4 -0
- package/node_modules/@whatwg-node/node-fetch/typings/AbortError.d.ts +4 -0
- package/node_modules/@whatwg-node/node-fetch/typings/Blob.d.cts +63 -0
- package/node_modules/@whatwg-node/node-fetch/typings/Blob.d.ts +63 -0
- package/node_modules/@whatwg-node/node-fetch/typings/Body.d.cts +54 -0
- package/node_modules/@whatwg-node/node-fetch/typings/Body.d.ts +54 -0
- package/node_modules/@whatwg-node/node-fetch/typings/CompressionStream.d.cts +6 -0
- package/node_modules/@whatwg-node/node-fetch/typings/CompressionStream.d.ts +6 -0
- package/node_modules/@whatwg-node/node-fetch/typings/DecompressionStream.d.cts +6 -0
- package/node_modules/@whatwg-node/node-fetch/typings/DecompressionStream.d.ts +6 -0
- package/node_modules/@whatwg-node/node-fetch/typings/File.d.cts +7 -0
- package/node_modules/@whatwg-node/node-fetch/typings/File.d.ts +7 -0
- package/node_modules/@whatwg-node/node-fetch/typings/FormData.d.cts +22 -0
- package/node_modules/@whatwg-node/node-fetch/typings/FormData.d.ts +22 -0
- package/node_modules/@whatwg-node/node-fetch/typings/Headers.d.cts +26 -0
- package/node_modules/@whatwg-node/node-fetch/typings/Headers.d.ts +26 -0
- package/node_modules/@whatwg-node/node-fetch/typings/IteratorObject.d.cts +20 -0
- package/node_modules/@whatwg-node/node-fetch/typings/IteratorObject.d.ts +20 -0
- package/node_modules/@whatwg-node/node-fetch/typings/ReadableStream.d.cts +27 -0
- package/node_modules/@whatwg-node/node-fetch/typings/ReadableStream.d.ts +27 -0
- package/node_modules/@whatwg-node/node-fetch/typings/Request.d.cts +38 -0
- package/node_modules/@whatwg-node/node-fetch/typings/Request.d.ts +38 -0
- package/node_modules/@whatwg-node/node-fetch/typings/Response.d.cts +23 -0
- package/node_modules/@whatwg-node/node-fetch/typings/Response.d.ts +23 -0
- package/node_modules/@whatwg-node/node-fetch/typings/TextEncoderDecoder.d.cts +15 -0
- package/node_modules/@whatwg-node/node-fetch/typings/TextEncoderDecoder.d.ts +15 -0
- package/node_modules/@whatwg-node/node-fetch/typings/TextEncoderDecoderStream.d.cts +14 -0
- package/node_modules/@whatwg-node/node-fetch/typings/TextEncoderDecoderStream.d.ts +14 -0
- package/node_modules/@whatwg-node/node-fetch/typings/TransformStream.d.cts +9 -0
- package/node_modules/@whatwg-node/node-fetch/typings/TransformStream.d.ts +9 -0
- package/node_modules/@whatwg-node/node-fetch/typings/URL.d.cts +16 -0
- package/node_modules/@whatwg-node/node-fetch/typings/URL.d.ts +16 -0
- package/node_modules/@whatwg-node/node-fetch/typings/URLSearchParams.d.cts +4 -0
- package/node_modules/@whatwg-node/node-fetch/typings/URLSearchParams.d.ts +4 -0
- package/node_modules/@whatwg-node/node-fetch/typings/WritableStream.d.cts +9 -0
- package/node_modules/@whatwg-node/node-fetch/typings/WritableStream.d.ts +9 -0
- package/node_modules/@whatwg-node/node-fetch/typings/fetch.d.cts +3 -0
- package/node_modules/@whatwg-node/node-fetch/typings/fetch.d.ts +3 -0
- package/node_modules/@whatwg-node/node-fetch/typings/fetchCurl.d.cts +3 -0
- package/node_modules/@whatwg-node/node-fetch/typings/fetchCurl.d.ts +3 -0
- package/node_modules/@whatwg-node/node-fetch/typings/fetchNodeHttp.d.cts +3 -0
- package/node_modules/@whatwg-node/node-fetch/typings/fetchNodeHttp.d.ts +3 -0
- package/node_modules/@whatwg-node/node-fetch/typings/index.d.cts +18 -0
- package/node_modules/@whatwg-node/node-fetch/typings/index.d.ts +18 -0
- package/node_modules/@whatwg-node/node-fetch/typings/utils.d.cts +21 -0
- package/node_modules/@whatwg-node/node-fetch/typings/utils.d.ts +21 -0
- package/node_modules/@whatwg-node/server/package.json +2 -1
- package/node_modules/urlpattern-polyfill/LICENSE +19 -0
- package/node_modules/urlpattern-polyfill/README.md +242 -0
- package/node_modules/urlpattern-polyfill/dist/index.d.ts +9 -0
- package/node_modules/urlpattern-polyfill/dist/types.d.ts +49 -0
- package/node_modules/urlpattern-polyfill/dist/urlpattern.cjs +1 -0
- package/node_modules/urlpattern-polyfill/dist/urlpattern.js +1 -0
- package/node_modules/urlpattern-polyfill/index.cjs +7 -0
- package/node_modules/urlpattern-polyfill/index.js +7 -0
- package/node_modules/urlpattern-polyfill/package.json +149 -0
- package/package.json +18 -8
- package/src/context.ts +1 -1
- package/src/index.ts +2 -0
- package/src/lib/map-share.ts +1 -1
- package/src/routes/maps.ts +1 -1
- package/src/types.ts +2 -2
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// Definitions by: Jacob Baskin <https://github.com/jacobbaskin>
|
|
2
|
+
// BendingBender <https://github.com/BendingBender>
|
|
3
|
+
// Igor Savin <https://github.com/kibertoad>
|
|
4
|
+
|
|
5
|
+
/// <reference types="node" />
|
|
6
|
+
|
|
7
|
+
import * as http from 'node:http';
|
|
8
|
+
import { Readable, Writable } from 'node:stream';
|
|
9
|
+
export { Dicer } from "../deps/dicer/lib/dicer";
|
|
10
|
+
|
|
11
|
+
export const Busboy: BusboyConstructor;
|
|
12
|
+
export default Busboy;
|
|
13
|
+
|
|
14
|
+
export interface BusboyConfig {
|
|
15
|
+
/**
|
|
16
|
+
* These are the HTTP headers of the incoming request, which are used by individual parsers.
|
|
17
|
+
*/
|
|
18
|
+
headers: BusboyHeaders;
|
|
19
|
+
/**
|
|
20
|
+
* `highWaterMark` to use for this Busboy instance.
|
|
21
|
+
* @default WritableStream default.
|
|
22
|
+
*/
|
|
23
|
+
highWaterMark?: number | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* highWaterMark to use for file streams.
|
|
26
|
+
* @default ReadableStream default.
|
|
27
|
+
*/
|
|
28
|
+
fileHwm?: number | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Default character set to use when one isn't defined.
|
|
31
|
+
* @default 'utf8'
|
|
32
|
+
*/
|
|
33
|
+
defCharset?: string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Detect if a Part is a file.
|
|
36
|
+
*
|
|
37
|
+
* By default a file is detected if contentType
|
|
38
|
+
* is application/octet-stream or fileName is not
|
|
39
|
+
* undefined.
|
|
40
|
+
*
|
|
41
|
+
* Modify this to handle e.g. Blobs.
|
|
42
|
+
*/
|
|
43
|
+
isPartAFile?: (fieldName: string | undefined, contentType: string | undefined, fileName: string | undefined) => boolean;
|
|
44
|
+
/**
|
|
45
|
+
* If paths in the multipart 'filename' field shall be preserved.
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
48
|
+
preservePath?: boolean | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Various limits on incoming data.
|
|
51
|
+
*/
|
|
52
|
+
limits?:
|
|
53
|
+
| {
|
|
54
|
+
/**
|
|
55
|
+
* Max field name size (in bytes)
|
|
56
|
+
* @default 100 bytes
|
|
57
|
+
*/
|
|
58
|
+
fieldNameSize?: number | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Max field value size (in bytes)
|
|
61
|
+
* @default 1MB
|
|
62
|
+
*/
|
|
63
|
+
fieldSize?: number | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Max number of non-file fields
|
|
66
|
+
* @default Infinity
|
|
67
|
+
*/
|
|
68
|
+
fields?: number | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* For multipart forms, the max file size (in bytes)
|
|
71
|
+
* @default Infinity
|
|
72
|
+
*/
|
|
73
|
+
fileSize?: number | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* For multipart forms, the max number of file fields
|
|
76
|
+
* @default Infinity
|
|
77
|
+
*/
|
|
78
|
+
files?: number | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* For multipart forms, the max number of parts (fields + files)
|
|
81
|
+
* @default Infinity
|
|
82
|
+
*/
|
|
83
|
+
parts?: number | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* For multipart forms, the max number of header key=>value pairs to parse
|
|
86
|
+
* @default 2000
|
|
87
|
+
*/
|
|
88
|
+
headerPairs?: number | undefined;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* For multipart forms, the max size of a header part
|
|
92
|
+
* @default 81920
|
|
93
|
+
*/
|
|
94
|
+
headerSize?: number | undefined;
|
|
95
|
+
}
|
|
96
|
+
| undefined;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type BusboyHeaders = { 'content-type': string } & http.IncomingHttpHeaders;
|
|
100
|
+
|
|
101
|
+
export interface BusboyFileStream extends
|
|
102
|
+
Readable {
|
|
103
|
+
|
|
104
|
+
truncated: boolean;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* The number of bytes that have been read so far.
|
|
108
|
+
*/
|
|
109
|
+
bytesRead: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface Busboy extends Writable {
|
|
113
|
+
addListener<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
|
|
114
|
+
|
|
115
|
+
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
116
|
+
|
|
117
|
+
on<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
|
|
118
|
+
|
|
119
|
+
on(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
120
|
+
|
|
121
|
+
once<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
|
|
122
|
+
|
|
123
|
+
once(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
124
|
+
|
|
125
|
+
removeListener<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
|
|
126
|
+
|
|
127
|
+
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
128
|
+
|
|
129
|
+
off<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
|
|
130
|
+
|
|
131
|
+
off(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
132
|
+
|
|
133
|
+
prependListener<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
|
|
134
|
+
|
|
135
|
+
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
136
|
+
|
|
137
|
+
prependOnceListener<Event extends keyof BusboyEvents>(event: Event, listener: BusboyEvents[Event]): this;
|
|
138
|
+
|
|
139
|
+
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export interface BusboyEvents {
|
|
143
|
+
/**
|
|
144
|
+
* Emitted for each new file form field found.
|
|
145
|
+
*
|
|
146
|
+
* * Note: if you listen for this event, you should always handle the `stream` no matter if you care about the
|
|
147
|
+
* file contents or not (e.g. you can simply just do `stream.resume();` if you want to discard the contents),
|
|
148
|
+
* otherwise the 'finish' event will never fire on the Busboy instance. However, if you don't care about **any**
|
|
149
|
+
* incoming files, you can simply not listen for the 'file' event at all and any/all files will be automatically
|
|
150
|
+
* and safely discarded (these discarded files do still count towards `files` and `parts` limits).
|
|
151
|
+
* * If a configured file size limit was reached, `stream` will both have a boolean property `truncated`
|
|
152
|
+
* (best checked at the end of the stream) and emit a 'limit' event to notify you when this happens.
|
|
153
|
+
*
|
|
154
|
+
* @param listener.transferEncoding Contains the 'Content-Transfer-Encoding' value for the file stream.
|
|
155
|
+
* @param listener.mimeType Contains the 'Content-Type' value for the file stream.
|
|
156
|
+
*/
|
|
157
|
+
file: (
|
|
158
|
+
fieldname: string,
|
|
159
|
+
stream: BusboyFileStream,
|
|
160
|
+
filename: string,
|
|
161
|
+
transferEncoding: string,
|
|
162
|
+
mimeType: string,
|
|
163
|
+
) => void;
|
|
164
|
+
/**
|
|
165
|
+
* Emitted for each new non-file field found.
|
|
166
|
+
*/
|
|
167
|
+
field: (
|
|
168
|
+
fieldname: string,
|
|
169
|
+
value: string,
|
|
170
|
+
fieldnameTruncated: boolean,
|
|
171
|
+
valueTruncated: boolean,
|
|
172
|
+
transferEncoding: string,
|
|
173
|
+
mimeType: string,
|
|
174
|
+
) => void;
|
|
175
|
+
finish: () => void;
|
|
176
|
+
/**
|
|
177
|
+
* Emitted when specified `parts` limit has been reached. No more 'file' or 'field' events will be emitted.
|
|
178
|
+
*/
|
|
179
|
+
partsLimit: () => void;
|
|
180
|
+
/**
|
|
181
|
+
* Emitted when specified `files` limit has been reached. No more 'file' events will be emitted.
|
|
182
|
+
*/
|
|
183
|
+
filesLimit: () => void;
|
|
184
|
+
/**
|
|
185
|
+
* Emitted when specified `fields` limit has been reached. No more 'field' events will be emitted.
|
|
186
|
+
*/
|
|
187
|
+
fieldsLimit: () => void;
|
|
188
|
+
error: (error: unknown) => void;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface BusboyConstructor {
|
|
192
|
+
(options: BusboyConfig): Busboy;
|
|
193
|
+
|
|
194
|
+
new(options: BusboyConfig): Busboy;
|
|
195
|
+
}
|
|
196
|
+
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const WritableStream = require('node:stream').Writable
|
|
4
|
+
const { inherits } = require('node:util')
|
|
5
|
+
const Dicer = require('../deps/dicer/lib/Dicer')
|
|
6
|
+
|
|
7
|
+
const MultipartParser = require('./types/multipart')
|
|
8
|
+
const UrlencodedParser = require('./types/urlencoded')
|
|
9
|
+
const parseParams = require('./utils/parseParams')
|
|
10
|
+
|
|
11
|
+
function Busboy (opts) {
|
|
12
|
+
if (!(this instanceof Busboy)) { return new Busboy(opts) }
|
|
13
|
+
|
|
14
|
+
if (typeof opts !== 'object') {
|
|
15
|
+
throw new TypeError('Busboy expected an options-Object.')
|
|
16
|
+
}
|
|
17
|
+
if (typeof opts.headers !== 'object') {
|
|
18
|
+
throw new TypeError('Busboy expected an options-Object with headers-attribute.')
|
|
19
|
+
}
|
|
20
|
+
if (typeof opts.headers['content-type'] !== 'string') {
|
|
21
|
+
throw new TypeError('Missing Content-Type-header.')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
headers,
|
|
26
|
+
...streamOptions
|
|
27
|
+
} = opts
|
|
28
|
+
|
|
29
|
+
this.opts = {
|
|
30
|
+
autoDestroy: false,
|
|
31
|
+
...streamOptions
|
|
32
|
+
}
|
|
33
|
+
WritableStream.call(this, this.opts)
|
|
34
|
+
|
|
35
|
+
this._done = false
|
|
36
|
+
this._parser = this.getParserByHeaders(headers)
|
|
37
|
+
this._finished = false
|
|
38
|
+
}
|
|
39
|
+
inherits(Busboy, WritableStream)
|
|
40
|
+
|
|
41
|
+
Busboy.prototype.emit = function (ev) {
|
|
42
|
+
if (ev === 'finish') {
|
|
43
|
+
if (!this._done) {
|
|
44
|
+
this._parser?.end()
|
|
45
|
+
return
|
|
46
|
+
} else if (this._finished) {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
this._finished = true
|
|
50
|
+
}
|
|
51
|
+
WritableStream.prototype.emit.apply(this, arguments)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
Busboy.prototype.getParserByHeaders = function (headers) {
|
|
55
|
+
const parsed = parseParams(headers['content-type'])
|
|
56
|
+
|
|
57
|
+
const cfg = {
|
|
58
|
+
defCharset: this.opts.defCharset,
|
|
59
|
+
fileHwm: this.opts.fileHwm,
|
|
60
|
+
headers,
|
|
61
|
+
highWaterMark: this.opts.highWaterMark,
|
|
62
|
+
isPartAFile: this.opts.isPartAFile,
|
|
63
|
+
limits: this.opts.limits,
|
|
64
|
+
parsedConType: parsed,
|
|
65
|
+
preservePath: this.opts.preservePath
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (MultipartParser.detect.test(parsed[0])) {
|
|
69
|
+
return new MultipartParser(this, cfg)
|
|
70
|
+
}
|
|
71
|
+
if (UrlencodedParser.detect.test(parsed[0])) {
|
|
72
|
+
return new UrlencodedParser(this, cfg)
|
|
73
|
+
}
|
|
74
|
+
throw new Error('Unsupported Content-Type.')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
Busboy.prototype._write = function (chunk, encoding, cb) {
|
|
78
|
+
this._parser.write(chunk, cb)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = Busboy
|
|
82
|
+
module.exports.default = Busboy
|
|
83
|
+
module.exports.Busboy = Busboy
|
|
84
|
+
|
|
85
|
+
module.exports.Dicer = Dicer
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// TODO:
|
|
4
|
+
// * support 1 nested multipart level
|
|
5
|
+
// (see second multipart example here:
|
|
6
|
+
// http://www.w3.org/TR/html401/interact/forms.html#didx-multipartform-data)
|
|
7
|
+
// * support limits.fieldNameSize
|
|
8
|
+
// -- this will require modifications to utils.parseParams
|
|
9
|
+
|
|
10
|
+
const { Readable } = require('node:stream')
|
|
11
|
+
const { inherits } = require('node:util')
|
|
12
|
+
|
|
13
|
+
const Dicer = require('../../deps/dicer/lib/Dicer')
|
|
14
|
+
|
|
15
|
+
const parseParams = require('../utils/parseParams')
|
|
16
|
+
const decodeText = require('../utils/decodeText')
|
|
17
|
+
const basename = require('../utils/basename')
|
|
18
|
+
const getLimit = require('../utils/getLimit')
|
|
19
|
+
|
|
20
|
+
const RE_BOUNDARY = /^boundary$/i
|
|
21
|
+
const RE_FIELD = /^form-data$/i
|
|
22
|
+
const RE_CHARSET = /^charset$/i
|
|
23
|
+
const RE_FILENAME = /^filename$/i
|
|
24
|
+
const RE_NAME = /^name$/i
|
|
25
|
+
|
|
26
|
+
Multipart.detect = /^multipart\/form-data/i
|
|
27
|
+
function Multipart (boy, cfg) {
|
|
28
|
+
let i
|
|
29
|
+
let len
|
|
30
|
+
const self = this
|
|
31
|
+
let boundary
|
|
32
|
+
const limits = cfg.limits
|
|
33
|
+
const isPartAFile = cfg.isPartAFile || ((fieldName, contentType, fileName) => (contentType === 'application/octet-stream' || fileName !== undefined))
|
|
34
|
+
const parsedConType = cfg.parsedConType || []
|
|
35
|
+
const defCharset = cfg.defCharset || 'utf8'
|
|
36
|
+
const preservePath = cfg.preservePath
|
|
37
|
+
const fileOpts = { highWaterMark: cfg.fileHwm }
|
|
38
|
+
|
|
39
|
+
for (i = 0, len = parsedConType.length; i < len; ++i) {
|
|
40
|
+
if (Array.isArray(parsedConType[i]) &&
|
|
41
|
+
RE_BOUNDARY.test(parsedConType[i][0])) {
|
|
42
|
+
boundary = parsedConType[i][1]
|
|
43
|
+
break
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function checkFinished () {
|
|
48
|
+
if (nends === 0 && finished && !boy._done) {
|
|
49
|
+
finished = false
|
|
50
|
+
self.end()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (typeof boundary !== 'string') { throw new Error('Multipart: Boundary not found') }
|
|
55
|
+
|
|
56
|
+
const fieldSizeLimit = getLimit(limits, 'fieldSize', 1 * 1024 * 1024)
|
|
57
|
+
const fileSizeLimit = getLimit(limits, 'fileSize', Infinity)
|
|
58
|
+
const filesLimit = getLimit(limits, 'files', Infinity)
|
|
59
|
+
const fieldsLimit = getLimit(limits, 'fields', Infinity)
|
|
60
|
+
const partsLimit = getLimit(limits, 'parts', Infinity)
|
|
61
|
+
const headerPairsLimit = getLimit(limits, 'headerPairs', 2000)
|
|
62
|
+
const headerSizeLimit = getLimit(limits, 'headerSize', 80 * 1024)
|
|
63
|
+
|
|
64
|
+
let nfiles = 0
|
|
65
|
+
let nfields = 0
|
|
66
|
+
let nends = 0
|
|
67
|
+
let curFile
|
|
68
|
+
let curField
|
|
69
|
+
let finished = false
|
|
70
|
+
|
|
71
|
+
this._needDrain = false
|
|
72
|
+
this._pause = false
|
|
73
|
+
this._cb = undefined
|
|
74
|
+
this._nparts = 0
|
|
75
|
+
this._boy = boy
|
|
76
|
+
|
|
77
|
+
const parserCfg = {
|
|
78
|
+
boundary,
|
|
79
|
+
maxHeaderPairs: headerPairsLimit,
|
|
80
|
+
maxHeaderSize: headerSizeLimit,
|
|
81
|
+
partHwm: fileOpts.highWaterMark,
|
|
82
|
+
highWaterMark: cfg.highWaterMark
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this.parser = new Dicer(parserCfg)
|
|
86
|
+
this.parser.on('drain', function () {
|
|
87
|
+
self._needDrain = false
|
|
88
|
+
if (self._cb && !self._pause) {
|
|
89
|
+
const cb = self._cb
|
|
90
|
+
self._cb = undefined
|
|
91
|
+
cb()
|
|
92
|
+
}
|
|
93
|
+
}).on('part', function onPart (part) {
|
|
94
|
+
if (++self._nparts > partsLimit) {
|
|
95
|
+
self.parser.removeListener('part', onPart)
|
|
96
|
+
self.parser.on('part', skipPart)
|
|
97
|
+
boy.hitPartsLimit = true
|
|
98
|
+
boy.emit('partsLimit')
|
|
99
|
+
return skipPart(part)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// hack because streams2 _always_ doesn't emit 'end' until nextTick, so let
|
|
103
|
+
// us emit 'end' early since we know the part has ended if we are already
|
|
104
|
+
// seeing the next part
|
|
105
|
+
if (curField) {
|
|
106
|
+
const field = curField
|
|
107
|
+
field.emit('end')
|
|
108
|
+
field.removeAllListeners('end')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
part.on('header', function (header) {
|
|
112
|
+
let contype
|
|
113
|
+
let fieldname
|
|
114
|
+
let parsed
|
|
115
|
+
let charset
|
|
116
|
+
let encoding
|
|
117
|
+
let filename
|
|
118
|
+
let nsize = 0
|
|
119
|
+
|
|
120
|
+
if (header['content-type']) {
|
|
121
|
+
parsed = parseParams(header['content-type'][0])
|
|
122
|
+
if (parsed[0]) {
|
|
123
|
+
contype = parsed[0].toLowerCase()
|
|
124
|
+
for (i = 0, len = parsed.length; i < len; ++i) {
|
|
125
|
+
if (RE_CHARSET.test(parsed[i][0])) {
|
|
126
|
+
charset = parsed[i][1].toLowerCase()
|
|
127
|
+
break
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (contype === undefined) { contype = 'text/plain' }
|
|
134
|
+
if (charset === undefined) { charset = defCharset }
|
|
135
|
+
|
|
136
|
+
if (header['content-disposition']) {
|
|
137
|
+
parsed = parseParams(header['content-disposition'][0])
|
|
138
|
+
if (!RE_FIELD.test(parsed[0])) { return skipPart(part) }
|
|
139
|
+
for (i = 0, len = parsed.length; i < len; ++i) {
|
|
140
|
+
if (RE_NAME.test(parsed[i][0])) {
|
|
141
|
+
fieldname = parsed[i][1]
|
|
142
|
+
} else if (RE_FILENAME.test(parsed[i][0])) {
|
|
143
|
+
filename = parsed[i][1]
|
|
144
|
+
if (!preservePath) { filename = basename(filename) }
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
} else { return skipPart(part) }
|
|
148
|
+
|
|
149
|
+
if (header['content-transfer-encoding']) { encoding = header['content-transfer-encoding'][0].toLowerCase() } else { encoding = '7bit' }
|
|
150
|
+
|
|
151
|
+
let onData,
|
|
152
|
+
onEnd
|
|
153
|
+
|
|
154
|
+
if (isPartAFile(fieldname, contype, filename)) {
|
|
155
|
+
// file/binary field
|
|
156
|
+
if (nfiles === filesLimit) {
|
|
157
|
+
if (!boy.hitFilesLimit) {
|
|
158
|
+
boy.hitFilesLimit = true
|
|
159
|
+
boy.emit('filesLimit')
|
|
160
|
+
}
|
|
161
|
+
return skipPart(part)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
++nfiles
|
|
165
|
+
|
|
166
|
+
if (boy.listenerCount('file') === 0) {
|
|
167
|
+
self.parser._ignore()
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
++nends
|
|
172
|
+
const file = new FileStream(fileOpts)
|
|
173
|
+
curFile = file
|
|
174
|
+
file.on('end', function () {
|
|
175
|
+
--nends
|
|
176
|
+
self._pause = false
|
|
177
|
+
checkFinished()
|
|
178
|
+
if (self._cb && !self._needDrain) {
|
|
179
|
+
const cb = self._cb
|
|
180
|
+
self._cb = undefined
|
|
181
|
+
cb()
|
|
182
|
+
}
|
|
183
|
+
})
|
|
184
|
+
file._read = function (n) {
|
|
185
|
+
if (!self._pause) { return }
|
|
186
|
+
self._pause = false
|
|
187
|
+
if (self._cb && !self._needDrain) {
|
|
188
|
+
const cb = self._cb
|
|
189
|
+
self._cb = undefined
|
|
190
|
+
cb()
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
boy.emit('file', fieldname, file, filename, encoding, contype)
|
|
194
|
+
|
|
195
|
+
onData = function (data) {
|
|
196
|
+
if ((nsize += data.length) > fileSizeLimit) {
|
|
197
|
+
const extralen = fileSizeLimit - nsize + data.length
|
|
198
|
+
if (extralen > 0) { file.push(data.slice(0, extralen)) }
|
|
199
|
+
file.truncated = true
|
|
200
|
+
file.bytesRead = fileSizeLimit
|
|
201
|
+
part.removeAllListeners('data')
|
|
202
|
+
file.emit('limit')
|
|
203
|
+
return
|
|
204
|
+
} else if (!file.push(data)) { self._pause = true }
|
|
205
|
+
|
|
206
|
+
file.bytesRead = nsize
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
onEnd = function () {
|
|
210
|
+
curFile = undefined
|
|
211
|
+
file.push(null)
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
// non-file field
|
|
215
|
+
if (nfields === fieldsLimit) {
|
|
216
|
+
if (!boy.hitFieldsLimit) {
|
|
217
|
+
boy.hitFieldsLimit = true
|
|
218
|
+
boy.emit('fieldsLimit')
|
|
219
|
+
}
|
|
220
|
+
return skipPart(part)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
++nfields
|
|
224
|
+
++nends
|
|
225
|
+
let buffer = ''
|
|
226
|
+
let truncated = false
|
|
227
|
+
curField = part
|
|
228
|
+
|
|
229
|
+
onData = function (data) {
|
|
230
|
+
if ((nsize += data.length) > fieldSizeLimit) {
|
|
231
|
+
const extralen = (fieldSizeLimit - (nsize - data.length))
|
|
232
|
+
buffer += data.toString('binary', 0, extralen)
|
|
233
|
+
truncated = true
|
|
234
|
+
part.removeAllListeners('data')
|
|
235
|
+
} else { buffer += data.toString('binary') }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
onEnd = function () {
|
|
239
|
+
curField = undefined
|
|
240
|
+
if (buffer.length) { buffer = decodeText(buffer, 'binary', charset) }
|
|
241
|
+
boy.emit('field', fieldname, buffer, false, truncated, encoding, contype)
|
|
242
|
+
--nends
|
|
243
|
+
checkFinished()
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/* As of node@2efe4ab761666 (v0.10.29+/v0.11.14+), busboy had become
|
|
248
|
+
broken. Streams2/streams3 is a huge black box of confusion, but
|
|
249
|
+
somehow overriding the sync state seems to fix things again (and still
|
|
250
|
+
seems to work for previous node versions).
|
|
251
|
+
*/
|
|
252
|
+
part._readableState.sync = false
|
|
253
|
+
|
|
254
|
+
part.on('data', onData)
|
|
255
|
+
part.on('end', onEnd)
|
|
256
|
+
}).on('error', function (err) {
|
|
257
|
+
if (curFile) { curFile.emit('error', err) }
|
|
258
|
+
})
|
|
259
|
+
}).on('error', function (err) {
|
|
260
|
+
boy.emit('error', err)
|
|
261
|
+
}).on('finish', function () {
|
|
262
|
+
finished = true
|
|
263
|
+
checkFinished()
|
|
264
|
+
})
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
Multipart.prototype.write = function (chunk, cb) {
|
|
268
|
+
const r = this.parser.write(chunk)
|
|
269
|
+
if (r && !this._pause) {
|
|
270
|
+
cb()
|
|
271
|
+
} else {
|
|
272
|
+
this._needDrain = !r
|
|
273
|
+
this._cb = cb
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
Multipart.prototype.end = function () {
|
|
278
|
+
const self = this
|
|
279
|
+
|
|
280
|
+
if (self.parser.writable) {
|
|
281
|
+
self.parser.end()
|
|
282
|
+
} else if (!self._boy._done) {
|
|
283
|
+
process.nextTick(function () {
|
|
284
|
+
self._boy._done = true
|
|
285
|
+
self._boy.emit('finish')
|
|
286
|
+
})
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function skipPart (part) {
|
|
291
|
+
part.resume()
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function FileStream (opts) {
|
|
295
|
+
Readable.call(this, opts)
|
|
296
|
+
|
|
297
|
+
this.bytesRead = 0
|
|
298
|
+
|
|
299
|
+
this.truncated = false
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
inherits(FileStream, Readable)
|
|
303
|
+
|
|
304
|
+
FileStream.prototype._read = function (n) {}
|
|
305
|
+
|
|
306
|
+
module.exports = Multipart
|