Support Content-Length and Last-Modified for webview local resources (#125994)
Closes #125992
This commit is contained in:
parent
3c1fa1b286
commit
28f0fc47d0
3 changed files with 17 additions and 7 deletions
|
@ -543,6 +543,7 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
|
|||
mime: result.mimeType,
|
||||
data: buffer,
|
||||
etag: result.etag,
|
||||
mtime: result.mtime
|
||||
});
|
||||
}
|
||||
case WebviewResourceResponse.Type.NotModified:
|
||||
|
@ -552,6 +553,7 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
|
|||
status: 304, // not modified
|
||||
path: uri.path,
|
||||
mime: result.mimeType,
|
||||
mtime: result.mtime
|
||||
});
|
||||
}
|
||||
case WebviewResourceResponse.Type.AccessDenied:
|
||||
|
|
|
@ -100,7 +100,9 @@ class RequestStore {
|
|||
|
||||
/**
|
||||
* Map of requested paths to responses.
|
||||
* @typedef {{ type: 'response', body: any, mime: string, etag: string | undefined, } | { type: 'not-modified', mime: string } | undefined} ResourceResponse
|
||||
* @typedef {{ type: 'response', body: Uint8Array, mime: string, etag: string | undefined, mtime: number | undefined } |
|
||||
* { type: 'not-modified', mime: string, mtime: number | undefined } |
|
||||
* undefined} ResourceResponse
|
||||
* @type {RequestStore<ResourceResponse>}
|
||||
*/
|
||||
const resourceRequestStore = new RequestStore();
|
||||
|
@ -142,12 +144,12 @@ sw.addEventListener('message', async (event) => {
|
|||
switch (data.status) {
|
||||
case 200:
|
||||
{
|
||||
response = { type: 'response', body: data.data, mime: data.mime, etag: data.etag };
|
||||
response = { type: 'response', body: data.data, mime: data.mime, etag: data.etag, mtime: data.mtime };
|
||||
break;
|
||||
}
|
||||
case 304:
|
||||
{
|
||||
response = { type: 'not-modified', mime: data.mime };
|
||||
response = { type: 'not-modified', mime: data.mime, mtime: data.mtime };
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -233,15 +235,19 @@ async function processResourceRequest(event, requestUrl) {
|
|||
}
|
||||
}
|
||||
|
||||
/** @type {Record<String, string>} */
|
||||
/** @type {Record<string, string>} */
|
||||
const headers = {
|
||||
'Content-Type': entry.mime,
|
||||
'Content-Length': entry.body.byteLength.toString(),
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
};
|
||||
if (entry.etag) {
|
||||
headers['ETag'] = entry.etag;
|
||||
headers['Cache-Control'] = 'no-cache';
|
||||
}
|
||||
if (entry.mtime) {
|
||||
headers['Last-Modified'] = new Date(entry.mtime).toUTCString();
|
||||
}
|
||||
const response = new Response(entry.body, {
|
||||
status: 200,
|
||||
headers
|
||||
|
|
|
@ -22,6 +22,7 @@ export namespace WebviewResourceResponse {
|
|||
constructor(
|
||||
public readonly stream: VSBufferReadableStream,
|
||||
public readonly etag: string | undefined,
|
||||
public readonly mtime: number | undefined,
|
||||
public readonly mimeType: string,
|
||||
) { }
|
||||
}
|
||||
|
@ -34,6 +35,7 @@ export namespace WebviewResourceResponse {
|
|||
|
||||
constructor(
|
||||
public readonly mimeType: string,
|
||||
public readonly mtime: number | undefined,
|
||||
) { }
|
||||
}
|
||||
|
||||
|
@ -50,7 +52,7 @@ export async function loadLocalResource(
|
|||
logService: ILogService,
|
||||
token: CancellationToken,
|
||||
): Promise<WebviewResourceResponse.StreamResponse> {
|
||||
logService.debug(`loadLocalResource - being. requestUri=${requestUri}`);
|
||||
logService.debug(`loadLocalResource - begin. requestUri=${requestUri}`);
|
||||
|
||||
const resourceToLoad = getResourceToLoad(requestUri, options.roots);
|
||||
|
||||
|
@ -64,14 +66,14 @@ export async function loadLocalResource(
|
|||
|
||||
try {
|
||||
const result = await fileService.readFileStream(resourceToLoad, { etag: options.ifNoneMatch });
|
||||
return new WebviewResourceResponse.StreamSuccess(result.value, result.etag, mime);
|
||||
return new WebviewResourceResponse.StreamSuccess(result.value, result.etag, result.mtime, mime);
|
||||
} catch (err) {
|
||||
if (err instanceof FileOperationError) {
|
||||
const result = err.fileOperationResult;
|
||||
|
||||
// NotModified status is expected and can be handled gracefully
|
||||
if (result === FileOperationResult.FILE_NOT_MODIFIED_SINCE) {
|
||||
return new WebviewResourceResponse.NotModified(mime);
|
||||
return new WebviewResourceResponse.NotModified(mime, err.options?.mtime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue