Skip to content

Commit

Permalink
Respect Content-Type from internal headers instead of caching it in body
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=220535

Reviewed by Youenn Fablet.

Previously, Content-Type is cached as `m_contentType` in
FetchBodyOwner. However, as the spec says, Content-Type should be
derived from the one in Headers. Thus, we'd like to remove the cached
Content-Type and always retrieve it from internal headers instead.

* LayoutTests/http/wpt/fetch/fetch-as-blob-expected.txt: Removed.
* LayoutTests/http/wpt/fetch/fetch-as-blob-worker-expected.txt: Removed.
* LayoutTests/http/wpt/fetch/fetch-as-blob-worker.html: Removed.
* LayoutTests/http/wpt/fetch/fetch-as-blob.html: Removed.
* LayoutTests/http/wpt/fetch/fetch-as-blob.js: Removed.
* LayoutTests/imported/w3c/resources/import-expectations.json:
* LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/cloned-any.js: Added.
(promise_test.async t):
* LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.js:
(forEach.bodyContainerCreator.promise_test.async t):
(forEach.bodyContainerCreator.assert_equals):
(new.Response.new.Blob.string_appeared_here.forEach.bodyContainerCreator.promise_test.async t):
(new.Response.new.Blob.string_appeared_here.forEach.bodyContainerCreator.assert_equals):
(new.Response.new.Blob):
* LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/w3c-import.log:
* LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.serviceworker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.sharedworker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/window/cache-match.https-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/worker/cache-match.https-expected.txt:
* Source/WebCore/Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::blob):
(WebCore::FetchBody::consumeOnceLoadingFinished):
* Source/WebCore/Modules/fetch/FetchBody.h:
* Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp:
(WebCore::resolveWithTypeAndData):
(WebCore::FetchBodyConsumer::resolve):
(WebCore::FetchBodyConsumer::takeAsBlob):
(WebCore::FetchBodyConsumer::clone):
* Source/WebCore/Modules/fetch/FetchBodyConsumer.h:
(WebCore::FetchBodyConsumer::setContentType): Deleted.
* Source/WebCore/Modules/fetch/FetchBodyOwner.cpp:
(WebCore::FetchBodyOwner::blob):
(WebCore::FetchBodyOwner::cloneBody):
(WebCore::FetchBodyOwner::extractBody):
(WebCore::FetchBodyOwner::consumeOnceLoadingFinished):
(WebCore::FetchBodyOwner::formData):
(WebCore::FetchBodyOwner::updateContentType): Deleted.
* Source/WebCore/Modules/fetch/FetchBodyOwner.h:
(WebCore::FetchBodyOwner::contentType const):
* Source/WebCore/Modules/fetch/FetchRequest.cpp:
(WebCore::m_signal):
(WebCore::FetchRequest::initializeWith):
* Source/WebCore/Modules/fetch/FetchResponse.cpp:
(WebCore::FetchResponse::create):
(WebCore::FetchResponse::clone):
(WebCore::FetchResponse::setReceivedInternalResponse):

Canonical link: https://commits.webkit.org/264054@main
  • Loading branch information
CYBAI authored and Ahmad Saleem committed May 14, 2023
1 parent 6bf2a1e commit cd292c4
Show file tree
Hide file tree
Showing 26 changed files with 216 additions and 205 deletions.
9 changes: 0 additions & 9 deletions LayoutTests/http/wpt/fetch/fetch-as-blob-expected.txt

This file was deleted.

9 changes: 0 additions & 9 deletions LayoutTests/http/wpt/fetch/fetch-as-blob-worker-expected.txt

This file was deleted.

17 changes: 0 additions & 17 deletions LayoutTests/http/wpt/fetch/fetch-as-blob-worker.html

This file was deleted.

14 changes: 0 additions & 14 deletions LayoutTests/http/wpt/fetch/fetch-as-blob.html

This file was deleted.

87 changes: 0 additions & 87 deletions LayoutTests/http/wpt/fetch/fetch-as-blob.js

This file was deleted.

Expand Up @@ -236,6 +236,7 @@
"web-platform-tests/feature-policy/resources/": "import",
"web-platform-tests/fetch": "import",
"web-platform-tests/fetch/api": "import",
"web-platform-tests/fetch/api/body": "import",
"web-platform-tests/fetch/api/cors": "import",
"web-platform-tests/fetch/api/redirect": "import",
"web-platform-tests/fetch/api/resources": "import",
Expand Down
@@ -0,0 +1,50 @@
// Changing the body after it have been passed to Response/Request
// should not change the outcome of the consumed body

const url = 'http://a';
const method = 'post';

promise_test(async t => {
const body = new FormData();
body.set('a', '1');
const res = new Response(body);
const req = new Request(url, { method, body });
body.set('a', '2');
assert_true((await res.formData()).get('a') === '1');
assert_true((await req.formData()).get('a') === '1');
}, 'FormData is cloned');

promise_test(async t => {
const body = new URLSearchParams({a: '1'});
const res = new Response(body);
const req = new Request(url, { method, body });
body.set('a', '2');
assert_true((await res.formData()).get('a') === '1');
assert_true((await req.formData()).get('a') === '1');
}, 'URLSearchParams is cloned');

promise_test(async t => {
const body = new Uint8Array([97]); // a
const res = new Response(body);
const req = new Request(url, { method, body });
body[0] = 98; // b
assert_true(await res.text() === 'a');
assert_true(await req.text() === 'a');
}, 'TypedArray is cloned');

promise_test(async t => {
const body = new Uint8Array([97]); // a
const res = new Response(body.buffer);
const req = new Request(url, { method, body: body.buffer });
body[0] = 98; // b
assert_true(await res.text() === 'a');
assert_true(await req.text() === 'a');
}, 'ArrayBuffer is cloned');

promise_test(async t => {
const body = new Blob(['a']);
const res = new Response(body);
const req = new Request(url, { method, body });
assert_true(await res.blob() !== body);
assert_true(await req.blob() !== body);
}, 'Blob is cloned');
@@ -1,8 +1,22 @@

FAIL Request: overriding explicit Content-Type assert_equals: expected "test/test" but got "text/plain"
FAIL Response: overriding explicit Content-Type assert_equals: expected "test/test" but got "text/plain"
FAIL Request: removing implicit Content-Type assert_equals: expected "" but got "application/x-www-form-urlencoded;charset=utf-8"
FAIL Response: removing implicit Content-Type assert_equals: expected "" but got "application/x-www-form-urlencoded;charset=utf-8"
FAIL Request: setting missing Content-Type assert_equals: expected "test/test" but got ""
FAIL Response: setting missing Content-Type assert_equals: expected "test/test" but got ""
PASS Request: overriding explicit Content-Type
PASS Response: overriding explicit Content-Type
PASS Request: removing implicit Content-Type
PASS Response: removing implicit Content-Type
PASS Request: setting missing Content-Type
PASS Response: setting missing Content-Type
PASS Request: MIME type for Blob from empty body
PASS Response: MIME type for Blob from empty body
PASS Request: MIME type for Blob from empty body with Content-Type
PASS Response: MIME type for Blob from empty body with Content-Type
PASS Request: MIME type for Blob
PASS Response: MIME type for Blob
PASS Request: MIME type for Blob with non-empty type
PASS Response: MIME type for Blob with non-empty type
PASS Request: Extract a MIME type with clone
FAIL Response: Extract a MIME type with clone assert_equals: expected "text/html" but got "text/plain"
PASS Request: Content-Type in headers wins Blob"s type
PASS Response: Content-Type in headers wins Blob"s type
PASS Request: setting missing Content-Type in headers and it wins Blob"s type
PASS Response: setting missing Content-Type in headers and it wins Blob"s type

Expand Up @@ -38,3 +38,90 @@
assert_equals(blob.type, newMIMEType);
}, `${bodyContainer.constructor.name}: setting missing Content-Type`);
});

[
() => new Request("about:blank", { method: "POST" }),
() => new Response(),
].forEach(bodyContainerCreator => {
const bodyContainer = bodyContainerCreator();
promise_test(async t => {
const blob = await bodyContainer.blob();
assert_equals(blob.type, "");
}, `${bodyContainer.constructor.name}: MIME type for Blob from empty body`);
});

[
() => new Request("about:blank", { method: "POST", headers: [["Content-Type", "Mytext/Plain"]] }),
() => new Response("", { headers: [["Content-Type", "Mytext/Plain"]] })
].forEach(bodyContainerCreator => {
const bodyContainer = bodyContainerCreator();
promise_test(async t => {
const blob = await bodyContainer.blob();
assert_equals(blob.type, 'mytext/plain');
}, `${bodyContainer.constructor.name}: MIME type for Blob from empty body with Content-Type`);
});

[
() => new Request("about:blank", { body: new Blob([""]), method: "POST" }),
() => new Response(new Blob([""]))
].forEach(bodyContainerCreator => {
const bodyContainer = bodyContainerCreator();
promise_test(async t => {
const blob = await bodyContainer.blob();
assert_equals(blob.type, "");
assert_equals(bodyContainer.headers.get("Content-Type"), null);
}, `${bodyContainer.constructor.name}: MIME type for Blob`);
});

[
() => new Request("about:blank", { body: new Blob([""], { type: "Text/Plain" }), method: "POST" }),
() => new Response(new Blob([""], { type: "Text/Plain" }))
].forEach(bodyContainerCreator => {
const bodyContainer = bodyContainerCreator();
promise_test(async t => {
const blob = await bodyContainer.blob();
assert_equals(blob.type, "text/plain");
assert_equals(bodyContainer.headers.get("Content-Type"), "text/plain");
}, `${bodyContainer.constructor.name}: MIME type for Blob with non-empty type`);
});

[
() => new Request("about:blank", { method: "POST", body: new Blob([""], { type: "Text/Plain" }), headers: [["Content-Type", "Text/Html"]] }),
() => new Response(new Blob([""], { type: "Text/Plain" }, { headers: [["Content-Type", "Text/Html"]] }))
].forEach(bodyContainerCreator => {
const bodyContainer = bodyContainerCreator();
const cloned = bodyContainer.clone();
promise_test(async t => {
const blobs = [await bodyContainer.blob(), await cloned.blob()];
assert_equals(blobs[0].type, "text/html");
assert_equals(blobs[1].type, "text/html");
assert_equals(bodyContainer.headers.get("Content-Type"), "Text/Html");
assert_equals(cloned.headers.get("Content-Type"), "Text/Html");
}, `${bodyContainer.constructor.name}: Extract a MIME type with clone`);
});

[
() => new Request("about:blank", { body: new Blob([], { type: "text/plain" }), method: "POST", headers: [["Content-Type", "text/html"]] }),
() => new Response(new Blob([], { type: "text/plain" }), { headers: [["Content-Type", "text/html"]] }),
].forEach(bodyContainerCreator => {
const bodyContainer = bodyContainerCreator();
promise_test(async t => {
assert_equals(bodyContainer.headers.get("Content-Type"), "text/html");
const blob = await bodyContainer.blob();
assert_equals(blob.type, "text/html");
}, `${bodyContainer.constructor.name}: Content-Type in headers wins Blob"s type`);
});

[
() => new Request("about:blank", { body: new Blob([], { type: "text/plain" }), method: "POST" }),
() => new Response(new Blob([], { type: "text/plain" })),
].forEach(bodyContainerCreator => {
const bodyContainer = bodyContainerCreator();
promise_test(async t => {
assert_equals(bodyContainer.headers.get("Content-Type"), "text/plain");
const newMIMEType = "text/html";
bodyContainer.headers.set("Content-Type", newMIMEType);
const blob = await bodyContainer.blob();
assert_equals(blob.type, newMIMEType);
}, `${bodyContainer.constructor.name}: setting missing Content-Type in headers and it wins Blob"s type`);
});
@@ -1,8 +1,22 @@

FAIL Request: overriding explicit Content-Type assert_equals: expected "test/test" but got "text/plain"
FAIL Response: overriding explicit Content-Type assert_equals: expected "test/test" but got "text/plain"
FAIL Request: removing implicit Content-Type assert_equals: expected "" but got "application/x-www-form-urlencoded;charset=utf-8"
FAIL Response: removing implicit Content-Type assert_equals: expected "" but got "application/x-www-form-urlencoded;charset=utf-8"
FAIL Request: setting missing Content-Type assert_equals: expected "test/test" but got ""
FAIL Response: setting missing Content-Type assert_equals: expected "test/test" but got ""
PASS Request: overriding explicit Content-Type
PASS Response: overriding explicit Content-Type
PASS Request: removing implicit Content-Type
PASS Response: removing implicit Content-Type
PASS Request: setting missing Content-Type
PASS Response: setting missing Content-Type
PASS Request: MIME type for Blob from empty body
PASS Response: MIME type for Blob from empty body
PASS Request: MIME type for Blob from empty body with Content-Type
PASS Response: MIME type for Blob from empty body with Content-Type
PASS Request: MIME type for Blob
PASS Response: MIME type for Blob
PASS Request: MIME type for Blob with non-empty type
PASS Response: MIME type for Blob with non-empty type
PASS Request: Extract a MIME type with clone
FAIL Response: Extract a MIME type with clone assert_equals: expected "text/html" but got "text/plain"
PASS Request: Content-Type in headers wins Blob"s type
PASS Response: Content-Type in headers wins Blob"s type
PASS Request: setting missing Content-Type in headers and it wins Blob"s type
PASS Response: setting missing Content-Type in headers and it wins Blob"s type

Expand Up @@ -14,5 +14,6 @@ Property values requiring vendor prefixes:
None
------------------------------------------------------------------------
List of files:
/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/cloned-any.js
/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/formdata.any.js
/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.js
Expand Up @@ -22,6 +22,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.

Expand Up @@ -22,6 +22,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.

Expand Up @@ -22,6 +22,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.

Expand Up @@ -22,6 +22,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.

Expand Up @@ -23,6 +23,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.

0 comments on commit cd292c4

Please sign in to comment.