Skip to content

fix: percent-encode + in setQueryItems so cursor pagination works#260

Merged
MasterJ93 merged 1 commit into
MasterJ93:mainfrom
mvanhorn:fix/256-fix-percent-encode--in-setqueryitems-so-
Jun 18, 2026
Merged

fix: percent-encode + in setQueryItems so cursor pagination works#260
MasterJ93 merged 1 commit into
MasterJ93:mainfrom
mvanhorn:fix/256-fix-percent-encode--in-setqueryitems-so-

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Description

APIClientService.setQueryItems(for:with:) builds query strings with URLComponents/URLQueryItem, which leave a literal + unescaped in query values. Bluesky's HTTP servers apply application/x-www-form-urlencoded semantics and decode a bare + as a space, so a cursor that contains + (e.g. a base64 segment from a feed generator) gets corrupted when it is sent back. The decoded cursor no longer matches the one the AppView issued, which returns HTTP 502 and breaks cursor-based pagination.

This patch rewrites percentEncodedQuery after the query items are assigned, replacing any literal + with %2B. Existing escaping produced by URLQueryItem is preserved; only the bare + is encoded. The reporter verified with curl that the same cursor returns HTTP 200 when sent as %2B and HTTP 502 when sent as a bare +.

A narrowly scoped unit test is added covering a value with +, a value without +, and a mix of multiple query items. The package's test target was commented out in Package.swift, so it is re-enabled so the test is discovered and run by swift test.

A broader alternative would be to serialize the whole query as form-urlencoded; that is intentionally left out here to keep the change small and reversible, and is noted for your discretion.

Linked Issues

#256

Type of Change

  • Bug Fix
  • New Feature
  • Documentation

Checklist:

  • My code follows the ATProtoKit API Design Guidelines as well as the Swift API Design Guidelines.
  • I have performed a self-review of my own code and commented it, particularly in hard-to-understand areas.
  • I have made corresponding changes to the documentation.
  • My changes generate no new warnings or errors in the compiler or runtime.
  • My code is able to build and run on my machine.

Screenshots (if applicable)

Not applicable.

Additional Notes

swift build and swift test both pass locally (1 test executed, 0 failures). If you would prefer to keep the test target disabled, I am happy to drop the Package.swift change and the test.

Credits

  • GitHub: mvanhorn

Fixes #256

@MasterJ93

Copy link
Copy Markdown
Owner

Thanks for the help! Unfortunately, I can't accept unit tests right now, so please remove it from the PR. Once you do that, I'll accept the PR.

The main reason why I'm not accepting unit tests yet is because most of ATProtoKit is still not fully ready for it. There are some places where they can accept them, sure, but I'd rather not do that until I know exactly how I want things (and I'm still actively working on it). Furthermore, I would prefer to use Swift Testing over XCTest (while there is an XCTest file, it's only because this package is old enough where Swift Testing wasn't exactly the norm yet).

@MasterJ93

Copy link
Copy Markdown
Owner

I'll be holding off on releasing the new version until your PR is merged, because I do want this PR to exist by the next update.

@MasterJ93

Copy link
Copy Markdown
Owner

Okay. I'm going to approve and merge the update, since I do want to get this out before the end of the week. I'll make the changes once that's done.

@MasterJ93 MasterJ93 merged commit fe9b061 into MasterJ93:main Jun 18, 2026
@mvanhorn

Copy link
Copy Markdown
Contributor Author

Thanks for taking this on, @MasterJ93. Percent-encoding the plus in setQueryItems fixes cursor pagination that the URLComponents default broke.

@mvanhorn

Copy link
Copy Markdown
Contributor Author

Appreciate you merging this, @MasterJ93. Percent-encoding the + in setQueryItems is exactly the kind of thing that quietly breaks cursor pagination.

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.

[Bug]: APIClientService.setQueryItems does not percent-encode +, breaking cursor-based pagination

2 participants