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://stackoverflow.com/questions/45941639/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" );