ronantakizawa/codereview-bench huggingface dataset:
Repository: gitbutlerapp/gitbutler
File: crates/but-api/src/commit.rs (Rust)

Code before:

        but_hunk_assignment::assign(
            db.hunk_assignments_mut()?,
            &repo,
            &ws,
            to_assign,
            None,
            context_lines,
        )?;
    }

    Ok(json::UIMoveChangesResult {
        replaced_commits: vec![(commit_id, new_commit_id.into())],
    })
}

/// Uncommits changes from a commit, with oplog and optional assign_to support
///
/// If `assign_to` is provided, the newly uncommitted changes will be assigned
/// to the specified stack.
#[but_api]
#[instrument(err(Debug))]
pub fn commit_uncommit_changes(
    ctx: &mut but_ctx::Context,
    commit_id: json::HexHash,
    changes: Vec<but_core::DiffSpec>,
    assign_to: Option<but_core::ref_metadata::StackId>,
) -> anyhow::Result<json::UIMoveChangesResult> {
    let maybe_oplog_entry = but_oplog::UnmaterializedOplogSnapshot::from_details(
        ctx,
        SnapshotDetails::new(OperationKind::DiscardChanges),
    )
    .ok();

    let res = commit_uncommit_changes_only(ctx, commit_id, changes, assign_to);

    if let Some(snapshot) = maybe_oplog_entry.filter(|_| res.is_ok()) {
        let mut guard = ctx.exclusive_worktree_access();
        snapshot.commit(ctx, guard.write_permission()).ok();
    };

    res
}


Review comment (suggestion):
With `but-api`, just like in plumbing crates, every parameter must be documented. Something to think about is `ctx` as it's always the first and I don't think it needs docs.
A viable way to not be repetitive is to link to the functions it calls, if viable.

Code after:
            .map(|a| HunkAssignmentRequest {
                hunk_header: a.hunk_header,
                path_bytes: a.path_bytes,
                stack_id: Some(stack_id),
            })
            .collect();

        but_hunk_assignment::assign(
            db.hunk_assignments_mut()?,
            &repo,
            &ws,
            to_assign,
            None,
            context_lines,
        )?;
    }

    Ok(MoveChangesResult {
        replaced_commits: vec![(commit_id, new_commit_id)],
    })
}

/// Uncommits changes from a commit, with oplog and optional assign_to support
///
/// If `assign_to` is provided, the newly uncommitted changes will be assigned
/// to the specified stack.
#[but_api(json::UIMoveChangesResult)]
#[instrument(err(Debug))]
pub fn commit_uncommit_changes(
    ctx: &mut but_ctx::Context,
    commit_id: gix::ObjectId,
    changes: Vec<but_core::DiffSpec>,
    assign_to: Option<but_core::ref_metadata::StackId>,
) -> anyhow::Result<MoveChangesResult> {
    let maybe_oplog_entry = but_oplog::UnmaterializedOplogSnapshot::from_details(
        ctx,
        SnapshotDetails::new(OperationKind::DiscardChanges),
    )
    .ok();

    let res = commit_uncommit_changes_only(ctx, commit_id, changes, assign_to);

    if let Some(snapshot) = maybe_oplog_entry.filter(|_| res.is_ok()) {
        let mut guard = ctx.exclusive_worktree_access();
        snapshot.commit(ctx, guard.write_permission()).ok();
    };

    res
}
Repository: gitbutlerapp/gitbutler
File: crates/but/src/command/update.rs (Rust)

Code before:
            // Auto-detect from current channel
            let current_channel = but_path::AppChannel::new();
            match current_channel {
                but_path::AppChannel::Nightly => VersionRequest::Nightly,
                but_path::AppChannel::Release => VersionRequest::Release,
                but_path::AppChannel::Dev => VersionRequest::Release, // Dev installs release
            }
        }
    };

    // Call installer directly (handles all user-facing output)
    // Don't print usage info since user is already using the CLI
    but_installer::run_installation_with_version(version_request, false)?;

    // Show change log link
    if let Some(writer) = out.for_human() {
        writeln!(
            writer,
            "{} {}",
            "→".cyan().bold(),
            "View release notes: https://gitbutler.com/releases".bold()
        )?;
        writeln!(writer)?;
    }

    tracing::info!("Invalidating update check cache");
    let mut cache = but_db::AppCacheHandle::new_in_directory(but_path::app_cache_dir().ok());
    if let Err(err) = cache.update_check_mut().and_then(|handle| handle.delete()) {
        tracing::warn!(?err, "Failed to invalidate update check cache");
        if let Some(writer) = out.for_human() {
            writeln!(
                writer,
                "Failed to invalidate update check cache - skipping invalidation: {err:?}",
            )?;
        }
    }

    Ok(())
}


Review comment (bug):
To me this isn't an `info` level trace, it's more like a `debug` or even `trace`.

Code after:
            // Auto-detect from current channel
            let current_channel = but_path::AppChannel::new();
            match current_channel {
                but_path::AppChannel::Nightly => VersionRequest::Nightly,
                but_path::AppChannel::Release => VersionRequest::Release,
                but_path::AppChannel::Dev => VersionRequest::Release, // Dev installs release
            }
        }
    };

    // Call installer directly (handles all user-facing output)
    // Don't print usage info since user is already using the CLI
    but_installer::run_installation_with_version(version_request, false)?;

    // Show change log link
    if let Some(writer) = out.for_human() {
        writeln!(
            writer,
            "{} {}",
            "→".cyan().bold(),
            "View release notes: https://gitbutler.com/releases".bold()
        )?;
        writeln!(writer)?;
    }

    let mut cache = but_ctx::Context::app_cache();
    if let Err(err) = cache.update_check_mut().and_then(|handle| handle.delete()) {
        tracing::warn!(?err, "Failed to invalidate update check cache");
        if let Some(writer) = out.for_human() {
            writeln!(
                writer,
                "Failed to invalidate update check cache - skipping invalidation: {err:?}",
            )?;
        }
    }

    Ok(())
}
Repository: go-chi/chi
File: context.go (Go)

Code before:
package chi

import (
	"context"
	"net/http"
)

var (
	RouteCtxKey = &contextKey{"RouteContext"}
)

var _ context.Context = &Context{}

// A Context is the default routing context set on the root node of a
// request context to track URL parameters and an optional routing path.
type Context struct {
	context.Context

	// URL routing parameter key and values.
	Params params

	// Routing path override used by subrouters.
	RoutePath string

	// Routing pattern matching the path.
	RoutePattern string

	// Routing patterns throughout the lifecycle of the request,
	// across all connected routers.
	RoutePatterns []string
}

// NewRouteContext returns a new routing Context object.
func NewRouteContext() *Context {
	rctx := &Context{}
	ctx := context.WithValue(context.Background(), RouteCtxKey, rctx)
	rctx.Context = ctx
	return rctx
}

// reset a routing context to its initial state.
func (x *Context) reset() {
	x.Params = x.Params[:0]
	x.RoutePath = ""

Review comment (suggestion):
@mrcpvn thanks for the note, however, chi v2 already breaks a lot of compatibility with v1, so that is okay. the chi.Context is itself a context.Context object, because it implements the context.Context interface, and uses the parent context.Context for behaviour (see implementations of the methods on chi.Context). 

@mrcpvn do you want to do this for testing..? we could export the "Parent", but I'd rather not unless we have to... this works https://github.com/pressly/chi/blob/master/mux_test.go#L833  .. is that not enough? let me know


Code after:
package chi

import (
	"context"
	"net/http"
	"time"
)

var (
	RouteCtxKey = &contextKey{"RouteContext"}
)

var _ context.Context = &Context{}

// Context is the default routing context set on the root node of a
// request context to track URL parameters and an optional routing path.
type Context struct {
	// Parent context
	parent context.Context

	// URL routing parameter key and values.
	Params params

	// Routing path override used by subrouters.
	RoutePath string

	// Routing pattern matching the path.
	RoutePattern string

	// Routing patterns throughout the lifecycle of the request,
	// across all connected routers.
	RoutePatterns []string
}

// NewRouteContext returns a new routing Context object.
func NewRouteContext() *Context {
	return &Context{}
}

// reset a routing context to its initial state.
func (x *Context) reset() {
	x.parent = nil
	x.Params = x.Params[:0]
	x.RoutePath = ""
Repository: go-chi/chi
File: middleware/middleware18_test.go (Go)

Code before:
// +build go1.8

package middleware

import (
	"crypto/tls"
	"io"
	"net/http"
	"testing"
	"time"

	"golang.org/x/net/http2"
)

// NOTE: we must import `golang.org/x/net/http2` in order to explicitly enable
// http2 transports for certain tests. The runtime pkg does not have this dependency
// though as the transport configuration happens under the hood on go 1.7+.

func TestWrapWriterHTTP2(t *testing.T) {
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, cn := w.(http.CloseNotifier)
		if !cn {
			t.Fatal("request should have been a http.CloseNotifier")
		}
		_, fl := w.(http.Flusher)
		if !fl {
			t.Fatal("request should have been a http.Flusher")
		}
		_, hj := w.(http.Hijacker)
		if hj {
			t.Fatal("request should not have been a http.Hijacker")
		}
		_, rf := w.(io.ReaderFrom)
		if rf {
			t.Fatal("request should not have been a io.ReaderFrom")
		}
		_, ps := w.(http.Pusher)
		if !ps {
			t.Fatal("request should have been a http.Pusher")
		}

		w.Write([]byte("OK"))
	})

	server := http.Server{
		Addr:    ":7072",
		Handler: handler,
	}

Review comment (suggestion):
Now I think about it, these messages should probably all read `ResponseWriter should have been ...`

Code after:
// +build go1.8

package middleware

import (
	"crypto/tls"
	"io"
	"net/http"
	"testing"
	"time"

	"golang.org/x/net/http2"
)

// NOTE: we must import `golang.org/x/net/http2` in order to explicitly enable
// http2 transports for certain tests. The runtime pkg does not have this dependency
// though as the transport configuration happens under the hood on go 1.7+.

func TestWrapWriterHTTP2(t *testing.T) {
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, cn := w.(http.CloseNotifier)
		if !cn {
			t.Fatal("request should have been a http.CloseNotifier")
		}
		_, fl := w.(http.Flusher)
		if !fl {
			t.Fatal("request should have been a http.Flusher")
		}
		_, hj := w.(http.Hijacker)
		if hj {
			t.Fatal("request should not have been a http.Hijacker")
		}
		_, rf := w.(io.ReaderFrom)
		if rf {
			t.Fatal("request should not have been a io.ReaderFrom")
		}
		_, ps := w.(http.Pusher)
		if !ps {
			t.Fatal("request should have been a http.Pusher")
		}

		w.Write([]byte("OK"))
	})

	wmw := func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			next.ServeHTTP(NewWrapResponseWriter(w, r.ProtoMajor), r)
		})
Repository: go-chi/chi
File: _examples/router-walk/main.go (Go)

Code before:
	"net/http"

	"github.com/go-chi/chi"
)

func main() {
	r := chi.NewRouter()
	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("root."))
	})

	r.Route("/road", func(r chi.Router) {
		r.Get("/left", func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("left road"))
		})
		r.Post("/right", func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("right road"))
		})
	})

	r.Put("/ping", Ping)

	methodCount := make(map[string]int)
	walkFunc := func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
		methodCount[method]++
		return nil
	}

	if err := chi.Walk(r, walkFunc); err != nil {
		fmt.Errorf("%+v", err)
	}

	for k, v := range methodCount {
		fmt.Printf("%d Routes use %s Method\n", v, k)
	}
}

// Ping returns pong
func Ping(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("pong"))
}


Review comment (suggestion):
You might wanna print the routes in the following format instead?

```
GET /
GET /ping
```

Code after:
	"net/http"

	"github.com/go-chi/chi"
)

func main() {
	r := chi.NewRouter()
	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("root."))
	})

	r.Route("/road", func(r chi.Router) {
		r.Get("/left", func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("left road"))
		})
		r.Post("/right", func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("right road"))
		})
	})

	r.Put("/ping", Ping)

	walkFunc := func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error {
		fmt.Printf("%s %s\n", method, route)
		return nil
	}

	if err := chi.Walk(r, walkFunc); err != nil {
		fmt.Printf("Logging err: %s\n", err.Error())
	}
}

// Ping returns pong
func Ping(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("pong"))
}
Repository: go-chi/chi
File: middleware/content_type.go (Go)

Code before:
		return http.HandlerFunc(fn)
	}
}

// AllowContentType enforces a whitelist of request Content-Types otherwise responds
// with a 415 Unsupported Media Type status.
func AllowContentType(contentTypes ...string) func(next http.Handler) http.Handler {
	allowedContentTypes := make(map[string]bool, len(contentTypes))
	for _, ctype := range contentTypes {
		allowedContentTypes[strings.TrimSpace(strings.ToLower(ctype))] = true
	}

	return func(next http.Handler) http.Handler {
		fn := func(w http.ResponseWriter, r *http.Request) {
			if r.ContentLength == 0 {
				// skip check for empty content body
				next.ServeHTTP(w, r)
				return
			}

			s := strings.ToLower(strings.TrimSpace(r.Header.Get("Content-Type")))
			if i := strings.Index(s, ";"); i > -1 {
				s = s[0:i]
			}

			if allowedContentTypes[s] {
				next.ServeHTTP(w, r)
				return
			}

			w.WriteHeader(http.StatusUnsupportedMediaType)
		}
		return http.HandlerFunc(fn)
	}
}


Review comment (suggestion):
If all you're doing is checking existence _within_ the map, might as well use `map[string]struct{}` and then comma okay. We don't actually care about the value, since they are all true.

```
if _, ok := allowedContentTypes[s]; ok {
	next.ServeHTTP(w, r)
	return
}
```

Code after:
		return http.HandlerFunc(fn)
	}
}

// AllowContentType enforces a whitelist of request Content-Types otherwise responds
// with a 415 Unsupported Media Type status.
func AllowContentType(contentTypes ...string) func(next http.Handler) http.Handler {
	allowedContentTypes := make(map[string]struct{}, len(contentTypes))
	for _, ctype := range contentTypes {
		allowedContentTypes[strings.TrimSpace(strings.ToLower(ctype))] = struct{}{}
	}

	return func(next http.Handler) http.Handler {
		fn := func(w http.ResponseWriter, r *http.Request) {
			if r.ContentLength == 0 {
				// skip check for empty content body
				next.ServeHTTP(w, r)
				return
			}

			s := strings.ToLower(strings.TrimSpace(r.Header.Get("Content-Type")))
			if i := strings.Index(s, ";"); i > -1 {
				s = s[0:i]
			}

			if _, ok := allowedContentTypes[s]; ok {
				next.ServeHTTP(w, r)
				return
			}

			w.WriteHeader(http.StatusUnsupportedMediaType)
		}
		return http.HandlerFunc(fn)
	}
}
Repository: go-chi/chi
File: middleware/profiler.go (Go)

Code before:
package middleware

import (
	"expvar"
	"net/http"
	"net/http/pprof"

	"github.com/go-chi/chi/v5"
)

// Profiler is a convenient subrouter used for mounting net/http/pprof. ie.
//
//	func MyService() http.Handler {
//	  r := chi.NewRouter()
//	  // ..middlewares
//	  r.Mount("/debug", middleware.Profiler())
//	  // ..routes
//	  return r
//	}
func Profiler() http.Handler {
	r := chi.NewRouter()
	r.Use(NoCache)

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.RequestURI+"/pprof/", http.StatusMovedPermanently)
	})
	r.HandleFunc("/pprof", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.RequestURI+"/", http.StatusMovedPermanently)
	})

	r.HandleFunc("/pprof/*", pprof.Index)
	r.HandleFunc("/pprof/cmdline", pprof.Cmdline)
	r.HandleFunc("/pprof/profile", pprof.Profile)
	r.HandleFunc("/pprof/symbol", pprof.Symbol)
	r.HandleFunc("/pprof/trace", pprof.Trace)
	r.Handle("/vars", expvar.Handler())

	r.Handle("/pprof/goroutine", pprof.Handler("goroutine"))
	r.Handle("/pprof/threadcreate", pprof.Handler("threadcreate"))

Review comment (suggestion):
It was fixed by VS Code automatically from spaces to tabs. If it is important to be as before, I can revert this comment back via `vim`

Code after:
package middleware

import (
	"expvar"
	"net/http"
	"net/http/pprof"

	"github.com/go-chi/chi/v5"
)

// Profiler is a convenient subrouter used for mounting net/http/pprof. ie.
//
//	func MyService() http.Handler {
//		r := chi.NewRouter()
//		// ..middlewares
//		r.Mount("/debug", middleware.Profiler())
//		// ..routes
//		return r
//	}
func Profiler() http.Handler {
	r := chi.NewRouter()
	r.Use(NoCache)

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.RequestURI+"/pprof/", http.StatusMovedPermanently)
	})
	r.HandleFunc("/pprof", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.RequestURI+"/", http.StatusMovedPermanently)
	})

	r.HandleFunc("/pprof/*", pprof.Index)
	r.HandleFunc("/pprof/cmdline", pprof.Cmdline)
	r.HandleFunc("/pprof/profile", pprof.Profile)
	r.HandleFunc("/pprof/symbol", pprof.Symbol)
	r.HandleFunc("/pprof/trace", pprof.Trace)
	r.Handle("/vars", expvar.Handler())

	r.Handle("/pprof/goroutine", pprof.Handler("goroutine"))
	r.Handle("/pprof/threadcreate", pprof.Handler("threadcreate"))
Repository: go-chi/chi
File: middleware/profiler.go (Go)

Code before:
package middleware

import (
	"expvar"
	"net/http"
	"net/http/pprof"

	"github.com/go-chi/chi/v5"
)

// Profiler is a convenient subrouter used for mounting net/http/pprof. ie.
//
//	func MyService() http.Handler {
//	  r := chi.NewRouter()
//	  // ..middlewares
//	  r.Mount("/debug", middleware.Profiler())
//	  // ..routes
//	  return r
//	}
func Profiler() http.Handler {
	r := chi.NewRouter()
	r.Use(NoCache)

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.RequestURI+"/pprof/", http.StatusMovedPermanently)
	})
	r.HandleFunc("/pprof", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.RequestURI+"/", http.StatusMovedPermanently)
	})

	r.HandleFunc("/pprof/*", pprof.Index)
	r.HandleFunc("/pprof/cmdline", pprof.Cmdline)
	r.HandleFunc("/pprof/profile", pprof.Profile)
	r.HandleFunc("/pprof/symbol", pprof.Symbol)
	r.HandleFunc("/pprof/trace", pprof.Trace)
	r.Handle("/vars", expvar.Handler())

	r.Handle("/pprof/goroutine", pprof.Handler("goroutine"))
	r.Handle("/pprof/threadcreate", pprof.Handler("threadcreate"))
	r.Handle("/pprof/mutex", pprof.Handler("mutex"))
	r.Handle("/pprof/heap", pprof.Handler("heap"))
	r.Handle("/pprof/block", pprof.Handler("block"))
	r.Handle("/pprof/allocs", pprof.Handler("allocs"))


Review comment (bug):
Let's use TAB instead of whitespace:

```suggestion
 //	func MyService() http.Handler {
//		r := chi.NewRouter()
//		// ..middlewares
//		r.Mount("/debug", middleware.Profiler())
//		// ..routes
//		return r
//	}
```

Code after:
package middleware

import (
	"expvar"
	"net/http"
	"net/http/pprof"

	"github.com/go-chi/chi/v5"
)

// Profiler is a convenient subrouter used for mounting net/http/pprof. ie.
//
//	func MyService() http.Handler {
//		r := chi.NewRouter()
//		// ..middlewares
//		r.Mount("/debug", middleware.Profiler())
//		// ..routes
//		return r
//	}
func Profiler() http.Handler {
	r := chi.NewRouter()
	r.Use(NoCache)

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.RequestURI+"/pprof/", http.StatusMovedPermanently)
	})
	r.HandleFunc("/pprof", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, r.RequestURI+"/", http.StatusMovedPermanently)
	})

	r.HandleFunc("/pprof/*", pprof.Index)
	r.HandleFunc("/pprof/cmdline", pprof.Cmdline)
	r.HandleFunc("/pprof/profile", pprof.Profile)
	r.HandleFunc("/pprof/symbol", pprof.Symbol)
	r.HandleFunc("/pprof/trace", pprof.Trace)
	r.Handle("/vars", expvar.Handler())

	r.Handle("/pprof/goroutine", pprof.Handler("goroutine"))
	r.Handle("/pprof/threadcreate", pprof.Handler("threadcreate"))
	r.Handle("/pprof/mutex", pprof.Handler("mutex"))
	r.Handle("/pprof/heap", pprof.Handler("heap"))
	r.Handle("/pprof/block", pprof.Handler("block"))
	r.Handle("/pprof/allocs", pprof.Handler("allocs"))
Repository: go-chi/chi
File: middleware/realip.go (Go)

Code before:
package middleware

// Ported from Goji's middleware, source:
// https://github.com/zenazn/goji/tree/master/web/middleware

import (
	"net"
	"net/http"
	"strings"
)

var DefaultRealIPHeaders = []string{
	"True-Client-IP",   // Cloudflare Enterprise plan
	"X-Real-IP",
	"X-Forwarded-For",
}

// RealIP is a middleware that sets a http.Request's RemoteAddr to the results
// of parsing either the True-Client-IP, X-Real-IP or the X-Forwarded-For headers
// (in that order).
//
// This middleware should be inserted fairly early in the middleware stack to
// ensure that subsequent layers (e.g., request loggers) which examine the
// RemoteAddr will see the intended value.
//
// You should only use this middleware if you can trust the headers passed to
// you (in particular, the three headers this middleware uses), for example
// because you have placed a reverse proxy like HAProxy or nginx in front of
// chi. If your reverse proxies are configured to pass along arbitrary header
// values from the client, or if you use this middleware without a reverse
// proxy, malicious clients will be able to make you very sad (or, depending on
// how you're using RemoteAddr, vulnerable to an attack of some sort).
func RealIP(h http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		if rip := getRealIP(r, DefaultRealIPHeaders); rip != "" {
			r.RemoteAddr = rip
		}

Review comment (suggestion):
I don't love making package-level variables as any dependency could change the values and create side effects. I'd rather make it a const, or unexported and folks can pass their own with the new method

Code after:
package middleware

// Ported from Goji's middleware, source:
// https://github.com/zenazn/goji/tree/master/web/middleware

import (
	"net"
	"net/http"
	"strings"
)

var defaultHeaders = []string{
	"True-Client-IP", // Cloudflare Enterprise plan
	"X-Real-IP",
	"X-Forwarded-For",
}

// RealIP is a middleware that sets a http.Request's RemoteAddr to the results
// of parsing either the True-Client-IP, X-Real-IP or the X-Forwarded-For headers
// (in that order).
//
// This middleware should be inserted fairly early in the middleware stack to
// ensure that subsequent layers (e.g., request loggers) which examine the
// RemoteAddr will see the intended value.
//
// You should only use this middleware if you can trust the headers passed to
// you (in particular, the three headers this middleware uses), for example
// because you have placed a reverse proxy like HAProxy or nginx in front of
// chi. If your reverse proxies are configured to pass along arbitrary header
// values from the client, or if you use this middleware without a reverse
// proxy, malicious clients will be able to make you very sad (or, depending on
// how you're using RemoteAddr, vulnerable to an attack of some sort).
func RealIP(h http.Handler) http.Handler {
	fn := func(w http.ResponseWriter, r *http.Request) {
		if rip := getRealIP(r, defaultHeaders); rip != "" {
			r.RemoteAddr = rip
		}