|
24 | 24 | * SOFTWARE.
|
25 | 25 | */
|
26 | 26 |
|
27 |
| -import { decode as convert } from "iconv-lite" |
28 |
| -import getCharSet from "./utils/getCharSet" |
29 |
| -import { load as $ } from "cheerio" |
30 |
| -import { isURLSearchParams, isBlob, isArrayBuffer } from "./utils/is" |
31 |
| -import { Stream, Writable } from "stream" |
32 |
| - |
33 |
| -/** |
34 |
| -* Detect buffer encoding and convert to target encoding |
35 |
| -* ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding |
36 |
| -* |
37 |
| -* @param buffer Incoming buffer. |
38 |
| -* @param headers Headers provided with the request. |
39 |
| -*/ |
40 |
| -export function convertBody(buffer: Buffer, headers?: Headers): string { |
41 |
| - const contentType = headers instanceof Headers ? headers.get("content-type") : null |
42 |
| - let charset: string |
43 |
| - |
44 |
| - // Header |
45 |
| - if (contentType) charset = getCharSet(contentType) |
46 |
| - |
47 |
| - // No charset in content type, peek at response body for at most 1024 bytes |
48 |
| - const res = buffer.slice(0, 1024).toString() |
49 |
| - |
50 |
| - // HTML5, HTML4 and XML |
51 |
| - if (!charset && res) { |
52 |
| - charset = getCharSet( |
53 |
| - $(res)("meta[charset]").attr("charset") || // HTML5 |
54 |
| - $(res)("meta[http-equiv][content]").attr("content") || // HTML4 |
55 |
| - $(res.replace(/<\?(.*)\?>/im, "<$1>"), { xmlMode: true }).root().find("xml").attr("encoding") // XML |
56 |
| - ) |
57 |
| - } |
58 |
| - |
59 |
| - // Prevent decode issues when sites use incorrect encoding |
60 |
| - // ref: https://hsivonen.fi/encoding-menu/ |
61 |
| - if (charset && charset.toLowerCase() in ["gb2312", "gbk"]) charset = "gb18030" |
62 |
| - |
63 |
| - // Turn raw buffers into a single utf-8 buffer |
64 |
| - return convert( |
65 |
| - buffer, |
66 |
| - charset || "utf-8" |
67 |
| - ) |
68 |
| -} |
69 |
| - |
70 |
| -/** |
71 |
| - * Performs the operation "extract a `Content-Type` value from |object|" as |
72 |
| - * specified in the specification: |
73 |
| - * https://fetch.spec.whatwg.org/#concept-bodyinit-extract |
74 |
| - * |
75 |
| - * This function assumes that instance.body is present. |
76 |
| - * |
77 |
| - * @param body Any options.body input |
78 |
| - */ |
79 |
| -export function extractContentType(body: any): string | null { |
80 |
| - // Body is string |
81 |
| - if (typeof body === "string") return "text/plain;charset=UTF-8" |
82 |
| - |
83 |
| - // Body is a URLSearchParams |
84 |
| - if (isURLSearchParams(body)) return "application/x-www-form-urlencoded;charset=UTF-8" |
85 |
| - |
86 |
| - // Body is blob |
87 |
| - if (isBlob(body)) return body.type || null |
88 |
| - |
89 |
| - // Body is a Buffer (Buffer, ArrayBuffer or ArrayBufferView) |
90 |
| - if (Buffer.isBuffer(body) || isArrayBuffer(body) || ArrayBuffer.isView(body)) return null |
91 |
| - |
92 |
| - // Detect form data input from form-data module |
93 |
| - if (typeof body.getBoundary === "function") return `multipart/form-data;boundary=${body.getBoundary()}` |
94 |
| - |
95 |
| - // Body is stream - can't really do much about this |
96 |
| - if (body instanceof Stream) return null |
97 |
| - |
98 |
| - // Body constructor defaults other things to string |
99 |
| - return "text/plain;charset=UTF-8" |
100 |
| -} |
101 |
| - |
102 |
| -/** |
103 |
| - * The Fetch Standard treats this as if "total bytes" is a property on the body. |
104 |
| - * For us, we have to explicitly get it with a function. |
105 |
| - * |
106 |
| - * ref: https://fetch.spec.whatwg.org/#concept-body-total-bytes |
107 |
| - * |
108 |
| - * @param body Body object from the Body instance. |
109 |
| - */ |
110 |
| -export function getTotalBytes(body: any): number | null { |
111 |
| - // Body is null or undefined |
112 |
| - if (body == null) return 0 |
113 |
| - |
114 |
| - // Body is Blob |
115 |
| - if (isBlob(body)) return body.size |
116 |
| - |
117 |
| - // Body is Buffer |
118 |
| - if (Buffer.isBuffer(body)) return body.length |
119 |
| - |
120 |
| - // Detect form data input from form-data module |
121 |
| - if (body && typeof body.getLengthSync === "function") return body.hasKnownLength && body.hasKnownLength() ? body.getLengthSync() : null |
122 |
| - |
123 |
| - // Body is stream |
124 |
| - return null |
125 |
| -} |
126 |
| - |
127 |
| -/** |
128 |
| - * Write a Body to a Node.js WritableStream (e.g. http.Request) object. |
129 |
| - * |
130 |
| - * @param body Body object from the Body instance. |
131 |
| - * @param dest The stream to write to. |
132 |
| - */ |
133 |
| -export function writeToStream(body: any, dest: Writable): void { |
134 |
| - // Body is null |
135 |
| - if (body == null) dest.end() |
136 |
| - |
137 |
| - // Body is Blob |
138 |
| - else if (isBlob(body)) body.stream().pipe(dest) |
139 |
| - |
140 |
| - // Body is buffer |
141 |
| - else if (Buffer.isBuffer(body)) { |
142 |
| - dest.write(body) |
143 |
| - dest.end() |
144 |
| - } else { |
145 |
| - // Body is stream |
146 |
| - body.pipe(dest) |
147 |
| - } |
148 |
| -} |
| 27 | +export { convertBody } from "./lib/convert-body" |
| 28 | +export { extractContentType } from "./lib/extract-content-type" |
| 29 | +export { getTotalBytes } from "./lib/get-total-bytes" |
| 30 | +export { writeToStream } from "./lib/write-to-stream" |
0 commit comments