Skip to content

Commit

Permalink
Merge pull request #460 from cloudflare/jsnell/url-canparse
Browse files Browse the repository at this point in the history
  • Loading branch information
jasnell authored Mar 21, 2023
2 parents 400db30 + 3116830 commit 662240e
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/workerd/api/url-standard-test.c++
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,15 @@ KJ_TEST("Parse protocol with state override") {
}
}


KJ_TEST("Can parse") {
{
KJ_ASSERT(URL::canParse(jsg::usv("http://example.org")));
KJ_ASSERT(URL::canParse(jsg::usv("foo"), jsg::usv("http://example.org")));
KJ_ASSERT(!URL::canParse(jsg::usv("this is not a parseable URL")));
KJ_ASSERT(!URL::canParse(jsg::usv("foo"), jsg::usv("base is not a URL")));
}
}
} // namespace
} // namespace workerd::api::url

15 changes: 15 additions & 0 deletions src/workerd/api/url-standard.c++
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,21 @@ URL::~URL() noexcept(false) {
}
}

bool URL::canParse(jsg::UsvString url, jsg::Optional<jsg::UsvString> maybeBase) {
KJ_IF_MAYBE(base, maybeBase) {
KJ_IF_MAYBE(parsedBase, URL::parse(*base)) {
KJ_IF_MAYBE(parsed, URL::parse(url, *parsedBase)) {
return true;
}
}
} else {
KJ_IF_MAYBE(parsed, URL::parse(url)) {
return true;
}
}
return false;
}

jsg::UsvString URL::getOrigin() {
KJ_SWITCH_ONEOF(inner.getOrigin()) {
KJ_CASE_ONEOF(opaque, OpaqueOrigin) {
Expand Down
14 changes: 14 additions & 0 deletions src/workerd/api/url-standard.h
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,19 @@ class URL: public jsg::Object {

UrlRecord& getRecord() KJ_LIFETIMEBOUND { return inner; }

static bool canParse(jsg::UsvString url,
jsg::Optional<jsg::UsvString> base = nullptr);
// Standard utility that returns true if the given input can be
// successfully parsed as a URL. This is useful for validating
// URL inputs without incurring the additional cost of constructing
// and throwing an error. For example:
//
// const urls = [
// 'https://example.org/good',
// 'not a url'
// ].filter((test) => URL.canParse(test));
//

JSG_RESOURCE_TYPE(URL) {
JSG_READONLY_PROTOTYPE_PROPERTY(origin, getOrigin);
JSG_PROTOTYPE_PROPERTY(href, getHref, setHref);
Expand All @@ -313,6 +326,7 @@ class URL: public jsg::Object {
JSG_READONLY_PROTOTYPE_PROPERTY(searchParams, getSearchParams);
JSG_METHOD_NAMED(toJSON, getHref);
JSG_METHOD_NAMED(toString, getHref);
JSG_STATIC_METHOD(canParse);

JSG_TS_OVERRIDE(URL {
constructor(url: string | URL, base?: string | URL);
Expand Down

0 comments on commit 662240e

Please # to comment.