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

Handle base in adapters #5290

Merged
merged 5 commits into from
Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/blue-parrots-jam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@astrojs/cloudflare': major
'@astrojs/deno': major
'@astrojs/node': major
'astro': patch
---

Handle base configuration in adapters

This allows adapters to correctly handle `base` configuration. Internally Astro now matches routes when the URL includes the `base`.

Adapters now also have access to the `removeBase` method which will remove the `base` from a pathname. This is useful to look up files for static assets.
1 change: 1 addition & 0 deletions packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,7 @@ export interface PreviewServerParams {
serverEntrypoint: URL;
host: string | undefined;
port: number;
base: string;
}

export type CreatePreviewServer = (
Expand Down
16 changes: 14 additions & 2 deletions packages/astro/src/core/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { attachToResponse, getSetCookiesFromResponse } from '../cookies/index.js
import { call as callEndpoint } from '../endpoint/index.js';
import { consoleLogDestination } from '../logger/console.js';
import { error } from '../logger/core.js';
import { joinPaths, prependForwardSlash } from '../path.js';
import { joinPaths, prependForwardSlash, removeTrailingForwardSlash } from '../path.js';
import {
createEnvironment,
createRenderContext,
Expand Down Expand Up @@ -45,6 +45,8 @@ export class App {
dest: consoleLogDestination,
level: 'info',
};
#base: string;
#baseWithoutTrailingSlash: string;

constructor(manifest: Manifest, streaming = true) {
this.#manifest = manifest;
Expand Down Expand Up @@ -78,14 +80,24 @@ export class App {
ssr: true,
streaming,
});

this.#base = this.#manifest.base || '/';
this.#baseWithoutTrailingSlash = removeTrailingForwardSlash(this.#base);
}
removeBase(pathname: string) {
if(pathname.startsWith(this.#base)) {
return pathname.slice(this.#baseWithoutTrailingSlash.length + 1);
}
return pathname;
}
match(request: Request, { matchNotFound = false }: MatchOptions = {}): RouteData | undefined {
const url = new URL(request.url);
// ignore requests matching public assets
if (this.#manifest.assets.has(url.pathname)) {
return undefined;
}
let routeData = matchRoute(url.pathname, this.#manifestData);
let pathname = '/' + this.removeBase(url.pathname);
let routeData = matchRoute(pathname, this.#manifestData);

if (routeData) {
return routeData;
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/build/vite-plugin-ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ function buildManifest(
pageMap: null as any,
renderers: [],
entryModules,
assets: staticFiles.map((s) => '/' + s),
assets: staticFiles.map((s) => settings.config.base + s),
};

return ssrManifest;
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/core/preview/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export default async function preview(
serverEntrypoint: new URL(settings.config.build.serverEntry, settings.config.build.server),
host,
port,
base: settings.config.base,
});

return server;
Expand Down
15 changes: 13 additions & 2 deletions packages/astro/test/ssr-request.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ describe('Using Astro.request in SSR', () => {
root: './fixtures/ssr-request/',
adapter: testAdapter(),
output: 'server',
base: '/subpath/'
});
await fixture.build();
});

it('Gets the request pased in', async () => {
it('Gets the request passed in', async () => {
const app = await fixture.loadTestAdapterApp();
const request = new Request('http://example.com/request');
const request = new Request('http://example.com/subpath/request');
const response = await app.render(request);
expect(response.status).to.equal(200);
const html = await response.text();
const $ = cheerioLoad(html);
expect($('#origin').text()).to.equal('http://example.com');
Expand All @@ -29,4 +31,13 @@ describe('Using Astro.request in SSR', () => {
const json = await fixture.readFile('/client/cars.json');
expect(json).to.not.be.undefined;
});

it('assets can be fetched', async () => {
const app = await fixture.loadTestAdapterApp();
const request = new Request('http://example.com/subpath/cars.json');
const response = await app.render(request);
expect(response.status).to.equal(200);
const data = await response.json();
expect(data).to.be.an('array');
});
});
16 changes: 15 additions & 1 deletion packages/astro/test/test-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,23 @@ export default function ({ provideAddress } = { provideAddress: true }) {
if (id === '@my-ssr') {
return `
import { App } from 'astro/app';
import fs from 'fs';

class MyApp extends App {
render(request, routeData) {
#manifest = null;
constructor(manifest, streaming) {
super(manifest, streaming);
this.#manifest = manifest;
}

async render(request, routeData) {
const url = new URL(request.url);
if(this.#manifest.assets.has(url.pathname)) {
const filePath = new URL('../client/' + this.removeBase(url.pathname), import.meta.url);
const data = await fs.promises.readFile(filePath);
return new Response(data);
}

${provideAddress ? `request[Symbol.for('astro.clientAddress')] = '0.0.0.0';` : ''}
return super.render(request, routeData);
}
Expand Down
3 changes: 3 additions & 0 deletions packages/integrations/cloudflare/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
"dependencies": {
"esbuild": "^0.14.42"
},
"peerDependencies": {
"astro": "^1.6.3"
},
"devDependencies": {
"astro": "workspace:*",
"astro-scripts": "workspace:*",
Expand Down
4 changes: 3 additions & 1 deletion packages/integrations/cloudflare/src/server.advanced.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ type Env = {
export function createExports(manifest: SSRManifest) {
const app = new App(manifest, false);

//manifest.base

matthewp marked this conversation as resolved.
Show resolved Hide resolved
const fetch = async (request: Request, env: Env, context: any) => {
const { origin, pathname } = new URL(request.url);

// static assets
if (manifest.assets.has(pathname)) {
const assetRequest = new Request(`${origin}/static${pathname}`, request);
const assetRequest = new Request(`${origin}/static/${app.removeBase(pathname)}`, request);
return env.ASSETS.fetch(assetRequest);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/cloudflare/src/server.directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function createExports(manifest: SSRManifest) {
const { origin, pathname } = new URL(request.url);
// static assets
if (manifest.assets.has(pathname)) {
const assetRequest = new Request(`${origin}/static${pathname}`, request);
const assetRequest = new Request(`${origin}/static/${app.removeBase(pathname)}`, request);
return next(assetRequest);
}

Expand Down
3 changes: 3 additions & 0 deletions packages/integrations/deno/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
"dependencies": {
"esbuild": "^0.14.43"
},
"peerDependencies": {
"astro": "^1.6.3"
},
"devDependencies": {
"astro": "workspace:*",
"astro-scripts": "workspace:*"
Expand Down
2 changes: 1 addition & 1 deletion packages/integrations/deno/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function start(manifest: SSRManifest, options: Options) {
// If the request path wasn't found in astro,
// try to fetch a static file instead
const url = new URL(request.url);
const localPath = new URL('.' + url.pathname, clientRoot);
const localPath = new URL('./' + app.removeBase(url.pathname), clientRoot);
const fileResp = await fetch(localPath.toString());

// If the static file can't be found
Expand Down
3 changes: 3 additions & 0 deletions packages/integrations/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
"@astrojs/webapi": "^1.1.1",
"send": "^0.18.0"
},
"peerDependencies": {
"astro": "^1.6.3"
},
"devDependencies": {
"@types/send": "^0.17.1",
"astro": "workspace:*",
Expand Down
6 changes: 4 additions & 2 deletions packages/integrations/node/src/http-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ interface CreateServerOptions {
client: URL;
port: number;
host: string | undefined;
removeBase: (pathname: string) => string;
}

export function createServer(
{ client, port, host }: CreateServerOptions,
{ client, port, host, removeBase }: CreateServerOptions,
handler: http.RequestListener
) {
const listener: http.RequestListener = (req, res) => {
if (req.url) {
const stream = send(req, encodeURI(req.url), {
const pathname = '/' + removeBase(req.url);
const stream = send(req, encodeURI(pathname), {
root: fileURLToPath(client),
dotfiles: 'deny',
});
Expand Down
11 changes: 10 additions & 1 deletion packages/integrations/node/src/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { fileURLToPath } from 'url';
import { createServer } from './http-server.js';
import type { createExports } from './server';

const preview: CreatePreviewServer = async function ({ client, serverEntrypoint, host, port }) {
const preview: CreatePreviewServer = async function ({ client, serverEntrypoint, host, port, base }) {
type ServerModule = ReturnType<typeof createExports>;
type MaybeServerModule = Partial<ServerModule>;
let ssrHandler: ServerModule['handler'];
Expand Down Expand Up @@ -36,11 +36,20 @@ const preview: CreatePreviewServer = async function ({ client, serverEntrypoint,
});
};

const baseWithoutTrailingSlash: string = base.endsWith('/') ? base.slice(0, base.length - 1) : base;
function removeBase(pathname: string): string {
if(pathname.startsWith(base)) {
return pathname.slice(0, baseWithoutTrailingSlash.length);
}
matthewp marked this conversation as resolved.
Show resolved Hide resolved
return pathname;
}

const server = createServer(
{
client,
port,
host,
removeBase
},
handler
);
Expand Down
1 change: 1 addition & 0 deletions packages/integrations/node/src/standalone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default function startServer(app: NodeApp, options: Options) {
client,
port,
host,
removeBase: app.removeBase.bind(app),
},
handler
);
Expand Down