Skip to content

refactor(integration)!: move echo integration into its own package - #135

Open
alecsammon wants to merge 4 commits into
ggicci:mainfrom
alecsammon:split_echo_integration
Open

alecsammon wants to merge 4 commits into
ggicci:mainfrom
alecsammon:split_echo_integration

Conversation

@alecsammon

@alecsammon alecsammon commented Sep 1, 2026 •

Copy link
Copy Markdown
Contributor

THIS IS A BREAKING CHANGE - I am still thinking if the there is a better way through. Will bring it out of draft when I'm happy!

This PR was generated with AI.

I have left the original description below, but thought good to explain in my own terms (and prove I know what this is doing!)

When you import integration.UseGochiURLParam then it drags in github.com/labstack/echo/v4
This has a large number of indirect dependencies, and an open CVE.
This dependency is only used for a test.

By moving the test into a sub-package - then it drops out of the dependencies when you import the package. This means the labstack/echo is no longer included.

--

Why

integration is a single package, and Go's unit of dependency is the package. So importing it for the chi, gorilla or net/http integration also pulls in Echo.

That asymmetry isn't deliberate — it falls out of one design difference:

Integration Signature Third-party imports
UseGochiURLParam takes chi.URLParam as a func value none
UseGorillaMux takes mux.Vars as a func value none
UseHttpPathVariable none needed none
UseEchoRouter takes a concrete *echo.Echo labstack/echo/v4

echo.go is the only non-test file in the package that imports a router. Everyone else pays for it.

What it costs today

A consumer that imports integration purely for UseGochiURLParam:

import (
    "github.com/ggicci/httpin/integration"
    "github.com/go-chi/chi/v5"
)

func main() { integration.UseGochiURLParam("path", chi.URLParam) }

Before — go mod tidy records 11 indirect dependencies:

github.com/ggicci/owl              // indirect
github.com/labstack/echo/v4        // indirect
github.com/labstack/gommon         // indirect
github.com/mattn/go-colorable      // indirect
github.com/mattn/go-isatty         // indirect
github.com/valyala/bytebufferpool  // indirect
github.com/valyala/fasttemplate    // indirect
golang.org/x/crypto                // indirect
golang.org/x/net                   // indirect
golang.org/x/sys                   // indirect
golang.org/x/text                  // indirect

After — one:

github.com/ggicci/owl // indirect

None of it was ever linked into the binary — the linker drops it — but it is recorded in every consumer's go.mod, which is what Dependabot reads for Go modules. Consumers' go.sum sheds it too (16 lines, down from 36). So each Echo CVE raises a bump on codebases that have never constructed an echo.Echo. GHSA-vfp3-v2gw-7wfq, for instance, is in the static file handler and is unreachable for anyone not serving files with Echo.

What this changes

echo.go and echo_test.go move to integration/echo. Nothing else moves: the other three integrations carry no dependencies, so they belong exactly where they are. Git renders both files as renames — the edits are the package clause, an import alias, the import path in the doc comment, and a four-line test fixture that was previously shared with gorilla_test.go.

go.mod for this module is unchanged — Echo is still a direct requirement, because integration/echo genuinely uses it. The difference is that downstream module graphs only include it when they import that package.

Migration

One import line:

-import httpin_integration "github.com/ggicci/httpin/integration"
+import httpin_echo "github.com/ggicci/httpin/integration/echo"

 func init() {
     e := echo.New()
-    httpin_integration.UseEchoRouter("path", e)
+    httpin_echo.UseEchoRouter("path", e)
 }

I kept the name UseEchoRouter rather than shortening it to Use, to keep the diff and the docs churn minimal — happy to rename if you'd prefer httpin_echo.Use.

The docs at ggicci.github.io/httpin/integrations/echo will need the same one-line update; let me know if that lives somewhere I can send a patch.

Verification

go build ./..., go vet ./... and go test -race -failfast ./... all pass locally, and this branch is green on CI — integration/echo reports 100% coverage. go.mod and go.sum are untouched; the diff is two files, both renames.

The before/after dependency counts above were measured with a scratch consumer module against this branch and against main: 11 indirect requirements and a 36-line go.sum on main, 1 and 16 on this branch.

Raised as a draft — it is a breaking change to a public import path, so I'd rather check you want it at all before polishing. Happy to close it if this is a trade you'd rather not make.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Sep 1, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.12%. Comparing base (0e74f54) to head (3ce8f30).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #135   +/-   ##
=======================================
  Coverage   91.12%   91.12%           
=======================================
  Files          36       36           
  Lines        1307     1307           
=======================================
  Hits         1191     1191           
  Misses         72       72           
  Partials       44       44           
Flag Coverage Δ
unittests 91.12% <100.00%> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@alecsammon
alecsammon force-pushed the split_echo_integration branch from 04e56e8 to b1ee2cc Compare September 1, 2026 12:42
The echo integration is the only one that takes a concrete router type
(*echo.Echo). gochi, gorilla and http all accept function values, so they
carry no third-party dependencies at all.

Because Go's unit of dependency is the package, importing `integration`
for chi or gorilla pulls echo — and gommon, fasttemplate, bytebufferpool,
colorable and isatty — into every consumer's module graph.

Moving it to `integration/echo` leaves the dependency-free integrations
where they are and confines echo to the users who actually want it.

BREAKING CHANGE: echo users must import
github.com/ggicci/httpin/integration/echo instead of
github.com/ggicci/httpin/integration.
@alecsammon
alecsammon force-pushed the split_echo_integration branch from b1ee2cc to a107663 Compare September 1, 2026 12:48
@ggicci

ggicci commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Taking a look.

@ggicci
ggicci marked this pull request as ready for review September 11, 2026 05:04
@ggicci

ggicci commented Sep 14, 2026 •

Copy link
Copy Markdown
Owner

Testing

With this change, we still have echo in the root module of httpin package, see:

httpin on  split_echo_integration -33 [!] via 🐹 v1.26.5 on ☁️
❯ rg 'echo' go.mod
10:	github.com/labstack/echo/v4 v4.15.4

httpin on  split_echo_integration -33 [!] via 🐹 v1.26.5 on ☁️
❯ go mod why -m github.com/labstack/echo/v4
# github.com/labstack/echo/v4
github.com/ggicci/httpin/integration/echo
github.com/labstack/echo/v4

Create a customer package with a main.go file containing code:

package main

import (
	"github.com/ggicci/httpin/integration"
	"github.com/go-chi/chi/v5"
)

func main() {
	integration.UseGochiURLParam("path", chi.URLParam)
}

We expect echo doesn't exist in its mod file, but:

/tmp/httpin-test via 🐹 v1.26.5 on ☁️ 
❯ go mod graph | rg echo
github.com/ggicci/httpin@v0.0.0-00010101000000-000000000000 github.com/labstack/echo/v4@v4.15.4

This means this change didn't resolve the problem it intended to.

@ggicci

ggicci commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Updating code to create a nested module for echo.

@ggicci

ggicci commented Sep 14, 2026

Copy link
Copy Markdown
Owner

TODO: release and update docs

Comment thread integration/echo/go.mod
@@ -0,0 +1,23 @@
module github.com/ggicci/httpin/integration/echo

go 1.26.5

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

your base package is still go 1.25.0

Does it make sense to keep this to the same version?

@alecsammon

Copy link
Copy Markdown
Contributor Author

Thank you for picking this up! Sorry - had opened a draft PR to explore - wasn't expecting you to fix all the problems!

This branch has not been deployed

No deployments
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