Skip to content

Commit

Permalink
encode arraybuffer with b64
Browse files Browse the repository at this point in the history
  • Loading branch information
Elia872 committed Aug 11, 2023
1 parent d81597e commit bcffb55
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 33 deletions.
1 change: 1 addition & 0 deletions packages/kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dependencies": {
"@sveltejs/vite-plugin-svelte": "^2.4.1",
"@types/cookie": "^0.5.1",
"base64-arraybuffer": "^1.0.2",
"cookie": "^0.5.0",
"devalue": "^4.3.1",
"esm-env": "^1.0.0",
Expand Down
9 changes: 8 additions & 1 deletion packages/kit/src/runtime/client/fetcher.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DEV } from 'esm-env';
import { hash } from '../hash.js';
import { decode as b64_decode } from 'base64-arraybuffer';

let loading = 0;

Expand Down Expand Up @@ -78,10 +79,16 @@ export function initial_fetch(resource, opts) {

const script = document.querySelector(selector);
if (script?.textContent) {
const { body, ...init } = JSON.parse(script.textContent);
let { body, ...init } = JSON.parse(script.textContent);

const ttl = script.getAttribute('data-ttl');
if (ttl) cache.set(selector, { body, init, ttl: 1000 * Number(ttl) });
const b64 = script.getAttribute('data-b64');
if (b64 !== null) {
// Can't use native_fetch('data:...;base64,${body}')
// csp can block the request
body = b64_decode(body);
}

return Promise.resolve(new Response(body, init));
}
Expand Down
75 changes: 43 additions & 32 deletions packages/kit/src/runtime/server/page/load_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { disable_search, make_trackable } from '../../../utils/url.js';
import { unwrap_promises } from '../../../utils/promises.js';
import { DEV } from 'esm-env';
import { validate_depends } from '../../shared.js';
import { encode as encode_b64 } from 'base64-arraybuffer';

/**
* Calls the user's server `load` function.
Expand Down Expand Up @@ -245,38 +246,33 @@ export function create_universal_fetch(event, state, fetched, csr, resolve_opts)

const proxy = new Proxy(response, {
get(response, key, _receiver) {
async function text() {
const body = await response.text();

if (!body || typeof body === 'string') {
const status_number = Number(response.status);
if (isNaN(status_number)) {
throw new Error(
`response.status is not a number. value: "${
response.status
}" type: ${typeof response.status}`
);
}

fetched.push({
url: same_origin ? url.href.slice(event.url.origin.length) : url.href,
method: event.request.method,
request_body: /** @type {string | ArrayBufferView | undefined} */ (
input instanceof Request && cloned_body
? await stream_to_string(cloned_body)
: init?.body
),
request_headers: cloned_headers,
response_body: body,
response
});
}

if (dependency) {
dependency.body = body;
/**
* @param {string} body
* @param {boolean} is_b64
*/
async function push_fetched(body, is_b64) {
const status_number = Number(response.status);
if (isNaN(status_number)) {
throw new Error(
`response.status is not a number. value: "${
response.status
}" type: ${typeof response.status}`
);
}

return body;
fetched.push({
url: same_origin ? url.href.slice(event.url.origin.length) : url.href,
method: event.request.method,
request_body: /** @type {string | ArrayBufferView | undefined} */ (
input instanceof Request && cloned_body
? await stream_to_string(cloned_body)
: init?.body
),
request_headers: cloned_headers,
response_body: body,
response,
is_b64
});
}

if (key === 'arrayBuffer') {
Expand All @@ -287,13 +283,28 @@ export function create_universal_fetch(event, state, fetched, csr, resolve_opts)
dependency.body = new Uint8Array(buffer);
}

// TODO should buffer be inlined into the page (albeit base64'd)?
// any conditions in which it shouldn't be?
if (buffer instanceof ArrayBuffer) {
await push_fetched(encode_b64(buffer), true);
}

return buffer;
};
}

async function text() {
const body = await response.text();

if (!body || typeof body === 'string') {
await push_fetched(body, false);
}

if (dependency) {
dependency.body = body;
}

return body;
}

if (key === 'text') {
return text;
}
Expand Down
4 changes: 4 additions & 0 deletions packages/kit/src/runtime/server/page/serialize_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ export function serialize_data(fetched, filter, prerendering = false) {
`data-url=${escape_html_attr(fetched.url)}`
];

if (fetched.is_b64) {
attrs.push('data-b64');
}

if (fetched.request_headers || fetched.request_body) {
/** @type {import('types').StrictBody[]} */
const values = [];
Expand Down
1 change: 1 addition & 0 deletions packages/kit/src/runtime/server/page/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface Fetched {
request_headers?: HeadersInit | undefined;
response_body: string;
response: Response;
is_b64?: boolean;
}

export type Loaded = {
Expand Down
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit bcffb55

Please sign in to comment.