kwhitley / itty-router

A little router.
MIT License
1.7k stars 77 forks source link

does itty router support file upload handle? #151

Closed hakushigo closed 1 year ago

hakushigo commented 1 year ago

hey, i'm using itty router to create serverless back-end on cloudflare worker. Is it possible to handle upload file on itty-router?

kwhitley commented 1 year ago

Yep, it's no problem at all... check out https://itty.sh. This sends uploads file content and catches it in a Worker on the backend. Here's the (private) handler call receiving it on the backend Worker.

Basically the flow I used is this:

  1. detect MIME type from content-type header on the Request
  2. if text-based, parse as JSON
  3. if not, extract the body as an ArrayBuffer and go from there
  4. filename can be extracted from the headers as well
import { json } from 'itty-router-extras'
import { datePlus } from 'itty-time'
import { createEntry } from '~/actions/createEntry'
import { getRecords } from '~/services/db/records'
import { getKV } from '~/services/kv'
import { getStorage } from '~/services/storage'
import { str2ab } from '~/utils/buffers'
import { getAvailableKey } from '~/utils/getAvailableKey'
import { isText } from '~/utils/isText'

export const postEntry = async (request, env, context) => {
  let {
    ExpirationGroup,
    addAnalytics,
    options,
    stats,
    waitUntil,
  } = request

  let { type, ttl, keyLength } = options
  let content = isText(type)
              ? await request.json()
              : await request.arrayBuffer()

  // get services
  const records = getRecords(env)
  const kv = getKV(env)
  const storage = getStorage(env)
  const expires = datePlus(ttl)
  const filename = request.headers.get('filename')

  // turn all text content into ArrayBuffer for storage
  if (isText(type)) {
    content = str2ab(JSON.stringify(content))
  }

  // get available key
  const key: string = await getAvailableKey(records, keyLength)

  context.waitUntil(
    createEntry({ ...env, ExpirationGroup, stats })(key, { content, type, filename }, {
      ttl,
      kvEnabled: content.byteLength < 1024 * 1024,
    })
  )

  return json({
    key,
    type,
    filename,
    url: `https://ity.sh/${key}`,
  })
}
kwhitley commented 1 year ago

Gonna close this, but definitely recommend chatting on Discord if you run into issues on this - we'll help ya out! :)

hakushigo commented 1 year ago

thanks!