feat(assets): Allow users to set a custom endpoint to use for image optimization (#8467)

Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
This commit is contained in:
Erika 2023-09-13 18:15:58 +02:00 committed by GitHub
parent c92e0acd71
commit ecc65abbf9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 1 deletions

View file

@ -0,0 +1,5 @@
---
'astro': minor
---
Add a new `image.endpoint` setting to allow using a custom endpoint in dev and SSR

View file

@ -974,6 +974,28 @@ export interface AstroUserConfig {
* @name Image Options
*/
image?: {
/**
* @docs
* @name image.endpoint
* @type {string}
* @default `undefined`
* @version 3.1.0
* @description
* Set the endpoint to use for image optimization in dev and SSR. Set to `undefined` to use the default endpoint.
*
* The endpoint will always be injected at `/_image`.
*
* ```js
* {
* image: {
* // Example: Use a custom image endpoint
* endpoint: './src/image-endpoint.ts',
* },
* }
* ```
*/
endpoint?: string;
/**
* @docs
* @name image.service

View file

@ -11,10 +11,12 @@ import type {
import { matchHostname, matchPattern } from './utils/remotePattern.js';
export function injectImageEndpoint(settings: AstroSettings) {
const endpointEntrypoint = settings.config.image.endpoint ?? 'astro/assets/image-endpoint';
// TODO: Add a setting to disable the image endpoint
settings.injectedRoutes.push({
pattern: '/_image',
entryPoint: 'astro/assets/image-endpoint',
entryPoint: endpointEntrypoint,
prerender: false,
});

View file

@ -183,6 +183,7 @@ export const AstroConfigSchema = z.object({
.default(ASTRO_CONFIG_DEFAULTS.redirects),
image: z
.object({
endpoint: z.string().optional(),
service: z
.object({
entrypoint: z

View file

@ -462,6 +462,47 @@ describe('astro:image', () => {
expect($('#local img').attr('data-service-config')).to.equal('bar');
});
});
describe('custom endpoint', async () => {
/** @type {import('./test-utils').DevServer} */
let customEndpointDevServer;
/** @type {import('./test-utils.js').Fixture} */
let customEndpointFixture;
before(async () => {
customEndpointFixture = await loadFixture({
root: './fixtures/core-image/',
image: {
endpoint: './src/custom-endpoint.ts',
service: testImageService({ foo: 'bar' }),
domains: ['avatars.githubusercontent.com'],
},
});
customEndpointDevServer = await customEndpointFixture.startDevServer({
server: { port: 4324 },
});
});
it('custom endpoint works', async () => {
const response = await customEndpointFixture.fetch('/');
const html = await response.text();
const $ = cheerio.load(html);
const src = $('#local img').attr('src');
let res = await customEndpointFixture.fetch(src);
expect(res.status).to.equal(200);
expect(await res.text()).to.equal(
"You fool! I'm not a image endpoint at all, I just return this!"
);
});
after(async () => {
await customEndpointDevServer.stop();
});
});
});
describe('proper errors', () => {

View file

@ -0,0 +1,3 @@
export const GET = async () => {
return new Response("You fool! I'm not a image endpoint at all, I just return this!", { status: 200 });
};