w3c / FileAPI

File API
https://w3c.github.io/FileAPI/
Other
104 stars 44 forks source link

blob: slice() without valid content type yields unexpected results #177

Closed dlrobertson closed 2 years ago

dlrobertson commented 2 years ago

Based on my reading of blob.slice(), it seems that the resulting blobs content type should be the empty string under the following cases:

1) contentType is not given 2) contentType has a value outside the range of U+0020 to U+007E

After writing a simple wpt test, it seems like no browser does 1 and only one does 2.

Test Safari Chrome Firefox
no contentType :x: :x: :x:
bad contentType :white_check_mark: :x: :x:

Just in case the issue is actually my test cases 😄, I've attached the example I used below:

promise_test(function(test) {
  var blob = new Blob(["this has no content type"]);
  let slice = blob.slice(12, 24, "\0");
  return fetch(URL.createObjectURL(slice)).then(function (resp) {
    assert_equals(resp.status, 200, "HTTP status is 200");
    assert_equals(resp.type, "basic", "response type is basic");
    assert_equals(resp.headers.get("Content-Type"), "");
    assert_equals(resp.headers.get("Content-Length"), "12");
    return resp.text();
  }).then(function(bodyAsText) {
    assert_equals("content type", bodyAsText)
  });
}, "Set content type to the empty string for slice with invalid content type");

promise_test(function(test) {
  var blob = new Blob(["this has a content type"], {"type": "application/xml"});
  let slice = blob.slice(11, 23);
  return fetch(URL.createObjectURL(slice)).then(function (resp) {
    assert_equals(resp.status, 200, "HTTP status is 200");
    assert_equals(resp.type, "basic", "response type is basic");
    assert_equals(resp.headers.get("Content-Type"), "");
    assert_equals(resp.headers.get("Content-Length"), "12");
    return resp.text();
  }).then(function(bodyAsText) {
    assert_equals("content type", bodyAsText)
  });
}, "Set content type to the empty string for slice with no content type ");
inexorabletash commented 2 years ago

But slice.type === '', correct? Isn't the behavior identical for blobs created with an explicit empty/non-valid contentType?

Don't your tests end up being more about what the Fetch API returns for blob URLs when the Blob's type is an empty string?

I haven't stared at Fetch enough, but it does seem inconsistent - to get a header name should only return null if the header list does not contain the header, yet the "blob" fetch algorithm unconditionally appends Content-Type with the blob’s type. It may be that Fetch needs to define an attempt to parse the type, and on failure not append. Consider filing a bug against Fetch?

dlrobertson commented 2 years ago

But slice.type === '', correct? Isn't the behavior identical for blobs created with an explicit empty/non-valid contentType?

Ah! You're right! Didn't think to check this. slice.type is correct, but the header is not.