UNPKG

@ctx-core/solid-start

Version:
107 lines (106 loc) 3.71 kB
import { ext_R_mime } from '@ctx-core/http' import type { APIGatewayProxyEvent, APIGatewayProxyEventV2, APIGatewayProxyResult } from 'aws-lambda' import { type Stats } from 'node:fs' import { readFile, stat } from 'node:fs/promises' import { dirname, extname, join, resolve } from 'node:path' // @ts-ignore import { splitCookiesString } from 'set-cookie-parser' import { type FetchEvent } from 'solid-start' import 'solid-start/node/globals.js' // @ts-ignore import { default as manifest } from '../../dist/client/route-manifest.json' // @ts-ignore import { default as _server } from './entry-server.js' const server = _server as (event:FetchEvent)=>Promise<Response> const isBase64Encoded__regex = /^(image\/[^(svg)]|audio\/|video\/|application\/(pdf|zip|vnd.|msword|x-shockwave-flash|java-archive))/ export async function handler( event:APIGatewayProxyEvent|APIGatewayProxyEventV2 ):Promise<APIGatewayProxyResult> { const url = new URL( (event as APIGatewayProxyEvent).path || (event as APIGatewayProxyEventV2).rawPath, `https://${event.requestContext.domainName}`) const client_path = resolve(join(dirname(new URL(import.meta.url).pathname), '..', 'client')) const pathname = url.pathname const fs_path = join(client_path, pathname) let stats:Stats|undefined = undefined try { stats = await stat(fs_path) } catch (err:any) { if (err.code !== 'ENOENT') { console.trace(err) throw err } } if (stats && stats.isFile()) { const ContentType = ext_R_mime[extname(pathname)] const isBase64Encoded = isBase64Encoded_(event, ContentType) const body = await readFile(fs_path) .then($=>$.toString(isBase64Encoded ? 'base64' : undefined)) .catch($=>{ console.trace($) throw $ }) return { statusCode: 200, headers: { 'content-type': ContentType }, body, isBase64Encoded, } } const clientAddress = (event as APIGatewayProxyEvent).requestContext.identity ? (event as APIGatewayProxyEvent).requestContext.identity.sourceIp : (event as APIGatewayProxyEventV2).requestContext.http.sourceIp const response = await server({ request: createRequest(event), clientAddress, locals: {}, env: { manifest }, }).catch($=>{ console.trace($) throw $ }) const headers:Record<string, string> = {} for (const [name, value] of response.headers) { headers[name] = value } if (response.headers.has('set-cookie')) { const header = /** @type {string} */ (response.headers.get('set-cookie')) headers['set-cookie'] = splitCookiesString(header) } const isBase64Encoded = isBase64Encoded_(event, response.headers.get('Content-Type') || '') const _body = await response.text() const body = isBase64Encoded ? Buffer.from(_body).toString('base64') : _body return { statusCode: response.status, headers: headers, body, isBase64Encoded: isBase64Encoded_(event, response.headers.get('Content-Type') || ''), } function createRequest(event:APIGatewayProxyEvent|APIGatewayProxyEventV2) { const headers = new Headers() for (const [key, _value] of Object.entries(event.headers)) { const value = _value as string headers.append(key, value) } const method = (event as APIGatewayProxyEvent).httpMethod || (event as APIGatewayProxyEventV2).requestContext.http.method const init:RequestInit = { method, headers, } if (method !== 'GET' && method !== 'HEAD' && event.body) { init.body = event.isBase64Encoded ? Buffer.from(event.body, 'base64').toString() : event.body } return new Request(url.href, init) } } function isBase64Encoded_(event:APIGatewayProxyEvent|APIGatewayProxyEventV2, ContentType:string) { return !!(event.isBase64Encoded || ContentType.match(isBase64Encoded__regex)) }