Skip to content

Conversation

@tnull
Copy link
Contributor

@tnull tnull commented Jan 20, 2026

Fixes #468.

The url crate has a notoriously large dependency tree which is why we want to avoid it as far as possible. However, we found us then re-implementing several aspects of URL parsing in different places. To this end, I recently (mostly vibe-)coded the 0-dependency minurl crate (https://github.com/tnull/minurl) which is meant as a drop-in replacement for the popular url crate.

To this end, we kept the Url API completely compatible, and even added parity tests ensuring both APIs return exactly the same output given the same input.

While I'm generally fine maintaining this as a separate crate, it makes a lot of sense to have this live as part of bitreq and hence have it available everywhere in the ecosystem. Here I propose to upstream the minurl::Url type (and ofc the corresponding test code). This also allows us to replace the ~half-done http_url::HttpUrl type.

@tnull tnull force-pushed the 2026-01-upstream-minurl branch 2 times, most recently from fd71a06 to 0f95668 Compare January 20, 2026 13:07
@tnull tnull requested a review from tcharding as a code owner January 20, 2026 13:13
@tnull tnull force-pushed the 2026-01-upstream-minurl branch from fbe008a to d56d850 Compare January 20, 2026 13:15
@tnull
Copy link
Contributor Author

tnull commented Jan 20, 2026

@tcharding Hmm, to have the url dev-dependency build under the 1.75.0 MSRV is possible, but we need to pin-back idna_adapter back (which is the recommended way of doing it... see https://docs.rs/crate/idna_adapter ). What is the recommended way to do this here, I know that you dislike pinning-back in CI, right?

@tnull tnull force-pushed the 2026-01-upstream-minurl branch from d56d850 to 13bf05d Compare January 20, 2026 13:28
Copy link
Member

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

use proptest::prelude::*;
use url::Url as MaxUrl;

proptest! {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really feels like a better job for a fuzzer, but if we do stick with proptest maybe the simplest solution to the MSRV question is just just do the testing in a separate non-workspace crate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the MSRV question is really orthogonal to whether or not to proptest. I don't want to get into that discussion again - in this case we already have a bunch of proptests (which actually already uncovered a few edge cases during development), so we can just use them.

The MSRV issue is really just about url's MSRV, which we can easily fix by pinning-back idna_adapter (as usual), but it's mostly a question on how this repo wants to handle that.

Copy link
Member

@TheBlueMatt TheBlueMatt Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MSRV issue is really just about url's MSRV, which we can easily fix by pinning-back idna_adapter (as usual), but it's mostly a question on how this repo wants to handle that.

Right, my point was that it seems simpler to move the logic to a separate non-workspace crate in the bitreq repo? That way url and proptest also aren't even dev-deps and we don't have MSRV questions at all cause that test repo can have a stable msrv.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'd really like to get input from @tcharding as the workspace owner on this: Tobin, would you prefer to either pin-back the required dev-dependency or move the test code to a separate sub-crate that doesn't run in the MSRV CI.

@TheBlueMatt
Copy link
Member

Mind adding a test that this fixes #468?

@tnull tnull force-pushed the 2026-01-upstream-minurl branch 2 times, most recently from c35d3ea to f792086 Compare January 21, 2026 12:20
@tnull
Copy link
Contributor Author

tnull commented Jan 21, 2026

Mind adding a test that this fixes #468?

Now added a commit that moves percent encoding into the Url type to make it more robust, and let HAL generate a bunch of test cases for it, in particular also for #468.

@tnull tnull force-pushed the 2026-01-upstream-minurl branch 2 times, most recently from 24e1c26 to eb3e3b1 Compare January 21, 2026 13:25
tnull added 4 commits January 21, 2026 14:37
Move the minurl URL parsing code to `bitreq/src/url.rs` and expose it as
`bitreq::Url` and `bitreq::UrlParseError`.

Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
Migrate the property-based tests from minurl to bitreq:
- `url_properties.rs`: Tests that URL parsing properties hold
- `url_parity.rs`: Tests parity with the `url` crate
- `common/mod.rs`: Shared test utilities and strategies

Also add the required dev-dependencies (`proptest` and `url`).

Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
This commit replaces the internal `HttpUrl` type with the newly-migrated
`Url` type. The change includes:

- Add `pub(crate)` helper methods to `Url`: `is_https()`, `path_and_query()`,
  `append_query_params()`, `preserve_fragment_from()`, `write_base_url_to()`,
  and `write_resource_to()`
- Extract field-parsing logic into `parse_inner` method for use by mutation
  methods, making them simpler and more robust
- Update `ParsedRequest` to use `Url` instead of `HttpUrl`
- Update `ConnectionParams` to use `u16` for port instead of `Port` enum
- Simplify `http_url.rs` to only contain percent encoding functions
- Update `Response::new()` to accept url as `String` instead of `HttpUrl`
- Simplify WASM `build_full_url()` to use `Url::as_str()`

Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
Add `append_query_param` method to `Url` that handles percent encoding
internally, rather than having external code use the encoding functions
directly. This encapsulates the encoding logic within the `Url` type.

This ensures that existing percent-encoded query parameters in URLs
are not double-encoded when new parameters are added, fixing issue rust-bitcoin#468.

Co-Authored-By: HAL 9000
Signed-off-by: Elias Rohrer <dev@tnull.de>
@tnull tnull force-pushed the 2026-01-upstream-minurl branch from eb3e3b1 to 668eb49 Compare January 21, 2026 13:42
@tnull
Copy link
Contributor Author

tnull commented Jan 21, 2026

Now clippy should also be happy.

@tnull tnull moved this to Goal: Merge in Weekly Goals Jan 21, 2026
@tcharding
Copy link
Member

I pulled down minurl and added rust-edition = "1.85.0" to the manifest then built with cargo +1.85.0 test --all-features and it all seems to work.

What if we bump the MSRV of bitreq (and everything else in this repo) to Rust 1.85.0?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bitreq re-encode an already encoded url

3 participants