Fix Clone() so CheckRedirect closes over the clone, not the parent - #877
Fix Clone() so CheckRedirect closes over the clone, not the parent#877sapirbaruch wants to merge 2 commits into
Conversation
Clone() shared the parent's *httpBackend and therefore the parent's http.Client. The Client's CheckRedirect function was set during Init() as c.checkRedirectFunc(), which closes over the parent collector c. As a result, settings like AllowURLRevisit on a cloned collector had no effect on redirects: the redirect handler always read the *parent's* AllowURLRevisit field, causing spurious "already visited" errors when the clone allows URL revisits but the parent does not. Fix this by giving the clone its own http.Client — a shallow copy of the parent's — with a fresh CheckRedirect that closes over the clone. The Transport, Jar, and Timeout are still shared between parent and clone, preserving the existing connection-pool and cookie-jar sharing behaviour documented in Clone's comment. Fixes gocolly#875
|
I took a verification pass on this because the fix direction makes sense for #875, but the new regression test currently fails for me as submitted: $ go test ./... -run TestCloneAllowURLRevisitIndependent -count=1 -v
=== RUN TestCloneAllowURLRevisitIndependent
colly_test.go:2279: final URL visited 0 times, want 2
--- FAIL: TestCloneAllowURLRevisitIndependent (0.01s)The implementation itself looks consistent with the bug report: the clone gets its own I tried changing only that assertion path to count the final URL in go test . -run TestCloneAllowURLRevisitIndependent -count=1 -v
go test ./... -count=1So I think this is likely a test adjustment rather than a blocker in the core fix. |
OnRequest fires before net/http follows a redirect, so the final redirected URL was never counted. Use OnResponse with r.Request.URL to observe the URL that was actually reached. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Thanks for updating the test. I fetched go test ./... -run TestCloneAllowURLRevisitIndependent -count=1 -v
go test ./... -count=1
git diff --check upstream/master...HEADAll pass locally now. The regression test is exercising the redirected final URL through I only see the License Compliance status from GitHub; no code CI is reported on the PR branch. |
|
The test is now fixed and verified passing by @StantonMatt. The fix gives |
Fixes #875.
What's wrong
Clone()shares the parent's*httpBackend(and therefore the same*http.Client). DuringInit(), the client'sCheckRedirectis set toc.checkRedirectFunc(), a closure that captures the parent collectorc. When a cloned collector follows a redirect, it calls the parent's redirect function, not the clone's.Concretely, even if
clone.AllowURLRevisit = true, the redirect check readsparent.AllowURLRevisit(which may befalse), and the redirect fails withAlreadyVisitedError.Fix
Give the clone its own
http.Client— a shallow copy of the parent's, withCheckRedirectreplaced byd.checkRedirectFunc()(closing over the clone). TheTransport,Jar, andTimeoutare copied by the struct literal and still reference the same underlying objects, so connection-pool and cookie-jar sharing is preserved.Test
TestCloneAllowURLRevisitIndependentcreates a parent withAllowURLRevisit = false, clones it and setsAllowURLRevisit = trueon the clone, then visits a redirecting URL twice. Before this fix the second visit panicked with anAlreadyVisitedErroron the redirect leg; after the fix both visits complete successfully.