rsnext/packages/next/server/web/form-data.ts
Javi Velasco a815ba9f79
Implement Middleware RFC (#30081)
This PR adds support for [Middleware as per RFC ](https://github.com/vercel/next.js/discussions/29750). 

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes
2021-10-20 17:52:11 +00:00

73 lines
1.8 KiB
TypeScript

import { isBlob } from './is'
import { streamToIterator } from './utils'
const carriage = '\r\n'
const dashes = '--'
const carriageLength = 2
function escape(str: string) {
return str.replace(/"/g, '\\"')
}
function getFooter(boundary: string) {
return `${dashes}${boundary}${dashes}${carriage.repeat(2)}`
}
function getHeader(boundary: string, name: string, field: FormDataEntryValue) {
let header = ''
header += `${dashes}${boundary}${carriage}`
header += `Content-Disposition: form-data; name="${escape(name)}"`
if (isBlob(field)) {
header += `; filename="${escape(field.name)}"${carriage}`
header += `Content-Type: ${field.type || 'application/octet-stream'}`
}
return `${header}${carriage.repeat(2)}`
}
export function getBoundary() {
const array = new Uint8Array(32)
crypto.getRandomValues(array)
let str = ''
for (var i = 0; i < array.length; i++) {
str += array[i].toString(16).padStart(2, '0')
}
return str
}
export async function* formDataIterator(
form: FormData,
boundary: string
): AsyncIterableIterator<Uint8Array> {
const encoder = new TextEncoder()
for (const [name, value] of form) {
yield encoder.encode(getHeader(boundary, name, value))
if (isBlob(value)) {
const stream: ReadableStream<Uint8Array> = value.stream()
yield* streamToIterator(stream)
} else {
yield encoder.encode(value)
}
yield encoder.encode(carriage)
}
yield encoder.encode(getFooter(boundary))
}
export function getFormDataLength(form: FormData, boundary: string) {
let length = 0
for (const [name, value] of form) {
length += Buffer.byteLength(getHeader(boundary, name, value))
length += isBlob(value) ? value.size : Buffer.byteLength(String(value))
length += carriageLength
}
length += Buffer.byteLength(getFooter(boundary))
return length
}