mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 06:48:12 +00:00
LibWeb: Begin support for requesting blob URLs with Fetch infrastructure
This does not yet implement requests with a Range header.
This commit is contained in:
parent
9957d48f48
commit
a14f6e42a8
2 changed files with 82 additions and 2 deletions
|
@ -31,6 +31,8 @@
|
|||
#include <LibWeb/Fetch/Infrastructure/PortBlocking.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/Task.h>
|
||||
#include <LibWeb/Fetch/Infrastructure/URL.h>
|
||||
#include <LibWeb/FileAPI/Blob.h>
|
||||
#include <LibWeb/FileAPI/BlobURLStore.h>
|
||||
#include <LibWeb/HTML/EventLoop/EventLoop.h>
|
||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
|
@ -718,8 +720,83 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<PendingResponse>> scheme_fetch(JS::Realm& r
|
|||
}
|
||||
// -> "blob"
|
||||
else if (request->current_url().scheme() == "blob"sv) {
|
||||
// FIXME: Support 'blob://' URLs
|
||||
return PendingResponse::create(vm, request, Infrastructure::Response::network_error(vm, "Request has 'blob:' URL which is currently unsupported"sv));
|
||||
auto const& store = FileAPI::blob_url_store();
|
||||
|
||||
// 1. Let blobURLEntry be request’s current URL’s blob URL entry.
|
||||
auto blob_url_entry = store.get(TRY_OR_THROW_OOM(vm, request->current_url().to_string()));
|
||||
|
||||
// 2. If request’s method is not `GET`, blobURLEntry is null, or blobURLEntry’s object is not a Blob object,
|
||||
// then return a network error. [FILEAPI]
|
||||
if (request->method() != "GET"sv.bytes() || !blob_url_entry.has_value()) {
|
||||
// FIXME: Handle "blobURLEntry’s object is not a Blob object". It could be a MediaSource object, but we
|
||||
// have not yet implemented the Media Source Extensions spec.
|
||||
return PendingResponse::create(vm, request, Infrastructure::Response::network_error(vm, "Request has an invalid 'blob:' URL"sv));
|
||||
}
|
||||
|
||||
// 3. Let blob be blobURLEntry’s object.
|
||||
auto const& blob = blob_url_entry->object;
|
||||
|
||||
// 4. Let response be a new response.
|
||||
auto response = Infrastructure::Response::create(vm);
|
||||
|
||||
// 5. Let fullLength be blob’s size.
|
||||
auto full_length = blob->size();
|
||||
|
||||
// 6. Let serializedFullLength be fullLength, serialized and isomorphic encoded.
|
||||
auto serialized_full_length = TRY_OR_THROW_OOM(vm, String::number(full_length));
|
||||
|
||||
// 7. Let type be blob’s type.
|
||||
auto const& type = blob->type();
|
||||
|
||||
// 8. If request’s header list does not contain `Range`:
|
||||
if (!request->header_list()->contains("Range"sv.bytes())) {
|
||||
// 1. Let bodyWithType be the result of safely extracting blob.
|
||||
auto body_with_type = TRY(safely_extract_body(realm, blob));
|
||||
|
||||
// 2. Set response’s status message to `OK`.
|
||||
response->set_status_message(MUST(ByteBuffer::copy("OK"sv.bytes())));
|
||||
|
||||
// 3. Set response’s body to bodyWithType’s body.
|
||||
response->set_body(move(body_with_type.body));
|
||||
|
||||
// 4. Set response’s header list to « (`Content-Length`, serializedFullLength), (`Content-Type`, type) ».
|
||||
auto content_length_header = TRY_OR_THROW_OOM(vm, Infrastructure::Header::from_string_pair("Content-Length"sv, serialized_full_length));
|
||||
TRY_OR_THROW_OOM(vm, response->header_list()->append(move(content_length_header)));
|
||||
|
||||
auto content_type_header = TRY_OR_THROW_OOM(vm, Infrastructure::Header::from_string_pair("Content-Type"sv, type));
|
||||
TRY_OR_THROW_OOM(vm, response->header_list()->append(move(content_type_header)));
|
||||
}
|
||||
// FIXME: 9. Otherwise:
|
||||
else {
|
||||
// 1. Set response’s range-requested flag.
|
||||
// 2. Let rangeHeader be the result of getting `Range` from request’s header list.
|
||||
// 3. Let rangeValue be the result of parsing a single range header value given rangeHeader and true.
|
||||
// 4. If rangeValue is failure, then return a network error.
|
||||
// 5. Let (rangeStart, rangeEnd) be rangeValue.
|
||||
// 6. If rangeStart is null:
|
||||
// 1. Set rangeStart to fullLength − rangeEnd.
|
||||
// 2. Set rangeEnd to rangeStart + rangeEnd − 1.
|
||||
// 7. Otherwise:
|
||||
// 1. If rangeStart is greater than or equal to fullLength, then return a network error.
|
||||
// 2. If rangeEnd is null or rangeEnd is greater than or equal to fullLength, then set rangeEnd to fullLength − 1.
|
||||
// 8. Let slicedBlob be the result of invoking slice blob given blob, rangeStart, rangeEnd + 1, and type.
|
||||
// 9. Let slicedBodyWithType be the result of safely extracting slicedBlob.
|
||||
// 10. Set response’s body to slicedBodyWithType’s body.
|
||||
// 11. Let serializedSlicedLength be slicedBlob’s size, serialized and isomorphic encoded.
|
||||
// 12. Let contentRange be `bytes `.
|
||||
// 13. Append rangeStart, serialized and isomorphic encoded, to contentRange.
|
||||
// 14. Append 0x2D (-) to contentRange.
|
||||
// 15. Append rangeEnd, serialized and isomorphic encoded to contentRange.
|
||||
// 16. Append 0x2F (/) to contentRange.
|
||||
// 17. Append serializedFullLength to contentRange.
|
||||
// 18. Set response’s status to 206.
|
||||
// 19. Set response’s status message to `Partial Content`.
|
||||
// 20. Set response’s header list to « (`Content-Length`, serializedSlicedLength), (`Content-Type`, type), (`Content-Range`, contentRange) ».
|
||||
return PendingResponse::create(vm, request, Infrastructure::Response::network_error(vm, "Request has a 'blob:' URL with a Content-Range header, which is currently unsupported"sv));
|
||||
}
|
||||
|
||||
// 10. Return response.
|
||||
return PendingResponse::create(vm, request, response);
|
||||
}
|
||||
// -> "data"
|
||||
else if (request->current_url().scheme() == "data"sv) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue