Skip to content

Releases: go-chi/chi

v5.3.2

Choose a tag to compare

@VojtechVitek VojtechVitek released this 20 Aug 10:04
3893906

What's Changed

  • feat(middleware): add text/markdown, text/csv, text/vtt to default compressible types by @VojtechVitek in #1151
  • docs: deployment recipe for middleware.ClientIPFromXFFTrustedProxies() by @VojtechVitek in #1111
  • fix: don't drop handlers that collide with a Mount()/Route() pattern by @VojtechVitek in #1148
  • Don't duplicate methods in Allow: header for 405 responses by @flimzy in #1029
  • fix(middleware): reject catch-all compress wildcards by @VojtechVitek in #1156
    • middleware.NewCompressor(level, "/*") never worked and silently compressed nothing. Instead of turning it into a compress-everything catch-all (as proposed in #868 and #1121), we decided to reject both "/" and "/*" at construction and panic. Compressing every response wastes CPU on already-compressed types (zip, jpeg, png), which is why the middleware keeps a curated default list. Users should pass explicit content types.

Full Changelog: v5.3.1...v5.3.2

v5.3.1

Choose a tag to compare

@VojtechVitek VojtechVitek released this 06 Jul 14:32
8b258c7

What's Changed

New Contributors

Full Changelog: v5.3.0...v5.3.1

v5.3.0

Choose a tag to compare

@VojtechVitek VojtechVitek released this 22 May 15:46
3b17157

What's Changed

New Contributors

SECURITY: middleware.ClientIP, a replacement for middleware.RealIP

@VojtechVitek submitted PR #967, which introduces middleware.ClientIP — a replacement for middleware.RealIP that closes the three open spoofing advisories:

It also addresses issues outlined at:

middleware.RealIP is deprecated in this PR with pointers to the new API.

The deprecation only adds a // Deprecated: doc comment; the function keeps working for backward compatibility.

Why a new middleware (not "fix RealIP in place")

RealIP has two unfixable design choices: it mutates r.RemoteAddr, and it tries to be a one-size-fits-all default by walking a hard-coded list of headers any client can supply. Per adam-p's "The perils of the 'real' client IP" (which calls chi out by name on this), there is no safe default — the user must pick their trust source explicitly.

The new API

Four middlewares, two accessors. Pick exactly one middleware based on your
infrastructure, read the result with one of the two accessors:

// One of the four. There is no safe default — pick exactly one.
func ClientIPFromHeader(trustedHeader string) func(http.Handler) http.Handler
func ClientIPFromXFF(trustedIPPrefixes ...string) func(http.Handler) http.Handler
func ClientIPFromXFFTrustedProxies(numTrustedProxies int) func(http.Handler) http.Handler
func ClientIPFromRemoteAddr(h http.Handler) http.Handler

// Read the result.
func GetClientIP(ctx context.Context) string         // for logs, rate-limit keys
func GetClientIPAddr(ctx context.Context) netip.Addr // for typed work

Example usage:

// Pick a single ClientIP middleware based on your deployment
  
// Cloudflare.
r.Use(middleware.ClientIPFromHeader("CF-Connecting-IP"))

// Nginx with ngx_http_realip_module.
r.Use(middleware.ClientIPFromHeader("X-Real-IP"))

// Apache with mod_remoteip.
r.Use(middleware.ClientIPFromHeader("X-Client-IP"))

// AWS CloudFront, or any proxy fleet with known CIDRs.
r.Use(middleware.ClientIPFromXFF(
    "13.32.0.0/15",   // CloudFront IPv4
    "52.46.0.0/18",   // CloudFront IPv4
    "2600:9000::/28", // CloudFront IPv6
))

// Behind exactly 2 trusted proxies with dynamic IPs (autoscaling pools,
// ephemeral containers, dynamic CDN edges).
r.Use(middleware.ClientIPFromXFFTrustedProxies(2))

// Server directly on the public internet, no proxy in front.
r.Use(middleware.ClientIPFromRemoteAddr)

And in your handler or downstream middleware:

clientIP := middleware.GetClientIP(r.Context())
// log it, use it as a rate-limit key, etc.

Thanks to @adam-p, @c2h5oh, @rezmoss, @Saku0512, @convto, @Dirbaio, @jawnsy, @lrstanley, @mfridman, @n33pm, @pkieltyka for the prior discussions, detailed reviews, advisory reports, and test contributions that shaped this PR.

Full Changelog: v5.2.5...v5.3.0

v5.2.5

Choose a tag to compare

@VojtechVitek VojtechVitek released this 05 Feb 11:17
05f1ef7

What's Changed

New Contributors

Full Changelog: v5.2.3...v5.2.5

v5.2.4

Choose a tag to compare

@VojtechVitek VojtechVitek released this 22 Jul 10:11
6eb3588

What's Changed

New Contributors

Full Changelog: v5.2.3...v5.2.4

v5.2.3

Choose a tag to compare

@VojtechVitek VojtechVitek released this 27 Aug 08:11
9b9fb55

What's Changed

  • Add pathvalue example to README and implement PathValue handler. by @catatsuy in #985
  • Allow multiple whitespace between method & pattern by @JRaspass in #1013
  • Avoid potential nil dereference by @ProjectMutilation in #1008
  • feat(mux): support http.Request.Pattern in Go 1.23 by @Gusted in #986
  • fix/608 - Fix flaky Throttle middleware test by synchronizing token usage by @OtavioBernardes in #1016
  • Optimize throttle middleware by avoiding unnecessary timer creation by @vasayxtx in #1011
  • Simplify wildcard replacement in route patterns by @srpvpn in #1012
  • Replace methodTypString func with reverseMethodMap by @JRaspass in #1018

New Contributors

Full Changelog: v5.2.2...v5.2.3

v5.2.2

Choose a tag to compare

@VojtechVitek VojtechVitek released this 20 Jun 13:31
23c395f

What's Changed

Security fix

  • Fixes GHSA-vrw8-fxc6-2r93 - "Host Header Injection Leads to Open Redirect in RedirectSlashes" commit
    • a lower-severity Open Redirect that can't be exploited in browser or email client, as it requires manipulation of a Host header
    • reported by Anuraag Baishya, @anuraagbaishya. Thank you!

New Contributors

Full Changelog: v5.2.1...v5.2.2

v5.2.1

Choose a tag to compare

@VojtechVitek VojtechVitek released this 04 Feb 11:29
71307f9

⚠️ Chi supports Go 1.20+

Starting this release, we will now support the four most recent major versions of Go. See #963 for related discussion.

What's Changed

Full Changelog: v5.2.0...v5.2.1

v5.2.0

Choose a tag to compare

@VojtechVitek VojtechVitek released this 15 Dec 21:57
0a20a0e

What's Changed

New Contributors

Full Changelog: v5.1.0...v5.2.0

v5.1.0

Choose a tag to compare

@VojtechVitek VojtechVitek released this 28 Jun 14:36
67be7d9

What's Changed

  • middleware: add Discard method to WrapResponseWriter by @patrislav in #926
    • Adds Discard() method to the middleware.WrapResponseWriter interface. This is technically an API breaking change. However after some discussion at #926 (comment), we decided to move forward, and release as minor version, as we don't expect anyone to rely on this interface / implement it externally.

New Contributors

Full Changelog: v5.0.14...v5.1.0