Skip to content

Commit ec22f51

Browse files
committed
Use new http client and cookie jar across executions
This ensures that cookies from one app aren't leaked to other apps. Instead of InitHTTP setting a single global instance of http.Client, it now sets a factory method. Each time the http module is loaded, that factory is used to create a new http client. Those clients all share the same cache, but not cookie jars
1 parent df16041 commit ec22f51

File tree

3 files changed

+33
-18
lines changed

3 files changed

+33
-18
lines changed

runtime/httpcache.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,20 +56,22 @@ func InitHTTP(cache Cache) {
5656
transport: http.DefaultTransport,
5757
}
5858

59-
// Providing a cookie jar allows sessions and redirects to work properly. With a
60-
// jar present, any cookies set in a response will automatically be added to
61-
// subsequent requests. This means that we can follow redirects after logging into
62-
// a session. Without a jar, any cookies will be dropped from redirects unless explicitly
63-
// set in the original outgoing request.
64-
// https://cs.opensource.google/go/go/+/master:src/net/http/client.go;drc=4c394b5638cc2694b1eff6418bc3e7db8132de0e;l=88
65-
jar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) // never returns non-nil err
66-
67-
httpClient := &http.Client{
68-
Jar: jar,
69-
Transport: cc,
70-
Timeout: HTTPTimeout * 2,
59+
starlarkhttp.StarlarkHTTPClient = func() *http.Client {
60+
// Providing a cookie jar allows sessions and redirects to work properly. With a
61+
// jar present, any cookies set in a response will automatically be added to
62+
// subsequent requests. This means that we can follow redirects after logging into
63+
// a session. Without a jar, any cookies will be dropped from redirects unless explicitly
64+
// set in the original outgoing request.
65+
// https://cs.opensource.google/go/go/+/master:src/net/http/client.go;drc=4c394b5638cc2694b1eff6418bc3e7db8132de0e;l=88
66+
jar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) // never returns non-nil err
67+
68+
httpClient := &http.Client{
69+
Jar: jar,
70+
Transport: cc,
71+
Timeout: HTTPTimeout * 2,
72+
}
73+
return httpClient
7174
}
72-
starlarkhttp.StarlarkHTTPClient = httpClient
7375
}
7476

7577
// RoundTrip is an approximation of what our internal HTTP proxy does. It should

runtime/httpcache_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ func TestSetCookieOnRedirect(t *testing.T) {
191191
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
192192
// Requests to "/login" set a cookie and redirect to /destination
193193
if strings.HasSuffix(r.URL.Path, "/login") {
194+
if len(r.Cookies()) != 0 {
195+
t.Errorf("Cookie was already set on initial call")
196+
}
194197
w.Header().Set("Set-Cookie", "doodad=foobar; path=/; HttpOnly")
195198
w.Header().Set("Location", "/destination")
196199
w.WriteHeader(302)
@@ -200,7 +203,7 @@ func TestSetCookieOnRedirect(t *testing.T) {
200203
if strings.HasSuffix(r.URL.Path, "/destination") {
201204
c, err := r.Cookie("doodad")
202205
if err != nil {
203-
t.Errorf("Expected cookie `doodad` not present") // Occurs if client has no cookie jar
206+
t.Errorf("Expected cookie `doodad` not present") // Occurs if client has no cookie jar
204207
}
205208
if c.Value != "foobar" {
206209
t.Errorf("Cookie `doodad` value mismatch. Expected foobar, got %s", c.Value)
@@ -225,4 +228,12 @@ func TestSetCookieOnRedirect(t *testing.T) {
225228

226229
_, err = app.Run(context.Background())
227230
assert.NoError(t, err)
231+
232+
// Run it again and check that we're not using the same cookie jar
233+
// across executions. If we were, the first request would error out.
234+
app2, err := NewApplet("httpredirect.star", b)
235+
assert.NoError(t, err)
236+
237+
_, err = app2.Run(context.Background())
238+
assert.NoError(t, err)
228239
}

runtime/modules/starlarkhttp/starlarkhttp.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ func AsString(x starlark.Value) (string, error) {
5151
const ModuleName = "http.star"
5252

5353
var (
54-
// StarlarkHTTPClient is the http client used to create the http module. override with
55-
// a custom client before calling LoadModule
56-
StarlarkHTTPClient = http.DefaultClient
54+
// StarlarkHTTPClient is a factory method for creating the http client used to create the http module.
55+
// override with a custom function before calling LoadModule
56+
StarlarkHTTPClient = func() *http.Client {
57+
return http.DefaultClient
58+
}
5759
// StarlarkHTTPGuard is a global RequestGuard used in LoadModule. override with a custom
5860
// implementation before calling LoadModule
5961
StarlarkHTTPGuard RequestGuard
@@ -69,7 +71,7 @@ const (
6971

7072
// LoadModule creates an http Module
7173
func LoadModule() (starlark.StringDict, error) {
72-
var m = &Module{cli: StarlarkHTTPClient}
74+
var m = &Module{cli: StarlarkHTTPClient()}
7375
if StarlarkHTTPGuard != nil {
7476
m.rg = StarlarkHTTPGuard
7577
}

0 commit comments

Comments
 (0)