Skip to content

Fix source.dot.net proxied-index serving (500, .js, references, SolutionExplorer)#266

Merged
tannergooding merged 3 commits into
dotnet:mainfrom
tannergooding:tannergooding-investigate-azure-file-loading
Jul 19, 2026
Merged

Fix source.dot.net proxied-index serving (500, .js, references, SolutionExplorer)#266
tannergooding merged 3 commits into
dotnet:mainfrom
tannergooding:tannergooding-investigate-azure-file-loading

Conversation

@tannergooding

@tannergooding tannergooding commented Jul 19, 2026

Copy link
Copy Markdown
Member

Several defects that break source.dot.net, all rooted in the same thing: it serves the index from Azure blob storage through the proxy layer (SOURCE_BROWSER_INDEX_PROXY_URL set), where sites that serve the index from local disk (e.g. source.terrafx.dev, proxy disabled) never exercise the affected paths. That's why #264 surfaced them only on source.dot.net.


SolutionExplorer.html -> HTTP 500

Helpers.ProxyRequestAsync called Convert.ToBase64String(props.ContentHash) unconditionally. Azure does not guarantee a blob has a Content-MD5: block-uploaded blobs (the larger files, e.g. the ~2.8 MB SolutionExplorer.html) lack one, whereas smaller single-PutBlob uploads carry it. Convert.ToBase64String(null) threw, was rethrown as InvalidOperationException, and produced an empty-body 500. Every smaller proxied file returned 200 (with a Content-Md5), so only the large files broke.

Fix: only append Content-Md5 when ContentHash is present.


Symbol navigation shows "Don't use this page directly, pass #symbolId to get redirected."

#264 introduced a two-level symbol redirect where each A.html loads a generated per-assembly A.files.js. The proxy only served .html/.txt, so on a proxied deployment the .js fell through to the static-file provider -- which does not have the index on local disk -- and 404'd, leaving the redirect stub. Confirmed live: .../a.html -> 200 (blob), .../A.files.js -> 404.

Fix: also proxy that file, using the same FileExists fall-through. Scoped to the .files.js suffix -- the only .js the generator emits into the index -- so chrome scripts (scripts.js) keep serving from wwwroot rather than being proxied.


Reference fragments (/{assembly}/R/{id}.html) -> 404

The per-symbol reference fragments are packed into a single references.pack (+ references.index) served by ReferencePackMiddleware, which read them via raw File.* -- local disk only. On the proxied deployment the pack is uploaded to blob rather than shipped with the webapp, so every reference fragment 404'd. Confirmed live: a real source page linking R/36a0ef01cb5d5107.html etc., all 404.

Fix: make ReferencePack blob-aware, mirroring how IndexLoader already falls back to AzureBlobFileSystem. The small references.index is read into memory once; each fragment is then streamed straight to the response -- a ranged blob GET, or pooled chunked reads locally -- via a new IFileSystem.CopyBytesToAsync. Streaming rather than buffering means a heavily-referenced symbol's (multi-MB) fragment doesn't force a large-object-heap allocation per request. The local file-handle path is otherwise unchanged.


Graceful SolutionExplorer.html fallback

The nav frame redirects to /SolutionExplorer.html; the pipeline serves the generated one from the index (blob or local) and only falls through to wwwroot when it's absent. Added a static placeholder there -- matching the generated page's chrome, but with no tree and no onSolutionExplorerLoad() -- so an index without one shows a "use search" note in the nav pane instead of a 404.


Verified SourceIndexServer builds clean and the fallback is included on publish. The blob paths can only be fully exercised against the live proxied deployment (private container), so a post-deploy check is warranted. This is the vendored SourceBrowser copy; the same fixes should also land upstream in tannergooding/SourceBrowser on the next re-vendor.

…es.js

The index proxy threw on Convert.ToBase64String when a blob had no
ContentHash (block-uploaded blobs lack one), returning HTTP 500 for
larger files such as SolutionExplorer.html. Only emit Content-Md5 when
present.

Also serve the generated per-assembly A.files.js from blob so the new
two-level symbol redirect resolves; previously only .html/.txt were
proxied, so it 404'd and navigation fell through to the 'Don't use this
page directly' page. Scope the change to .files.js specifically -- the
only .js the index emits -- so chrome scripts.js keeps serving from
wwwroot.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@tannergooding
tannergooding force-pushed the tannergooding-investigate-azure-file-loading branch from 2ed7654 to fbecca7 Compare July 19, 2026 02:00
tannergooding and others added 2 commits July 18, 2026 19:14
The per-symbol reference fragments (/{assembly}/R/{id}.html) were read
only from the local references.pack, so they 404'd on source.dot.net
where the index -- pack included -- is uploaded to blob rather than
shipped with the webapp.

Make ReferencePack blob-aware: read the small references.index into
memory once, then stream each fragment out of references.pack via a new
IFileSystem.CopyBytesToAsync, mirroring how IndexLoader falls back to
AzureBlobFileSystem. Fragments are streamed straight to the response
(ranged blob GET, or pooled chunked reads locally) rather than buffered,
so a heavily-referenced symbol's multi-MB fragment doesn't force a
large-object-heap allocation per request.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The nav frame redirects to /SolutionExplorer.html; the pipeline serves
the generated one from the index (blob or local) and only falls through
to wwwroot when it's absent. Ship a static placeholder there so that
case shows a 'use search' note in the nav pane instead of a 404.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@tannergooding tannergooding changed the title Fix index proxy 500 on missing Content-MD5 and serve generated .js Fix source.dot.net proxied-index serving (500, .js, references, SolutionExplorer) Jul 19, 2026
@tannergooding
tannergooding enabled auto-merge (squash) July 19, 2026 02:23
@tannergooding
tannergooding merged commit abd63a8 into dotnet:main Jul 19, 2026
2 checks passed
@tannergooding
tannergooding deleted the tannergooding-investigate-azure-file-loading branch July 19, 2026 02:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants