Is this the right way to do this?
Yes.
In more detail:
Currently, the way I'm doing it is to just check if the url starts with 'blob:'
.
Is this the right way to do this? Is there a better way to do it?
We can find out for sure by consulting the specification that defines how URL.revokeObjectURL(url)
should work
(emphasis mine, and references to sub-instructions are inlined)
https://w3c.github.io/FileAPI/#dfn-revokeObjectURL
The revokeObjectURL(url)
static method must run these steps:
- Let
url record
be the result of parsing url
.
- If
url record
’s scheme is not "blob
", return.
- Let
origin
be the origin of url record
.
- Let
settings
be the current settings object.
- If
origin
is not same origin with settings
’s origin, return.
- Remove an entry from the Blob URL Store for
url
:
- Let store be the user agent’s blob URL store;
- Let url string be the result of serializing url.
- Remove store
url string
.
- Remove all entries from the
map
that match a given condition (i.e. equal url
)
- ...or do nothing if none do.
Additionally observe that the specification also notes that:
This means that rather than throwing some kind of error, attempting to revoke a URL that isn’t registered will silently fail. User agents might display a message on the error console if this happens.
Therefore, we can conclude:
- If a URI's Scheme is
blob:
, or if a string
URL starts with blob:
, then it is a Blob URL.
- ...and therefore it may be revoked by a script (on the same origin) calling
URL.revokeObjectURL(url)
.
- If
URL.revokeObjectURL(url)
is used with an invalid URL then nothing bad will happen (such as a thrown Error
or other runtime exception). Examples of invalid URLs include:
- non-
blob:
scheme URLs (due to step 2)
- Different-origin URLs (due to step 5)
- Already-revoked ObjectURLs (Due to step 6.3.2)
- Syntactically valid, same-origin
blob:
URLs containing bogus UUIDs (Also due to step 6.3.2)
Addendum: A Regular-Expression for Matching blob:
Object URLs:
The Web File API specification also prescribes a specific format for blob:
URIs, which means they can be matched by a regular-expression RegExp
too (assuming the specification doesn't change):
- Let
result
be the empty string.
- Append the string "
blob:
" to result
.
- Let
settings
be the current settings object
- Let
origin
be settings’s origin.
- Let
serialized
be the ASCII serialization of origin.
- If
serialized
is "null", set it to an implementation-defined value.
- Append serialized to
result
.
- Append
U+0024
SOLIDUS (/) to result
.
- Generate a UUID RFC4122 as a string and append it to
result
.
- Return
result
- An example of a blob URL that can be generated by this algorithm is
blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f64
.
Therefore the RegExp
in JS would be this (based on this RegExp to match HTTP Origin strings):
const blobObjectUrlRegex = /^blob:(?<origin>[\w\+]+:\/\/(?=.{1,254}(?::|$))(?:(?!\d|-)(?![a-z0-9\-]{1,62}-(?:\.|:|$))[a-z0-9\-]{1,63}\b(?!\.$)\.?)+(:\d+)?)\/(?<uuid>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
function isBlobOrObjectUrl( url ) {
return ( typeof url === 'string' ) && blobObjectUrlRegex.test( url );
}
Demo:
const objectUrlExample = 'blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f64';
const regex = /^blob:(?<origin>[\w\+]+:\/\/(?=.{1,254}(?::|$))(?:(?!\d|-)(?![a-z0-9\-]{1,62}-(?:\.|:|$))[a-z0-9\-]{1,63}\b(?!\.$)\.?)+(:\d+)?)\/(?<uuid>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/;
console.log( "Is \"%s\" an ObjectURL (aka Blob URL)? %o", objectUrlExample, regex.test( objectUrlExample ) ? "Yes" : "No" );
const nonObjectUrlExample = 'https://mcmap.net/q/270603/-proper-way-to-check-if-a-url-is-the-result-of-a-createobjecturl-call';
console.log( "Is \"%s\" an ObjectURL (aka Blob URL)? %o", nonObjectUrlExample, regex.test( nonObjectUrlExample ) ? "Yes" : "No" );
blob:
– Gyre