summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alan <altano@gmail.com> 2022-09-09 08:58:24 -0700
committerGravatar GitHub <noreply@github.com> 2022-09-09 11:58:24 -0400
commit255636cc7b4ed5f72045f75a2411ebd84a2bdb0d (patch)
tree1e0d3ceaf91d72581c7f4bdf98ede5501fc007b6
parentc706d845ebf4786c33d2295954a98df8c5a7f183 (diff)
downloadastro-255636cc7b4ed5f72045f75a2411ebd84a2bdb0d.tar.gz
astro-255636cc7b4ed5f72045f75a2411ebd84a2bdb0d.tar.zst
astro-255636cc7b4ed5f72045f75a2411ebd84a2bdb0d.zip
Add support for custom non-html route encoding (#4549)
* Add custom encoding support for non-html routes * Add changeset * Add tests for png and json routes
Diffstat (limited to '')
-rw-r--r--.changeset/stale-camels-invent.md5
-rw-r--r--packages/astro/src/@types/astro.ts1
-rw-r--r--packages/astro/src/core/build/generate.ts4
-rw-r--r--packages/astro/src/core/endpoint/index.ts2
-rw-r--r--packages/astro/test/fixtures/non-html-pages/package.json8
-rw-r--r--packages/astro/test/fixtures/non-html-pages/src/images/placeholder.pngbin0 -> 1040 bytes
-rw-r--r--packages/astro/test/fixtures/non-html-pages/src/pages/about.json.ts11
-rw-r--r--packages/astro/test/fixtures/non-html-pages/src/pages/placeholder.png.ts17
-rw-r--r--packages/astro/test/non-html-pages.test.js38
-rw-r--r--packages/astro/test/test-utils.js4
-rw-r--r--pnpm-lock.yaml6
11 files changed, 93 insertions, 3 deletions
diff --git a/.changeset/stale-camels-invent.md b/.changeset/stale-camels-invent.md
new file mode 100644
index 000000000..e3d88bc33
--- /dev/null
+++ b/.changeset/stale-camels-invent.md
@@ -0,0 +1,5 @@
+---
+'astro': minor
+---
+
+Allow specifying custom encoding when using a non-html route. Only option before was 'utf-8' and now that is just the default.
diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts
index b2347c410..c358d63e7 100644
--- a/packages/astro/src/@types/astro.ts
+++ b/packages/astro/src/@types/astro.ts
@@ -1085,6 +1085,7 @@ export interface APIContext {
export interface EndpointOutput {
body: Body;
+ encoding?: BufferEncoding;
}
export type APIRoute = (
diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts
index 406186a21..b6ebf4697 100644
--- a/packages/astro/src/core/build/generate.ts
+++ b/packages/astro/src/core/build/generate.ts
@@ -391,6 +391,7 @@ async function generatePath(
};
let body: string;
+ let encoding: BufferEncoding | undefined;
if (pageData.route.type === 'endpoint') {
const result = await callEndpoint(mod as unknown as EndpointHandler, options);
@@ -398,6 +399,7 @@ async function generatePath(
throw new Error(`Returning a Response from an endpoint is not supported in SSG mode.`);
}
body = result.body;
+ encoding = result.encoding;
} else {
const response = await render(options);
@@ -413,5 +415,5 @@ async function generatePath(
const outFile = getOutFile(astroConfig, outFolder, pathname, pageData.route.type);
pageData.route.distURL = outFile;
await fs.promises.mkdir(outFolder, { recursive: true });
- await fs.promises.writeFile(outFile, body, 'utf-8');
+ await fs.promises.writeFile(outFile, body, encoding ?? 'utf-8');
}
diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts
index 9e974ee36..73c96ae64 100644
--- a/packages/astro/src/core/endpoint/index.ts
+++ b/packages/astro/src/core/endpoint/index.ts
@@ -21,6 +21,7 @@ type EndpointCallResult =
| {
type: 'simple';
body: string;
+ encoding?: BufferEncoding;
}
| {
type: 'response';
@@ -52,5 +53,6 @@ export async function call(
return {
type: 'simple',
body: response.body,
+ encoding: response.encoding,
};
}
diff --git a/packages/astro/test/fixtures/non-html-pages/package.json b/packages/astro/test/fixtures/non-html-pages/package.json
new file mode 100644
index 000000000..c3a215d98
--- /dev/null
+++ b/packages/astro/test/fixtures/non-html-pages/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "@test/non-html-pages",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "astro": "workspace:*"
+ }
+}
diff --git a/packages/astro/test/fixtures/non-html-pages/src/images/placeholder.png b/packages/astro/test/fixtures/non-html-pages/src/images/placeholder.png
new file mode 100644
index 000000000..62841efdb
--- /dev/null
+++ b/packages/astro/test/fixtures/non-html-pages/src/images/placeholder.png
Binary files differ
diff --git a/packages/astro/test/fixtures/non-html-pages/src/pages/about.json.ts b/packages/astro/test/fixtures/non-html-pages/src/pages/about.json.ts
new file mode 100644
index 000000000..af61847f3
--- /dev/null
+++ b/packages/astro/test/fixtures/non-html-pages/src/pages/about.json.ts
@@ -0,0 +1,11 @@
+// Returns the file body for this non-HTML file.
+// The content type is based off of the extension in the filename,
+// in this case: about.json.
+export async function get() {
+ return {
+ body: JSON.stringify({
+ name: 'Astro',
+ url: 'https://astro.build/',
+ }),
+ };
+}
diff --git a/packages/astro/test/fixtures/non-html-pages/src/pages/placeholder.png.ts b/packages/astro/test/fixtures/non-html-pages/src/pages/placeholder.png.ts
new file mode 100644
index 000000000..0c2d3806b
--- /dev/null
+++ b/packages/astro/test/fixtures/non-html-pages/src/pages/placeholder.png.ts
@@ -0,0 +1,17 @@
+import { promises as fs } from 'node:fs';
+
+import type { APIRoute } from 'astro';
+
+export const get: APIRoute = async function get() {
+ try {
+ // Image is in the public domain. Sourced from
+ // https://en.wikipedia.org/wiki/File:Portrait_placeholder.png
+ const buffer = await fs.readFile('./test/fixtures/non-html-pages/src/images/placeholder.png');
+ return {
+ body: buffer.toString('binary'),
+ encoding: 'binary',
+ } as const;
+ } catch (error: unknown) {
+ throw new Error(`Something went wrong in placeholder.png route!: ${error as string}`);
+ }
+};
diff --git a/packages/astro/test/non-html-pages.test.js b/packages/astro/test/non-html-pages.test.js
new file mode 100644
index 000000000..e1b89ee6a
--- /dev/null
+++ b/packages/astro/test/non-html-pages.test.js
@@ -0,0 +1,38 @@
+import { expect } from 'chai';
+import { loadFixture } from './test-utils.js';
+
+describe('Non-HTML Pages', () => {
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({ root: './fixtures/non-html-pages/' });
+ await fixture.build();
+ });
+
+ describe('json', () => {
+ it('should match contents', async () => {
+ const json = JSON.parse(await fixture.readFile('/about.json'));
+ expect(json).to.have.property('name', 'Astro');
+ expect(json).to.have.property('url', 'https://astro.build/');
+ });
+ });
+
+ describe('png', () => {
+ it('should not have had its encoding mangled', async () => {
+ const buffer = await fixture.readFile('/placeholder.png', 'base64');
+
+ // Sanity check the first byte
+ const hex = Buffer.from(buffer, 'base64').toString('hex');
+ const firstHexByte = hex.slice(0, 2);
+ // If we accidentally utf8 encode the png, the first byte (in hex) will be 'c2'
+ expect(firstHexByte).to.not.equal('c2');
+ // and if correctly encoded in binary, it should be '89'
+ expect(firstHexByte).to.equal('89');
+
+ // Make sure the whole buffer (in base64) matches this snapshot
+ expect(buffer).to.equal(
+ 'iVBORw0KGgoAAAANSUhEUgAAAGQAAACWCAYAAAAouC1GAAAD10lEQVR4Xu3ZbW4iMRCE4c1RuP+ZEEfZFZHIAgHGH9Xtsv3m94yx6qHaM+HrfD7//cOfTQJfgNhYfG8EEC8PQMw8AAHELQGz/XCGAGKWgNl2aAggZgmYbYeGAGKWgNl2aAggZgmYbYeGAGKWgNl2aAggZgmYbYeGAGKWgNl2aAggZgmYbYeGAGKWgNl2aAggZgmYbYeGAGKWgNl2aAggZgmYbWe6hpxOp6oIL5dL1fWjL54CpBbhXagz4FiDqCCegZxhLEGiIGaAsQPJwrjhuLXFBiQbwrUtFiCjMZzaMhzEBcMFZSiIG4YDyjAQV4zRKENA3DFGoqSDzIIxCgWQgn9eZb6rpILM1o57qyyUNJCZMTLHFyAFI2s5kBXakYWS0hBAymsYDrISRkZLACn/8j5cGfXUFQqyYjuiWwJIY0Out0W0JAxk5XZEtgQQGtKRgOGt6rEV0pAdxlXU2AKks3U0pDPAiNuVKDREIGQNstP5EXGOyBsCSF/lAOnL7/tuRpYgRPUSKhQaIpIBRBSkahlAVEmK1gFEFKRqGUuQHR951e8i0kMdkP6+SUGu29kVxXJkAUJD+hMQrUBDREGqlgFElaRgHRXGdSsc6oAIEjBbgoYAUpfAbu8i1g3Z7V1EiRFyqANSN02er5Y/Zd0+YJexNUVDdmmJGiNsZAHSPrbCRtYOKFM1ZHWQCIzQkbX64Q5I+1iW3xmFkdKQFUcXIPLvePuCkRhpDVmpJcuArIASjZHakNmfujIwAKk4SpYFmXF0ZWEMachsoysTYyjIDE3JxhgO4owyAsMCxBFlFIYNiBPKSAxAnh57R2PYgLj9/j4SJvQXw5L3LjeM+z2PgBkG4gzx/EXKhEkHmQliRFvSQGaFyEZJAVkB4wYTPb7CQVbCyEAJA1kRImN8hYCsjhHZFDnILhhRKICUvL0eXKM86KUgu7Uj4kyRgeyMoRxfEhAw/neld3x1g4Dx+4DpQQFEcKi/WqIVpQuEdrzXTAcB47haLSjNDQHkGOR6RS1KEwgYZRgtj8PVIGDUYdS2BJD6fJvuKB1dVSC0o8ni56YSFED6Mq66WwpCO6qyf3vxEUpxQwAxAgFDg1HyGFzUEECMQMDQYhy15LAhgBiBgBGD8ent/WNDAIkDeYcCSGzmH1d/9U7yFoR25Eg9owCSk3vxmzsgM4AwrnKV7sfWy4YAAkhuAmaf9rEhtCNfC5D8zA8/8Yby6wyhIYfZhVwASEis7Yu+BKEd7YH23glIb4IB919RHs4QGhKQcsWSgFSElXEpIBkpV3zGAwjjqiK5oEsBCQq2Z9l/4WuAC09sfQEAAAAASUVORK5CYII='
+ );
+ });
+ });
+});
diff --git a/packages/astro/test/test-utils.js b/packages/astro/test/test-utils.js
index c6150b26b..59a925314 100644
--- a/packages/astro/test/test-utils.js
+++ b/packages/astro/test/test-utils.js
@@ -146,8 +146,8 @@ export async function loadFixture(inlineConfig) {
const previewServer = await preview(config, { logging, telemetry, ...opts });
return previewServer;
},
- readFile: (filePath) =>
- fs.promises.readFile(new URL(filePath.replace(/^\//, ''), config.outDir), 'utf8'),
+ readFile: (filePath, encoding) =>
+ fs.promises.readFile(new URL(filePath.replace(/^\//, ''), config.outDir), encoding ?? 'utf8'),
readdir: (fp) => fs.promises.readdir(new URL(fp.replace(/^\//, ''), config.outDir)),
glob: (p) =>
fastGlob(p, {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5e7d1dce1..e5c2a6f1e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1666,6 +1666,12 @@ importers:
packages/astro/test/fixtures/multiple-renderers/renderers/two:
specifiers: {}
+ packages/astro/test/fixtures/non-html-pages:
+ specifiers:
+ astro: workspace:*
+ dependencies:
+ astro: link:../../..
+
packages/astro/test/fixtures/page-format:
specifiers:
astro: workspace:*