Skip to content

Source URLs are built from daCtx.path, so / resolves to /.html #256

Description

@benpeter

The four source URLs in src/routes/da-admin.js are each assembled at the call site from daCtx.path and daCtx.ext. ext is html for two different reasons: the request named .html, or it named no extension and daCtx.js:110 supplied one. The call sites cannot tell those apart, so three of them guess whether to append .${ext}, and each guess is wrong for one of the two.

/ reads /.html. /page.html reads /page.html.html. Both 404, and daSourceGet answers 200 with the empty template.

Raised by @tripodsan in #242.

Proposal

Derive it once, in getDaCtx, from the filename rather than from ext:

const sourceName = filename.includes('.') ? filename : `${filename}.html`;
daCtx.sourcePath = `/${[...pathParts, sourceName].join('/')}`;

A dot in the filename means the request named its own extension. pathParts (daCtx.js:88-100) is already lowercased, index-substituted and empty-segment-filtered, so / and /folder/ resolve without a special case.

The four sites then read daCtx.sourcePath:

ext survives for the ext !== 'html' branch, which picks compose against raw proxy. sourcePath harmonizes the URL, not that classification.

Document the surviving path fields. path is the request pathname, aemPathname is what goes to *.aem.page, sourcePath is what goes to the store. The JSDoc currently says @param {pathname} pathname for a function that takes a Request.

Drop pathname, key, propsKey, filename, isFile and name. No file outside getDaCtx reads them. They are inherited from da-admin, where key is an R2 object key and isFile separates a file from a folder. This worker has neither, and isFile is constant since daCtx.js:110.

What changes

request before after
/ /.html /index.html
/folder/ /folder/.html /folder/index.html
/page.html /page.html.html /page.html
/Page.HTML /Page.HTML.html /page.html
/a/b.plain.html /a/b.plain.html.html /a/b.plain.html
/a//b /a//b.html, da-admin answers 400 /a/b.html
/page, /index, /sheet.json unchanged unchanged

POST doubles the extension for any type today, not only .html: /sheet.json writes /sheet.json.json and /media/logo.png writes /media/logo.png.png.

POST needs a content-type gate in the same change

daSourcePost reads any body as text and re-serializes it as HTML. A 68-byte PNG posted through the worker stored 133 bytes of text/html, each non-ASCII byte replaced with U+FFFD. Today that lands on a doubled key no route serves. After the change it lands on the key GET reads, so it overwrites the asset. Gate daSourcePost on an HTML content type, or the fix turns a dead write into a destructive one.

Tests

No test asserts the outbound /source/... URL. test/routes/da-admin.test.js builds a daCtx and checks the response, never the URL handed to env.daadmin.fetch, and there is no POST test. Repoint any of the four wrongly and the suite still passes. Capture the fetched URL for /, /page.html and a non-HTML path, across GET, HEAD and POST.

Relates to #242.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions