Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend fluent API with ability to better match the URI or parts of it #112

Open
skwasjer opened this issue Sep 8, 2024 · 0 comments
Open
Labels
enhancement New feature or request

Comments

@skwasjer
Copy link
Owner

skwasjer commented Sep 8, 2024

Currently, we have two request matchers RequestUri() and QueryString(). The former supports wildcards and can be used to effectively ignore portions of a URI, 'and' match the query string as well. The latter has its own specific implementation and if used in combination with RequestUri() requires that the expectation is postfixed with ?*.

This has caused confusion in the past (#25 and #42). The issue with wildcards is that it is very greedy and can match something you don't want. To illustrate once more, */file.jpg matches both http://localhost/file.jpg and http://localhost/some/path/file.jpg. And the fact that RequestUri() and QueryString() don't know about each other does not make things very intuitive. We can fix some of this in documentation, but not all.

Thus, I want to extend the API with additional overloads and pattern matchers to match specific parts of the URI (eg. Scheme, Host, Port, Authority, Path, Query).

Proposal

// Current API with wildcard. Limited but simple to use.
m.RequestUri("https://*/file.jpg?*").QueryString("w", "1024")
// Or
m.RequestUri("https://*/file.jpg?w=*")

// Similar to the current API, but more explicit. The current API would stop supporting wildcards, so you have to opt-in!
// Wildcards have their issues, so more explicit use would be better. Conceivably, we could also introduce glob to address some issues.
m.RequestUri(Pattern.Wildcard("https://*/file.jpg?w=*"))

// Full control via regex (but a bit more difficult and hard to read, however, you do you! ;)).
m.RequestUri(Pattern.Regex(@"^https://[^/]+/file\.jpg\?w=d+$")

// Full control via expressions
m.RequestUri(uri => uri.Scheme == "https" && uri.AbsolutePath == "/file.jpg" && uri.Query.Contains("w=1024"))

// Fluent builder pattern
m.RequestUri(u => u
    .Scheme("https")
    .Path("/file.jpg")
    .Query("w", "1024")
)

// Pattern negation using !
m.RequestUri(!Pattern.Wildcard("http://*"))

// Having all this, we can also combine patterns, expressions and the builder to make it even more flexible.
m.RequestUri(u => u
    .Scheme("https")
    .Path(Pattern.Regex(@"^/file\.jpg$"))
    .Query("w", v => int.TryParse(v, out var w) && w == 1024)
)

All the examples above would match: https://localhost/file.jpg?w=1024 and https://127.0.0.1/file.jpg?w=1024
But not, eg.: http://some-host/file1.jpg?h=2048

Note:
We can keep most of the existing API, but the existing QueryString() and WithoutQueryString() most likely would be deprecated as they are moved to the new fluent API builder. This would provide a more consistent API and solve the issues in #25 and #42.

Note2:
Parts of this design (specifically the pattern matching) could also be retrofitted into how header matching currently works, thus gaining the ability there also to use regex, expressions, wildcards, etc. in both the header key and header value(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant