Skip to content

Commit 5bb73b5

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 8e158fd commit 5bb73b5

File tree

3 files changed

+34
-18
lines changed

3 files changed

+34
-18
lines changed

runtime/httpcache.go

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

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

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

runtime/httpcache_test.go

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

226229
_, err = app.Run(map[string]string{})
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 := &Applet{}
235+
err = app2.Load("httpredirect", "httpredirect.star", b, nil)
236+
assert.NoError(t, err)
237+
238+
_, err = app2.Run(map[string]string{})
239+
assert.NoError(t, err)
228240
}

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)