Skip to content

feat(redirects): add --follow-redirects / --no-follow-redirects / --max-redirects (#13)#17

Merged
kavix merged 2 commits into
kavix:mainfrom
AzarAI-TOP:feat/redirect-control
Jun 13, 2026
Merged

feat(redirects): add --follow-redirects / --no-follow-redirects / --max-redirects (#13)#17
kavix merged 2 commits into
kavix:mainfrom
AzarAI-TOP:feat/redirect-control

Conversation

@AzarAI-TOP

Copy link
Copy Markdown
Contributor

Description

Fixes #13.

kurl always followed redirects with a hardcoded cap of 10 and no way to opt out, so inspecting a 301/302 response directly (common when debugging auth flows or URL shorteners) wasn't possible. This adds explicit control, mirroring curl's -L / --max-redirs:

Flag Behaviour
--follow-redirects follow 3xx (default — unchanged)
--no-follow-redirects return the redirect response itself, unfollowed
--max-redirects N cap the number of redirects followed (default 10)

Implementation

  • client.Options gains FollowRedirects and MaxRedirects. When not following, the first 3xx response is returned as-is so the caller can inspect status + Location. When following, the existing manual redirect loop now respects MaxRedirects instead of the hardcoded 10, and reports a clear stopped after N redirects (raise with --max-redirects, or use --no-follow-redirects) error.
  • Flags parsed in main.go (both --flag value and --flag=value forms), seeded via a shared baseOptions() helper so the CLI, save, and run paths agree on defaults.
  • Saved requests persist the settings; FollowRedirects is stored as a *bool so older saved files without the field still default to follow (not the bool zero value).
  • The redirect chain is already shown in verbose output via Result.Redirects, which is still populated when following.
  • Help text updated.

Maps to the issue's acceptance criteria:

  • --follow-redirects flag (default true, backward compatible)
  • --no-follow-redirects flag
  • --max-redirects flag with a sensible default (10)
  • Redirect chain shown in verbose output when following (existing Result.Redirects)
  • Test coverage added

Type of change

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update (help text updated in-tree)

How Has This Been Tested?

  • Added unit tests — CLI flag parsing (main_test.go: defaults, both spellings, invalid values) and client behaviour (client/redirect_test.go: follows + records hops, no-follow returns the 3xx, max-redirects exceeded errors).
  • Tested via go test ./... locally — all packages pass.
  • Compiled and tested via local binary:
    • kurl --no-follow-redirects http://github.com → shows 301 Moved Permanently instead of following
    • kurl --max-redirects abc …invalid max-redirects "abc": want a non-negative integer

Checklist

  • My code follows the style guidelines of this project (gofmt, go vet clean)
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (help text)
  • My changes generate no new warnings
  • I have added tests that prove my feature works
  • New and existing unit tests pass locally with my changes

…ax-redirects

kurl always followed redirects with a hardcoded cap of 10 and no way to
opt out, so inspecting a 301/302 response (common when debugging auth flows
or shorteners) was impossible. Add explicit control, mirroring curl's
-L / --max-redirs:

  --follow-redirects       follow 3xx (default, unchanged behaviour)
  --no-follow-redirects    return the redirect response itself, unfollowed
  --max-redirects N        cap the number of redirects followed (default 10)

Implementation:
- client.Options gains FollowRedirects and MaxRedirects. When not following,
  the first 3xx response is returned as-is; when following, the manual
  redirect loop now respects MaxRedirects instead of the hardcoded 10 and
  reports a clear "stopped after N redirects" error.
- Flags parsed in main.go (both "--flag value" and "--flag=value" forms),
  seeded via a shared baseOptions() helper so CLI, save and run agree on
  defaults. Saved requests persist the settings; FollowRedirects is stored
  as a pointer so older saved files without the field still default to true.
- The redirect chain is already shown in verbose output via Result.Redirects,
  which is still populated when following.
- Help text updated.

Tests: CLI flag parsing (defaults, both spellings, invalid values) and
client behaviour (follows + records hops, no-follow returns the 3xx,
max-redirects exceeded errors). All packages pass via `go test ./...`.

Closes #13

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kavix kavix self-requested a review June 13, 2026 20:41
@kavix

kavix commented Jun 13, 2026

Copy link
Copy Markdown
Owner

@copilot resolve the merge conflicts in this pull request

@kavix kavix merged commit 5c249cf into kavix:main Jun 13, 2026
1 check failed
@AzarAI-TOP AzarAI-TOP deleted the feat/redirect-control branch June 15, 2026 05:35
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.

Add --follow-redirects / --no-follow-redirects flag

2 participants