Repository navigation
Make a file the origin does not have from the middleware named for its path - #1363
Open
jwrosewell wants to merge 38 commits into
Open
jwrosewell wants to merge 38 commits into
jwrosewell wants to merge 38 commits into
Conversation
…ts path When the origin answers `404 Not Found` for a path a `[[fetch]]` entry with a path names middleware for, core runs that middleware on an empty document of the entry's media type and its output is the file, stored and served as a fetched one is. A GET and a HEAD are answered alike. With no such entry, on any other answer from the origin, or where only the entry covering every path applies, the origin's answer stands, because a page the origin does not have is the origin's answer. `PhaseEntries::creating` finds the entry. The sellers crate says its file is made from the lines alone where the publisher has none, which its middleware already does on an empty document.
The configuration guide says it with the entries for other media types and in the ads.txt section, the integration guide tells a middleware it may be run on an empty document, and the changelog records the rule.
# Conflicts: # CHANGELOG.md # crates/ads-txt/sellers/src/lib.rs # docs/guide/configuration.md
PhaseEntries::creating is now making and skips text/html entries, so a page the origin does not have stays the origin's answer and an HTML entry ahead of a text/plain one no longer makes the file as HTML. The HEAD test now checks the answer has no body. Comments and the guides say the rule once.
A missing file was made by the first non-HTML entry whose path covered the request, so an entry for text/css on / written ahead of the text/plain entry for /ads.txt made an empty stylesheet in place of the sellers file. The entry with the longest covering path now makes it, the first written winning between two of the same length.
This was referenced Oct 15, 2026
A file was made for any path under an entry's path, so an entry at / for a media type other than HTML answered every page the origin does not have with an empty 200, and an entry at /ads.txt made /ads.txt.bak as well. An entry now makes a file at its own path alone, never at a longer path it covers and never for a folder written with its closing slash, so a page the origin does not have keeps its 404. Where entries for two media types name the path, the first written makes the file.
Core runs no middleware for a request that names no host, so a file made for one went out as an empty 200. Core now makes no file for such a request and the origin's answer stands.
The check accepted any text/plain entry that names the module, so an entry with no path wrote the lines into every text/plain response and made no ads.txt, and an entry for another path wrote them into that file. A selected module is now refused unless a [[fetch]] entry for text/plain with path /ads.txt names it, which is the entry that makes the file where the origin has none.
A POST, PUT, PATCH, DELETE or OPTIONS keeps the origin's 404. A made file carries its Content-Type alone and none of the headers the origin sent with its 404. A made file goes through publisher_response_into_streaming_response, which the Fastly adapter finishes the answer with, and carries what the middleware writes.
Through the adapter's router with the stock modules and a stub origin that answers 404 with Set-Cookie and Cache-Control, a GET for /ads.txt gets 200, text/plain; charset=utf-8, neither header and the sellers lines alone. The route tests' settings take a test's own sections through test_settings_with.
13 of 14 tasks
This was referenced Oct 17, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Changes
crates/trusted-server-core/srccrates/trusted-server-adapter-axum/testscrates/ads-txt/sellersdocs/guideCHANGELOG.mdCloses
Closes #1280
Spec
Spec: middleware-creates-a-missing-file
Test plan
CI on this pull request at 0b7c6a6 passed all 32 checks.
cargo test-fastly && cargo test-axumcargo clippy-fastly && cargo clippy-axumcargo fmt --all -- --checkcd crates/trusted-server-js/lib && npx vitest runcd crates/trusted-server-js/lib && npm run formatcd docs && npm run formatcargo build --package trusted-server-adapter-fastly --release --target wasm32-wasip1fastly compute serveChecklist
unwrap()in production code (clippy deniesunwrap_usedin CI)logmacros as AGENTS.md asks (notprintln!)Stacks on the consent prompt phases (#1362).
What this pull request does
When the origin answers
404 Not Foundfor a path under thepathof a[[fetch]]entry for a media type other than HTML, core discards the origin's body and headers and runs that entry's middleware on an empty document of the entry's media type, and its output is the file. The prefix is compared as an entry's path always is, sopath = "/ads.txt"also makes/ads.txt.bak. The made file carries onlyContent-Type. It is not stored as a template, which is HTML alone, and no cache policy applies unless an asset policy names the path, so it is made again on every request. So a publisher whose origin has noads.txtgets one made of the sellers lines alone.The rule
A well known file is made where middleware is configured for its path, and is the origin's answer where none is.
404stands, an error among them.GETand aHEADare answered alike, theHEADwith no body.The middleware is an ordinary one, given an empty document. A middleware that adds to a file writes the same on an empty one, with nothing before its first line, which the sellers module already did.
How it was verified
Not exercised: no file has been made through an adapter against a real origin. The rule is checked through the publisher path with a stub origin answering 404, and the made file is streamed through the entry's middleware.
References #1280.