-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* Add URL wildcard feature (fixes #47) * Replace confusing/inaccurate test * Add another illustrative test of basic auth behavior * Correctly describe test * collapse unused constant * Rename general purpose boundary chars away from wildcard * Simplify boundary chars * Fix bug with trailing slashes * extra newline * test double-star behavior * moar tests * Note breaking changes in post_install_message * Bump version to 2.0 * Clarify language * enshorten * Update lib/webvalve/version.rb Co-authored-by: Nathan Griffith <nathan@betterment.com> * Better section title * Switch to Addressable::Template strategy * Factor out `#template` for legibility * Fix URL edge case and add tests * Typo in code comments * more succinct * also more succinct * Update README to match Addressable::Template capabilities * Better error message * Better comment * Update spec/webvalve/service_url_converter_spec.rb * Match multiple query params! * Revert "Match multiple query params!" This reverts commit 878fea0. * Revert "Better comment" This reverts commit d1f8cb5. * Revert "Better error message" This reverts commit 6ed0170. * Revert "also more succinct" This reverts commit e20c482. * Revert "more succinct" This reverts commit 96c0aed. * Revert "Typo in code comments" This reverts commit cb35fe3. * Revert "Factor out `#template` for legibility" This reverts commit ad2775c. * Revert "Switch to Addressable::Template strategy" This reverts commit 2deb420. * Don't rely on Addressable for tests when it's not a dependency * 2.0.0 changelog entry --------- Co-authored-by: Nathan Griffith <nathan@betterment.com> Co-authored-by: Sam Moore <sam@betterment.com>
- Loading branch information
1 parent
97e8645
commit d8668c5
Showing
8 changed files
with
297 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
module WebValve | ||
class ServiceUrlConverter | ||
TOKEN_BOUNDARY_CHARS = Regexp.escape('.:/?#@&=').freeze | ||
WILDCARD_SUBSTITUTION = ('[^' + TOKEN_BOUNDARY_CHARS + ']*').freeze | ||
URL_PREFIX_BOUNDARY = ('[' + TOKEN_BOUNDARY_CHARS + ']').freeze | ||
URL_SUFFIX_PATTERN = ('((' + URL_PREFIX_BOUNDARY + '|(?<=' + URL_PREFIX_BOUNDARY + ')).*)?\z').freeze | ||
|
||
attr_reader :url | ||
|
||
def initialize(url:) | ||
@url = url | ||
end | ||
|
||
def regexp | ||
if url.is_a?(String) | ||
regexp_string = Regexp.escape(url) | ||
substituted_regexp_string = regexp_string.gsub('\*', WILDCARD_SUBSTITUTION) | ||
%r(\A#{substituted_regexp_string}#{URL_SUFFIX_PATTERN}) | ||
else | ||
url | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
module WebValve | ||
VERSION = "1.3.1" | ||
VERSION = "2.0.0" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
require 'spec_helper' | ||
|
||
RSpec.describe WebValve::ServiceUrlConverter do | ||
let(:url) { "http://bar.com" } | ||
|
||
subject { described_class.new(url: url) } | ||
|
||
describe '#regexp' do | ||
it "returns a regexp" do | ||
expect(subject.regexp).to be_a(Regexp) | ||
end | ||
|
||
context "with a regexp" do | ||
let(:url) { %r{\Ahttp://foo\.com} } | ||
|
||
it "returns the same object" do | ||
expect(subject.regexp).to be_a(Regexp) | ||
expect(subject.regexp).to equal(url) | ||
end | ||
end | ||
|
||
context "with an empty url" do | ||
let(:url) { "" } | ||
|
||
it "matches empty string" do | ||
expect("").to match(subject.regexp) | ||
end | ||
|
||
it "matches a string starting with a URL delimiter because the rest is just interpreted as suffix" do | ||
expect(":do:do:dodo:do:do").to match(subject.regexp) | ||
end | ||
|
||
it "doesn't match a string that doesn't start with a delimiter" do | ||
expect("jamietart:do:do:dodo:do:do").not_to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a boundary char on the end" do | ||
let(:url) { "http://bar.com/" } | ||
|
||
it "matches arbitrary suffixes" do | ||
expect("http://bar.com/baz/bump/beep").to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with multiple asterisks" do | ||
let(:url) { "http://bar.com/**/bump" } | ||
|
||
it "matches like a single asterisk" do | ||
expect("http://bar.com/foo/bump").to match(subject.regexp) | ||
end | ||
|
||
it "doesn't match like a filesystem glob" do | ||
expect("http://bar.com/foo/bar/bump").not_to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a trailing *" do | ||
let(:url) { "http://bar.com/*" } | ||
|
||
it "matches when empty" do | ||
expect("http://bar.com/").to match(subject.regexp) | ||
end | ||
|
||
it "matches when existing" do | ||
expect("http://bar.com/foobaloo").to match(subject.regexp) | ||
end | ||
|
||
it "matches with additional tokens" do | ||
expect("http://bar.com/foobaloo/wink").to match(subject.regexp) | ||
end | ||
|
||
it "doesn't match when missing the trailing slash tho" do | ||
expect("http://bar.com").not_to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a totally wildcarded protocol" do | ||
let(:url) { "*://bar.com" } | ||
|
||
it "matches http" do | ||
expect("http://bar.com/").to match(subject.regexp) | ||
end | ||
|
||
it "matches anything else" do | ||
expect("gopher://bar.com/").to match(subject.regexp) | ||
end | ||
|
||
it "matches empty" do | ||
expect("://bar.com").to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a wildcarded partial protocol" do | ||
let(:url) { "http*://bar.com" } | ||
|
||
it "matches empty" do | ||
expect("http://bar.com/").to match(subject.regexp) | ||
end | ||
|
||
it "matches full" do | ||
expect("https://bar.com/").to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a TLD that is a substring of another TLD" do | ||
let(:url) { "http://bar.co" } | ||
|
||
it "doesn't match a different TLD when extending" do | ||
expect("http://bar.com").not_to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a wildcard subdomain" do | ||
let(:url) { "http://*.bar.com" } | ||
|
||
it "matches" do | ||
expect("http://foo.bar.com").to match(subject.regexp) | ||
end | ||
|
||
it "doesn't match when too many subdomains" do | ||
expect("http://beep.foo.bar.com").not_to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a partial postfix wildcard subdomain" do | ||
let(:url) { "http://foo*.bar.com" } | ||
|
||
it "matches when present" do | ||
expect("http://foobaz.bar.com").to match(subject.regexp) | ||
end | ||
|
||
it "matches when empty" do | ||
expect("http://foo.bar.com").to match(subject.regexp) | ||
end | ||
|
||
it "doesn't match when out of order" do | ||
expect("http://bazfoo.bar.com").not_to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a partial prefix wildcard subdomain" do | ||
let(:url) { "http://*baz.bar.com" } | ||
|
||
it "matches when present" do | ||
expect("http://foobaz.bar.com").to match(subject.regexp) | ||
end | ||
|
||
it "matches when empty" do | ||
expect("http://baz.bar.com").to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a wildcarded basic auth url" do | ||
let(:url) { "http://*:*@bar.com" } | ||
|
||
it "matches when present" do | ||
expect("http://bilbo:baggins@bar.com").to match(subject.regexp) | ||
end | ||
|
||
it "doesn't match when malformed" do | ||
expect("http://bilbobaggins@bar.com").not_to match(subject.regexp) | ||
end | ||
|
||
it "doesn't match when missing password part" do | ||
expect("http://bilbo@bar.com").not_to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a wildcarded path" do | ||
let(:url) { "http://bar.com/*/whatever" } | ||
|
||
it "matches with arbitrarily spicy but legal, non-URL-significant characters" do | ||
expect("http://bar.com/a0-_~[]!$'(),;%+/whatever").to match(subject.regexp) | ||
end | ||
|
||
it "doesn't match when you throw a URL-significant char in there" do | ||
expect("http://bar.com/life=love/whatever").not_to match(subject.regexp) | ||
end | ||
end | ||
|
||
context "with a wildcarded query param" do | ||
let(:url) { "http://bar.com/whatever?foo=*&bar=bump" } | ||
|
||
it "matches when present" do | ||
expect("http://bar.com/whatever?foo=baz&bar=bump").to match(subject.regexp) | ||
end | ||
|
||
it "doesn't match when you throw a URL-significant char in there" do | ||
expect("http://bar.com/whatever?foo=baz#&bar=bump").not_to match(subject.regexp) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters