Skip to content

Render a URL that is a URL - #31

Merged
mattpodwysocki merged 2 commits into
mainfrom
debug-url-encoding
Sep 17, 2026
Merged

mattpodwysocki merged 2 commits into
mainfrom
debug-url-encoding

Conversation

@mattpodwysocki

Copy link
Copy Markdown
Contributor

Found by running the thing. The Search Box API takes free text now, so this is an ordinary call:

mapbox search forward --q "Dog friendly coffee shops near me" --proximity -77.0336,38.8996

It works. The URL printed beside it did not:

[debug] GET …/forward?access_token=<redacted>&q=Dog friendly coffee shops near me&limit=1&…

$ curl "<that URL>"
HTTP 000          ← curl makes no request at all

A line whose whole purpose is "here's what was sent, go try it" couldn't be tried — and free-text queries are exactly the case that breaks it.

Only the printout was wrong

redacted_url concatenated name=value pairs raw. The request itself was never affected: reqwest encodes what it sends, which is why the call succeeded while the line beside it was unusable.

Two renderings share that function — --debug, and a text-mode --dry-run:

Dry run — nothing was sent.
POST https://api.mapbox.com/styles/v1/me?access_token=<redacted>

A JSON dry run keeps url and query as separate fields, so it never had the problem.

A value could also invent a parameter

This is the half that's worse than ugly. A value containing & split into another name=value pair, so the line claimed the request carried something it didn't, and anyone pasting it sent a different request than the one being debugged. = and + are the same class. That's the second test:

q = "coffee&limit=99&access_token=sk.theirs"
→ parses to exactly one parameter, value intact

Choices worth stating

%20, not form-urlencoding's +. Both decode to a space wherever the query is read as a form, but only %20 means a space everywhere else, and a + in a URL someone is reading is a character they have to stop and think about.

, : / @ stay literal. They're legal in a query and they're what keeps proximity=-77.0336,38.8996 readable instead of -77.0336%2C38.8996.

No new dependency. reqwest::Url was already used in this file, and the encoder is nine lines with the kept set spelled out.

Verified end to end

The printed URL, with a real token substituted for the placeholder:

HTTP 200
features: 2 | maman, petite maman

Same two features the CLI itself printed. Both new tests confirmed to fail with the encoding reverted.

599 tests, fmt and clippy clean.

Found by running the thing rather than reading it. The Search Box API takes
free text now, so this is an ordinary call:

    mapbox search forward --q "Dog friendly coffee shops near me" \
        --proximity -77.0336,38.8996

It works. The URL printed beside it did not:

    [debug] GET …/forward?access_token=<redacted>&q=Dog friendly coffee shops near me&…
    $ curl "<that>"
    HTTP 000

`curl` makes no request at all. A line whose entire purpose is "here is what
was sent, go try it" could not be tried, and free-text queries are the case
that breaks it.

`redacted_url` concatenated `name=value` pairs raw. The request was never
affected — reqwest encodes what it sends, which is why the call succeeded and
the printout beside it lied. Two renderings shared the function: `--debug`
and a text-mode `--dry-run`. A JSON dry run keeps `url` and `query` as
separate fields, so it never had the problem.

**Also: a value could invent a parameter.** One containing `&` split into
another pair, so the line claimed the request carried something it did not,
and anyone pasting it sent a different request than the one being debugged.
`=` and `+` are the same class. That is the second test.

`%20` rather than form-urlencoding's `+`: both decode to a space wherever the
query is read as a form, but only `%20` means a space everywhere else, and a
`+` in a URL someone is reading is a character they have to stop and think
about. `,` `:` `/` and `@` stay literal — they are legal in a query and they
are what make `proximity=-77.0336,38.8996` readable.

No new dependency: `reqwest::Url` was already used in this file, and the
encoder is nine lines with the kept set spelled out.

Verified end to end: the printed URL, with a real token substituted for the
placeholder, returns HTTP 200 and the same two features the CLI printed. Both
new tests confirmed to fail with the encoding reverted.

599 tests, fmt and clippy clean.
@mattpodwysocki
mattpodwysocki requested a review from a team as a code owner September 17, 2026 14:39
Only CHANGELOG.md conflicted. #26's Added entry and its Fixed entry both
belong alongside this branch's Fixed entry, so the section is one Added and
one Fixed holding both. No source change was involved.
@mattpodwysocki
mattpodwysocki merged commit 1b4a073 into main Sep 17, 2026
8 checks passed
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.

2 participants