Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose rawBody #1109

Merged
merged 17 commits into from
Apr 18, 2021
Merged
Prev Previous commit
Next Next commit
use rawBody, bundle worker with esbuild
  • Loading branch information
Rich-Harris committed Apr 18, 2021
commit 7dcac2d80da544db2155d3dbd62b7e14d27169d1
Original file line number Diff line number Diff line change
@@ -1,33 +1,17 @@
import { render } from './app.js'; // eslint-disable-line import/no-unresolved
// TODO hardcoding the relative location makes this brittle
import { render } from '../output/server/app.js'; // eslint-disable-line import/no-unresolved
import { getAssetFromKV, NotFoundError } from '@cloudflare/kv-asset-handler'; // eslint-disable-line import/no-unresolved

// From https://developers.cloudflare.com/workers/examples/read-post
async function readRequestBody(request) {
const { headers } = request;
const contentType = headers.get('content-type') || '';
if (contentType.includes('application/json')) {
return await request.json();
} else if (contentType.includes('application/text')) {
return await request.text();
} else if (contentType.includes('text/html')) {
return await request.text();
} else if (contentType.includes('form')) {
return await request.formData();
} else {
const myBlob = await request.blob();
const objectURL = URL.createObjectURL(myBlob);
return objectURL;
}
}

addEventListener('fetch', (event) => {
event.respondWith(handleEvent(event));
event.respondWith(handle(event));
});

async function handleEvent(event) {
//try static files first
async function handle(event) {
// try static files first
if (event.request.method == 'GET') {
try {
// TODO rather than attempting to get an asset,
// use the asset manifest to see if it exists
return await getAssetFromKV(event);
} catch (e) {
if (!(e instanceof NotFoundError)) {
Expand All @@ -38,7 +22,7 @@ async function handleEvent(event) {
}
}

//fall back to an app route
// fall back to an app route
const request = event.request;
const request_url = new URL(request.url);

Expand All @@ -47,17 +31,16 @@ async function handleEvent(event) {
host: request_url.host,
path: request_url.pathname,
query: request_url.searchParams,
body: request.body ? await readRequestBody(request) : null,
rawBody: request.body ? await read(request) : null,
headers: Object.fromEntries(request.headers),
method: request.method
});

if (rendered) {
const response = new Response(rendered.body, {
return new Response(rendered.body, {
status: rendered.status,
headers: rendered.headers
});
return response;
}
} catch (e) {
return new Response('Error rendering route:' + (e.message || e.toString()), { status: 500 });
Expand All @@ -68,3 +51,12 @@ async function handleEvent(event) {
statusText: 'Not Found'
});
}

function read(request) {
const type = request.headers.get('content-type') || '';
if (type.includes('application/octet-stream')) {
return request.arrayBuffer();
}

return request.text();
}
117 changes: 72 additions & 45 deletions packages/adapter-cloudflare-workers/index.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,95 @@
'use strict';

const { exec } = require('child_process');
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const esbuild = require('esbuild');
const toml = require('toml');

module.exports = function () {
/** @type {import('@sveltejs/kit').Adapter} */
const adapter = {
name: '@sveltejs/adapter-cloudflare-workers',
async adapt(utils) {
let wrangler_config;

if (fs.existsSync('wrangler.toml')) {
try {
wrangler_config = toml.parse(fs.readFileSync('wrangler.toml', 'utf-8'));
} catch (err) {
err.message = `Error parsing wrangler.toml: ${err.message}`;
throw err;
}
} else {
// TODO offer to create one?
throw new Error(
'Missing a wrangler.toml file. Consult https://developers.cloudflare.com/workers/platform/sites/configuration on how to setup your site'
);
}

if (!wrangler_config.site || !wrangler_config.site.bucket) {
throw new Error(
'You must specify site.bucket in wrangler.toml. Consult https://developers.cloudflare.com/workers/platform/sites/configuration'
);
}

const bucket = path.resolve(wrangler_config.site.bucket);
const entrypoint = path.resolve(wrangler_config.site['entry-point'] ?? 'workers-site');
const { site } = validate_config(utils);

utils.copy_static_files(bucket);
utils.copy_client_files(bucket);
utils.copy_server_files(entrypoint);
const bucket = site.bucket;
const entrypoint = site['entry-point'] || 'workers-site';

utils.rimraf(bucket);
utils.rimraf(entrypoint);

// copy the renderer
utils.copy(path.resolve(__dirname, 'files/render.js'), `${entrypoint}/index.js`);
utils.copy(path.resolve(__dirname, 'files/_package.json'), `${entrypoint}/package.json`);
utils.log.info('Installing worker dependencies...');
utils.copy(`${__dirname}/files/_package.json`, `.svelte/cloudflare-workers/package.json`);

// TODO would be cool if we could make this step unnecessary somehow
const stdout = execSync('npm install', { cwd: '.svelte/cloudflare-workers' });
utils.log.info(stdout.toString());

utils.log.minor('Generating worker...');
utils.copy(`${__dirname}/files/entry.js`, '.svelte/cloudflare-workers/entry.js');

await esbuild.build({
entryPoints: ['.svelte/cloudflare-workers/entry.js'],
outfile: `${entrypoint}/index.js`,
bundle: true,
platform: 'node'
});

utils.log.info('Prerendering static pages...');
await utils.prerender({
dest: bucket
});

utils.log.info('Installing Worker Dependencies...');
exec(
'npm install',
{
cwd: entrypoint
},
(error, stdout, stderr) => {
utils.log.info(stderr);
if (error) {
utils.log.error(error);
}
}
);
utils.log.minor('Copying assets...');
utils.copy_static_files(bucket);
utils.copy_client_files(bucket);
}
};

return adapter;
};

function validate_config(utils) {
if (fs.existsSync('wrangler.toml')) {
let wrangler_config;

try {
wrangler_config = toml.parse(fs.readFileSync('wrangler.toml', 'utf-8'));
} catch (err) {
err.message = `Error parsing wrangler.toml: ${err.message}`;
throw err;
}

if (!wrangler_config.site || !wrangler_config.site.bucket) {
throw new Error(
'You must specify site.bucket in wrangler.toml. Consult https://developers.cloudflare.com/workers/platform/sites/configuration'
);
}

return wrangler_config;
}

utils.log.error(
'Consult https://developers.cloudflare.com/workers/platform/sites/configuration on how to setup your site'
);

utils.log(
`
Sample wrangler.toml:

name = "<your-site-name>"
type = "javascript"
account_id = "<your-account-id>"
workers_dev = true
route = ""
zone_id = ""

[site]
bucket = "./.cloudflare/assets"
entry-point = "./.cloudflare/worker"`
.replace(/^\t+/gm, '')
.trim()
);

throw new Error('Missing a wrangler.toml file');
}
1 change: 1 addition & 0 deletions packages/adapter-cloudflare-workers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore"
},
"dependencies": {
"esbuild": "^0.11.12",
"toml": "^3.0.0"
},
"devDependencies": {
Expand Down