Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Make HTTP sessions work #1008

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
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
  • Loading branch information
dinosaursrarr committed Apr 24, 2024
commit ec22f510d2fe850941a014e7ef4c02facb11b992
28 changes: 15 additions & 13 deletions runtime/httpcache.go
Original file line number Diff line number Diff line change
@@ -56,20 +56,22 @@ func InitHTTP(cache Cache) {
transport: http.DefaultTransport,
}

// Providing a cookie jar allows sessions and redirects to work properly. With a
// jar present, any cookies set in a response will automatically be added to
// subsequent requests. This means that we can follow redirects after logging into
// a session. Without a jar, any cookies will be dropped from redirects unless explicitly
// set in the original outgoing request.
// https://cs.opensource.google/go/go/+/master:src/net/http/client.go;drc=4c394b5638cc2694b1eff6418bc3e7db8132de0e;l=88
jar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List}) // never returns non-nil err

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

httpClient := &http.Client{
Jar: jar,
Transport: cc,
Timeout: HTTPTimeout * 2,
}
return httpClient
}
starlarkhttp.StarlarkHTTPClient = httpClient
}

// RoundTrip is an approximation of what our internal HTTP proxy does. It should
13 changes: 12 additions & 1 deletion runtime/httpcache_test.go
Original file line number Diff line number Diff line change
@@ -191,6 +191,9 @@ func TestSetCookieOnRedirect(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Requests to "/#" set a cookie and redirect to /destination
if strings.HasSuffix(r.URL.Path, "/#") {
if len(r.Cookies()) != 0 {
t.Errorf("Cookie was already set on initial call")
}
w.Header().Set("Set-Cookie", "doodad=foobar; path=/; HttpOnly")
w.Header().Set("Location", "/destination")
w.WriteHeader(302)
@@ -200,7 +203,7 @@ func TestSetCookieOnRedirect(t *testing.T) {
if strings.HasSuffix(r.URL.Path, "/destination") {
c, err := r.Cookie("doodad")
if err != nil {
t.Errorf("Expected cookie `doodad` not present") // Occurs if client has no cookie jar
t.Errorf("Expected cookie `doodad` not present") // Occurs if client has no cookie jar
}
if c.Value != "foobar" {
t.Errorf("Cookie `doodad` value mismatch. Expected foobar, got %s", c.Value)
@@ -225,4 +228,12 @@ func TestSetCookieOnRedirect(t *testing.T) {

_, err = app.Run(context.Background())
assert.NoError(t, err)

// Run it again and check that we're not using the same cookie jar
// across executions. If we were, the first request would error out.
app2, err := NewApplet("httpredirect.star", b)
assert.NoError(t, err)

_, err = app2.Run(context.Background())
assert.NoError(t, err)
}
10 changes: 6 additions & 4 deletions runtime/modules/starlarkhttp/starlarkhttp.go
Original file line number Diff line number Diff line change
@@ -51,9 +51,11 @@ func AsString(x starlark.Value) (string, error) {
const ModuleName = "http.star"

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

// LoadModule creates an http Module
func LoadModule() (starlark.StringDict, error) {
var m = &Module{cli: StarlarkHTTPClient}
var m = &Module{cli: StarlarkHTTPClient()}
if StarlarkHTTPGuard != nil {
m.rg = StarlarkHTTPGuard
}
Loading
Oops, something went wrong.