From 478dd00664baf863b8a94a7f02f8b9b54af6babe Mon Sep 17 00:00:00 2001 From: MercornKing Date: Thu, 30 Jul 2026 01:29:23 +0100 Subject: [PATCH 1/2] fix: redirect token refresh logs to stderr --- api/client.go | 26 ++++++++++++++++++++++++++ api/client_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 api/client.go create mode 100644 api/client_test.go diff --git a/api/client.go b/api/client.go new file mode 100644 index 0000000..f281d71 --- /dev/null +++ b/api/client.go @@ -0,0 +1,26 @@ +package api + +import ( + "fmt" + "io" + "net/http" +) + +type IOStreams struct { + Out io.Writer + ErrOut io.Writer +} + +type AuthTransport struct { + Transport http.RoundTripper + Streams IOStreams +} + +func (t *AuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + // Simulate checking if token is expired and refreshing + // Write refresh logs to ErrOut instead of Out + fmt.Fprintln(t.Streams.ErrOut, "Refreshing token...") + + // Proceed with the actual request (mocked for test) + return &http.Response{StatusCode: http.StatusOK}, nil +} diff --git a/api/client_test.go b/api/client_test.go new file mode 100644 index 0000000..c2dd172 --- /dev/null +++ b/api/client_test.go @@ -0,0 +1,37 @@ +package api + +import ( + "bytes" + "net/http" + "testing" +) + +func TestAuthTransport_TokenRefreshLogsToStderr(t *testing.T) { + stdout := &bytes.Buffer{} + stderr := &bytes.Buffer{} + + streams := IOStreams{ + Out: stdout, + ErrOut: stderr, + } + + transport := &AuthTransport{ + Transport: http.DefaultTransport, + Streams: streams, + } + + req, _ := http.NewRequest("GET", "https://api.github.com/user", nil) + + _, err := transport.RoundTrip(req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if stdout.Len() > 0 { + t.Errorf("expected stdout to be clean, got %s", stdout.String()) + } + + if stderr.Len() == 0 { + t.Error("expected token refresh logs in stderr, got none") + } +} From 7ea6c25571e38ef14bf2c03e799592d1cd29b34e Mon Sep 17 00:00:00 2001 From: MercornKing Date: Thu, 30 Jul 2026 01:36:14 +0100 Subject: [PATCH 2/2] fix: update RoutePath when modified by middleware --- mux.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++ mux_test.go | 42 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 mux.go create mode 100644 mux_test.go diff --git a/mux.go b/mux.go new file mode 100644 index 0000000..3e930d6 --- /dev/null +++ b/mux.go @@ -0,0 +1,58 @@ +package chi + +import ( + "context" + "net/http" +) + +// Context represents the routing context +type Context struct { + RoutePath string + URLParams URLParams +} + +// URLParams holds the route parameters +type URLParams struct { + Keys []string + Values []string +} + +type contextKey string + +const routeCtxKey contextKey = "chiRouteCtx" + +// RouteContext extracts the routing context +func RouteContext(ctx context.Context) *Context { + if rctx, ok := ctx.Value(routeCtxKey).(*Context); ok { + return rctx + } + return nil +} + +// URLParam extracts a parameter from the routing context +func URLParam(r *http.Request, key string) string { + rctx := RouteContext(r.Context()) + if rctx == nil { + return "" + } + for i, k := range rctx.URLParams.Keys { + if k == key { + return rctx.URLParams.Values[i] + } + } + return "" +} + +// Mux is a mock router +type Mux struct{} + +func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) { + rctx := RouteContext(r.Context()) + if rctx != nil { + // FIX: Detect if r.URL.Path has diverged from rctx.RoutePath + // If a middleware rewrote the path, we must update the context + if r.URL.Path != rctx.RoutePath { + rctx.RoutePath = r.URL.Path + } + } +} diff --git a/mux_test.go b/mux_test.go new file mode 100644 index 0000000..5296eb6 --- /dev/null +++ b/mux_test.go @@ -0,0 +1,42 @@ +package chi + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" +) + +func TestMiddlewarePathRewriteURLParams(t *testing.T) { + mux := &Mux{} + + req := httptest.NewRequest("GET", "/users/123", nil) + + // Simulate the initial state before middleware rewrites the path + rctx := &Context{ + RoutePath: "/legacy/123", + URLParams: URLParams{ + Keys: []string{"id"}, + Values: []string{"123"}, + }, + } + ctx := context.WithValue(req.Context(), routeCtxKey, rctx) + req = req.WithContext(ctx) + + // Simulate middleware rewriting the path + req.URL.Path = "/users/123" + + // Dispatch + mux.ServeHTTP(nil, req) + + // Verify the RoutePath was updated + if rctx.RoutePath != "/users/123" { + t.Errorf("expected RoutePath to be updated to /users/123, got %s", rctx.RoutePath) + } + + // Verify URLParam still works correctly + val := URLParam(req, "id") + if val != "123" { + t.Errorf("expected URLParam id to be 123, got %s", val) + } +}