From d73eaf74e8aa309eab2dd8917470a074a556404a Mon Sep 17 00:00:00 2001 From: Harry Harpham Date: Sun, 29 Sep 2024 08:46:05 -0600 Subject: [PATCH 1/6] Use flashlight version with domain fronting changes --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3804a38c4..6001011f3 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( github.com/getlantern/eventual v1.0.0 github.com/getlantern/eventual/v2 v2.0.2 github.com/getlantern/filepersist v0.0.0-20210901195658-ed29a1cb0b7c - github.com/getlantern/flashlight/v7 v7.6.111 + github.com/getlantern/flashlight/v7 v7.6.112-0.20240929144745-72a54c5a4e73 github.com/getlantern/fronted v0.0.0-20240822220559-6e97652d23cc github.com/getlantern/golog v0.0.0-20230503153817-8e72de7e0a65 github.com/getlantern/hidden v0.0.0-20220104173330-f221c5a24770 diff --git a/go.sum b/go.sum index 3fbaf3d67..c03dab384 100644 --- a/go.sum +++ b/go.sum @@ -291,8 +291,8 @@ github.com/getlantern/fdcount v0.0.0-20210503151800-5decd65b3731/go.mod h1:XZwE+ github.com/getlantern/filepersist v0.0.0-20160317154340-c5f0cd24e799/go.mod h1:8DGAx0LNUfXNnEH+fXI0s3OCBA/351kZCiz/8YSK3i8= github.com/getlantern/filepersist v0.0.0-20210901195658-ed29a1cb0b7c h1:mcz27xtAkb1OuOLBct/uFfL1p3XxAIcFct82GbT+UZM= github.com/getlantern/filepersist v0.0.0-20210901195658-ed29a1cb0b7c/go.mod h1:8DGAx0LNUfXNnEH+fXI0s3OCBA/351kZCiz/8YSK3i8= -github.com/getlantern/flashlight/v7 v7.6.111 h1:v+HPV34U5OrCYe7K+iKln2eTXo4MjyQOp0M5+Exfev8= -github.com/getlantern/flashlight/v7 v7.6.111/go.mod h1:M7KG4/LELzZkk6FiFxucmk0rirlQwD785Y0ee5RyiOM= +github.com/getlantern/flashlight/v7 v7.6.112-0.20240929144745-72a54c5a4e73 h1:esX0xv38MqWiHc5oHo4Nc49jHM0PEfiPwSoqw3H0BPY= +github.com/getlantern/flashlight/v7 v7.6.112-0.20240929144745-72a54c5a4e73/go.mod h1:M7KG4/LELzZkk6FiFxucmk0rirlQwD785Y0ee5RyiOM= github.com/getlantern/framed v0.0.0-20190601192238-ceb6431eeede h1:yrU6Px3ZkvCsDLPryPGi6FN+2iqFPq+JeCb7EFoDBhw= github.com/getlantern/framed v0.0.0-20190601192238-ceb6431eeede/go.mod h1:nhnoiS6DE6zfe+BaCMU4YI01UpsuiXnDqM5S8jxHuuI= github.com/getlantern/fronted v0.0.0-20240822220559-6e97652d23cc h1:rVEoCLKM16Pfnz8CguT4U75m6o0QDN7stP+MBFUkmNk= From 303c26e66f391bdab79ac3ba677c12efb9437de4 Mon Sep 17 00:00:00 2001 From: Harry Harpham Date: Sun, 29 Sep 2024 08:52:53 -0600 Subject: [PATCH 2/6] Update auth client to use df.iantem.io always --- desktop/lib.go | 5 +++-- internalsdk/auth/auth.go | 22 ++++------------------ internalsdk/common/const.go | 5 +++-- internalsdk/session_model.go | 6 +----- 4 files changed, 11 insertions(+), 27 deletions(-) diff --git a/desktop/lib.go b/desktop/lib.go index 384ecb17d..29f069c01 100644 --- a/desktop/lib.go +++ b/desktop/lib.go @@ -13,6 +13,8 @@ import ( "strings" "time" + "github.com/joho/godotenv" + "github.com/getlantern/appdir" "github.com/getlantern/errors" "github.com/getlantern/flashlight/v7" @@ -31,7 +33,6 @@ import ( "github.com/getlantern/lantern-client/internalsdk/protos" "github.com/getlantern/lantern-client/internalsdk/webclient" "github.com/getlantern/osversion" - "github.com/joho/godotenv" ) import "C" @@ -70,7 +71,7 @@ func init() { proClient = proclient.NewClient(fmt.Sprintf("https://%s", common.ProAPIHost), &webclient.Opts{ UserConfig: userConfig, }) - authClient = auth.NewClient(fmt.Sprintf("https://%s", common.DFBaseUrl), userConfig) + authClient = auth.NewClient(fmt.Sprintf("https://%s", common.APIBaseURL), userConfig) a = app.NewApp(flags, cdir, proClient, ss) } diff --git a/internalsdk/auth/auth.go b/internalsdk/auth/auth.go index 69b7c6ae9..10e36e9e8 100644 --- a/internalsdk/auth/auth.go +++ b/internalsdk/auth/auth.go @@ -2,16 +2,14 @@ package auth import ( "context" + "time" - "fmt" "net/http" "strings" - "time" "github.com/getlantern/flashlight/v7/proxied" "github.com/getlantern/golog" "github.com/getlantern/lantern-client/internalsdk/common" - "github.com/getlantern/lantern-client/internalsdk/pro" "github.com/getlantern/lantern-client/internalsdk/protos" "github.com/getlantern/lantern-client/internalsdk/webclient" @@ -52,21 +50,9 @@ type AuthClient interface { // NewClient creates a new instance of AuthClient func NewClient(baseURL string, userConfig func() common.UserConfig) AuthClient { - // The default http.RoundTripper is ChainedNonPersistent which proxies requests through chained servers - // and does not use keep alive connections. Since no root CA is specified, we do not need to check for an error. - - var httpClient *http.Client - - if baseURL == fmt.Sprintf("https://%s", common.APIBaseUrl) { - log.Debug("using proxied.Fronted") - //this is ios version - httpClient = &http.Client{ - Transport: proxied.Fronted(30 * time.Second), - } - } else { - log.Debug("using proxied.ChainedNonPersistent") - rt, _ := proxied.ChainedNonPersistent("") - httpClient = pro.NewHTTPClient(rt, 30*time.Second) + httpClient := &http.Client{ + Transport: proxied.ChainedThenFronted(), + Timeout: 30 * time.Second, } rc := webclient.NewRESTClient(&webclient.Opts{ diff --git a/internalsdk/common/const.go b/internalsdk/common/const.go index 7bed11d4b..f817d9b64 100644 --- a/internalsdk/common/const.go +++ b/internalsdk/common/const.go @@ -42,8 +42,9 @@ var ( ProAPIHost = "api.getiantem.org" - DFBaseUrl = "df.iantem.io/api/v1" - APIBaseUrl = "iantem.io/api/v1" + // APIBaseURL is the URL for all requests to the back-end "API service". Paths at this URL can + // be hit directly, through proxies, or through domain fronting. + APIBaseURL = "df.iantem.io/api/v1" log = golog.LoggerFor("flashlight.common") diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index a6f7f912c..12ba838f9 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -182,11 +182,7 @@ func NewSessionModel(mdb minisql.DB, opts *SessionModelOpts) (*SessionModel, err } m.proClient = pro.NewClient(fmt.Sprintf("https://%s", common.ProAPIHost), webclientOpts) - authUrl := common.DFBaseUrl - if opts.Platform == "ios" { - authUrl = common.APIBaseUrl - } - m.authClient = auth.NewClient(fmt.Sprintf("https://%s", authUrl), webclientOpts.UserConfig) + m.authClient = auth.NewClient(common.APIBaseURL, webclientOpts.UserConfig) m.baseModel.doInvokeMethod = m.doInvokeMethod if opts.Platform == "ios" { From b27dae4a912410cf2f92a39f78d4455636b15953 Mon Sep 17 00:00:00 2001 From: Harry Harpham Date: Sun, 29 Sep 2024 09:18:54 -0600 Subject: [PATCH 3/6] Use df.iantem.io for pro server requests --- desktop/lib.go | 2 +- internalsdk/common/const.go | 3 ++- internalsdk/pro/pro.go | 15 +++++++++------ internalsdk/pro/proxy.go | 4 ++-- internalsdk/session_model.go | 2 +- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/desktop/lib.go b/desktop/lib.go index 29f069c01..98ef14099 100644 --- a/desktop/lib.go +++ b/desktop/lib.go @@ -68,7 +68,7 @@ func init() { userConfig := func() common.UserConfig { return settings.UserConfig(ss) } - proClient = proclient.NewClient(fmt.Sprintf("https://%s", common.ProAPIHost), &webclient.Opts{ + proClient = proclient.NewClient(common.ProAPIHost, common.ProAPIPath, &webclient.Opts{ UserConfig: userConfig, }) authClient = auth.NewClient(fmt.Sprintf("https://%s", common.APIBaseURL), userConfig) diff --git a/internalsdk/common/const.go b/internalsdk/common/const.go index f817d9b64..69d3bd19a 100644 --- a/internalsdk/common/const.go +++ b/internalsdk/common/const.go @@ -40,7 +40,8 @@ var ( // GlobalStagingURL is the URL for fetching the global config in a staging environment. GlobalStagingURL = "https://globalconfig.flashlightproxy.com/global.yaml.gz" - ProAPIHost = "api.getiantem.org" + ProAPIHost = "df.iantem.io" + ProAPIPath = "/api/pro-server" // APIBaseURL is the URL for all requests to the back-end "API service". Paths at this URL can // be hit directly, through proxies, or through domain fronting. diff --git a/internalsdk/pro/pro.go b/internalsdk/pro/pro.go index 0de1d51da..2e8edbc8b 100644 --- a/internalsdk/pro/pro.go +++ b/internalsdk/pro/pro.go @@ -7,13 +7,14 @@ import ( "net/http" "strings" + "github.com/go-resty/resty/v2" + "github.com/getlantern/errors" "github.com/getlantern/flashlight/v7/proxied" "github.com/getlantern/golog" "github.com/getlantern/lantern-client/internalsdk/common" "github.com/getlantern/lantern-client/internalsdk/protos" "github.com/getlantern/lantern-client/internalsdk/webclient" - "github.com/go-resty/resty/v2" "github.com/leekchan/accounting" "github.com/shopspring/decimal" @@ -55,7 +56,7 @@ type ProClient interface { } // NewClient creates a new instance of ProClient -func NewClient(baseURL string, opts *webclient.Opts) ProClient { +func NewClient(baseHost, basePath string, opts *webclient.Opts) ProClient { if opts.HttpClient == nil { // The default http.RoundTripper used by the ProClient is ParallelForIdempotent which // attempts to send requests through both chained and direct fronted routes in parallel @@ -64,7 +65,7 @@ func NewClient(baseURL string, opts *webclient.Opts) ProClient { } if opts.OnBeforeRequest == nil { opts.OnBeforeRequest = func(client *resty.Client, req *http.Request) error { - prepareProRequest(req, common.ProAPIHost, opts.UserConfig()) + prepareProRequest(req, baseHost, basePath, opts.UserConfig()) return nil } } @@ -74,12 +75,14 @@ func NewClient(baseURL string, opts *webclient.Opts) ProClient { } } -// prepareProRequest normalizes requests to the pro server with device ID, user ID, etc set. -func prepareProRequest(r *http.Request, proAPIHost string, userConfig common.UserConfig) { +// prepareProRequest normalizes requests to the pro server with device ID, user ID, etc set. The +// host is always set to baseHost and basePath is prepended to the request path. +func prepareProRequest(r *http.Request, baseHost, basePath string, userConfig common.UserConfig) { if r.URL.Scheme == "" { r.URL.Scheme = "http" } - r.URL.Host = proAPIHost + r.URL.Host = baseHost + r.URL.Path = basePath + r.URL.Path r.RequestURI = "" // http: Request.RequestURI can't be set in client requests. r.Header.Set("Access-Control-Allow-Headers", strings.Join([]string{ common.DeviceIdHeader, diff --git a/internalsdk/pro/proxy.go b/internalsdk/pro/proxy.go index 61fb3f70c..477da5c29 100644 --- a/internalsdk/pro/proxy.go +++ b/internalsdk/pro/proxy.go @@ -100,7 +100,7 @@ func (pt *proxyTransport) RoundTrip(req *http.Request) (resp *http.Response, err } // APIHandler returns an HTTP handler that specifically looks for and properly handles pro server requests. -func APIHandler(proAPIHost string, userConfig common.UserConfig) http.Handler { +func APIHandler(proAPIHost, proAPIPath string, userConfig common.UserConfig) http.Handler { log.Debugf("Returning pro API handler hitting host: %v", proAPIHost) return &httputil.ReverseProxy{ Transport: &proxyTransport{}, @@ -109,7 +109,7 @@ func APIHandler(proAPIHost string, userConfig common.UserConfig) http.Handler { if strings.HasPrefix(r.URL.Path, "/pro/") { r.URL.Path = r.URL.Path[4:] } - prepareProRequest(r, proAPIHost, userConfig) + prepareProRequest(r, proAPIHost, proAPIPath, userConfig) }, } } diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index 12ba838f9..cce6368db 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -180,7 +180,7 @@ func NewSessionModel(mdb minisql.DB, opts *SessionModelOpts) (*SessionModel, err ) }, } - m.proClient = pro.NewClient(fmt.Sprintf("https://%s", common.ProAPIHost), webclientOpts) + m.proClient = pro.NewClient(common.ProAPIHost, common.ProAPIPath, webclientOpts) m.authClient = auth.NewClient(common.APIBaseURL, webclientOpts.UserConfig) From 1de788298fafce86864481b62e93d6587e34ea0b Mon Sep 17 00:00:00 2001 From: Harry Harpham Date: Sun, 29 Sep 2024 09:29:02 -0600 Subject: [PATCH 4/6] Remove unused APIHandler, no-op HTTPClient --- internalsdk/pro/http.go | 25 ------------------------- internalsdk/pro/pro.go | 13 +++++++++---- internalsdk/pro/proxy.go | 18 +----------------- internalsdk/pro/proxy_test.go | 15 +++++++++++++++ 4 files changed, 25 insertions(+), 46 deletions(-) delete mode 100644 internalsdk/pro/http.go diff --git a/internalsdk/pro/http.go b/internalsdk/pro/http.go deleted file mode 100644 index 738f82abf..000000000 --- a/internalsdk/pro/http.go +++ /dev/null @@ -1,25 +0,0 @@ -package pro - -import ( - "net/http" - "time" - - "github.com/getlantern/flashlight/v7/proxied" -) - -// NewHTTPClient creates a new http.Client that is configured to use the given options and http.RoundTripper wrapped with -// proxied.AsRoundTripper to process requests -func NewHTTPClient(rt http.RoundTripper, timeout time.Duration) *http.Client { - if timeout == 0 { - timeout = 30 * time.Second - } - return &http.Client{ - Transport: proxied.AsRoundTripper( - func(req *http.Request) (*http.Response, error) { - log.Tracef("Pro client processing request to: %v (%v)", req.Host, req.URL.Host) - return rt.RoundTrip(req) - }, - ), - Timeout: timeout, - } -} diff --git a/internalsdk/pro/pro.go b/internalsdk/pro/pro.go index 2e8edbc8b..1278e2356 100644 --- a/internalsdk/pro/pro.go +++ b/internalsdk/pro/pro.go @@ -6,6 +6,7 @@ import ( "fmt" "net/http" "strings" + "time" "github.com/go-resty/resty/v2" @@ -58,11 +59,15 @@ type ProClient interface { // NewClient creates a new instance of ProClient func NewClient(baseHost, basePath string, opts *webclient.Opts) ProClient { if opts.HttpClient == nil { - // The default http.RoundTripper used by the ProClient is ParallelForIdempotent which - // attempts to send requests through both chained and direct fronted routes in parallel - // for HEAD and GET requests and ChainedThenFronted for all others. - opts.HttpClient = NewHTTPClient(proxied.ParallelForIdempotent(), opts.Timeout) + opts.HttpClient = &http.Client{ + // The default http.RoundTripper used by the ProClient is ParallelForIdempotent which + // attempts to send requests through both chained and direct fronted routes in parallel + // for HEAD and GET requests and ChainedThenFronted for all others. + Transport: proxied.ParallelForIdempotent(), + Timeout: 30 * time.Second, + } } + if opts.OnBeforeRequest == nil { opts.OnBeforeRequest = func(client *resty.Client, req *http.Request) error { prepareProRequest(req, baseHost, basePath, opts.UserConfig()) diff --git a/internalsdk/pro/proxy.go b/internalsdk/pro/proxy.go index 477da5c29..2271b390e 100644 --- a/internalsdk/pro/proxy.go +++ b/internalsdk/pro/proxy.go @@ -7,7 +7,6 @@ import ( "io" "io/ioutil" "net/http" - "net/http/httputil" "strconv" "strings" "time" @@ -45,7 +44,7 @@ func (pt *proxyTransport) RoundTrip(req *http.Request) (resp *http.Response, err origin := req.Header.Get("Origin") // Workaround for https://github.com/getlantern/pro-server/issues/192 req.Header.Del("Origin") - resp, err = NewHTTPClient(http.DefaultTransport, time.Duration(time.Second*30)).Do(req) + resp, err = (&http.Client{Timeout: 30 * time.Second}).Do(req) if err != nil { log.Errorf("Could not issue HTTP request? %v", err) return @@ -98,18 +97,3 @@ func (pt *proxyTransport) RoundTrip(req *http.Request) (resp *http.Response, err log.Debugf("Updating user data implicitly for user %v", userID) return } - -// APIHandler returns an HTTP handler that specifically looks for and properly handles pro server requests. -func APIHandler(proAPIHost, proAPIPath string, userConfig common.UserConfig) http.Handler { - log.Debugf("Returning pro API handler hitting host: %v", proAPIHost) - return &httputil.ReverseProxy{ - Transport: &proxyTransport{}, - Director: func(r *http.Request) { - // Strip /pro from path. - if strings.HasPrefix(r.URL.Path, "/pro/") { - r.URL.Path = r.URL.Path[4:] - } - prepareProRequest(r, proAPIHost, proAPIPath, userConfig) - }, - } -} diff --git a/internalsdk/pro/proxy_test.go b/internalsdk/pro/proxy_test.go index 80acdc18a..24addaf0b 100644 --- a/internalsdk/pro/proxy_test.go +++ b/internalsdk/pro/proxy_test.go @@ -62,3 +62,18 @@ package pro // assert.Equal(t, 200, resp.StatusCode, "should respond 200 ok") // } // } + +// // APIHandler returns an HTTP handler that specifically looks for and properly handles pro server requests. +// func APIHandler(proAPIHost, proAPIPath string, userConfig common.UserConfig) http.Handler { +// log.Debugf("Returning pro API handler hitting host: %v", proAPIHost) +// return &httputil.ReverseProxy{ +// Transport: &proxyTransport{}, +// Director: func(r *http.Request) { +// // Strip /pro from path. +// if strings.HasPrefix(r.URL.Path, "/pro/") { +// r.URL.Path = r.URL.Path[4:] +// } +// prepareProRequest(r, proAPIHost, proAPIPath, userConfig) +// }, +// } +// } From 06e19340da8803c41eb29d68599c89690c090f6e Mon Sep 17 00:00:00 2001 From: Harry Harpham Date: Sun, 29 Sep 2024 09:29:42 -0600 Subject: [PATCH 5/6] Remove unused proxyTransport --- internalsdk/pro/proxy.go | 99 ----------------------------------- internalsdk/pro/proxy_test.go | 79 ---------------------------- 2 files changed, 178 deletions(-) delete mode 100644 internalsdk/pro/proxy.go delete mode 100644 internalsdk/pro/proxy_test.go diff --git a/internalsdk/pro/proxy.go b/internalsdk/pro/proxy.go deleted file mode 100644 index 2271b390e..000000000 --- a/internalsdk/pro/proxy.go +++ /dev/null @@ -1,99 +0,0 @@ -package pro - -import ( - "bytes" - "compress/gzip" - "encoding/json" - "io" - "io/ioutil" - "net/http" - "strconv" - "strings" - "time" - - "github.com/getlantern/lantern-client/internalsdk/common" - "github.com/getlantern/lantern-client/internalsdk/protos" -) - -type proxyTransport struct { - // Satisfies http.RoundTripper -} - -func (pt *proxyTransport) processOptions(req *http.Request) *http.Response { - resp := &http.Response{ - StatusCode: http.StatusOK, - Header: http.Header{ - "Connection": {"keep-alive"}, - "Via": {"Lantern Client"}, - }, - Body: ioutil.NopCloser(strings.NewReader("preflight complete")), - } - if !common.ProcessCORS(resp.Header, req) { - return &http.Response{ - StatusCode: http.StatusForbidden, - } - } - return resp -} - -func (pt *proxyTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) { - if req.Method == "OPTIONS" { - // No need to proxy the OPTIONS request. - return pt.processOptions(req), nil - } - origin := req.Header.Get("Origin") - // Workaround for https://github.com/getlantern/pro-server/issues/192 - req.Header.Del("Origin") - resp, err = (&http.Client{Timeout: 30 * time.Second}).Do(req) - if err != nil { - log.Errorf("Could not issue HTTP request? %v", err) - return - } - - // Put the header back for subsequent CORS processing. - req.Header.Set("Origin", origin) - common.ProcessCORS(resp.Header, req) - if req.URL.Path != "/user-data" || resp.StatusCode != http.StatusOK { - return - } - // Try to update user data implicitly - _userID := req.Header.Get("X-Lantern-User-Id") - if _userID == "" { - log.Error("Request has an empty user ID") - return - } - userID, parseErr := strconv.ParseInt(_userID, 10, 64) - if parseErr != nil { - log.Errorf("User ID %s is invalid", _userID) - return - } - body, readErr := ioutil.ReadAll(resp.Body) - if readErr != nil { - log.Errorf("Error read response body: %v", readErr) - return - } - resp.Body = ioutil.NopCloser(bytes.NewReader(body)) - encoding := resp.Header.Get("Content-Encoding") - var br io.Reader = bytes.NewReader(body) - switch encoding { - case "gzip": - gzr, readErr := gzip.NewReader(bytes.NewReader(body)) - if readErr != nil { - log.Errorf("Unable to decode gzipped data: %v", readErr) - return - } - br = gzr - case "": - default: - log.Errorf("Unsupported response encoding %s", encoding) - return - } - user := protos.User{} - readErr = json.NewDecoder(br).Decode(&user) - if readErr != nil { - log.Errorf("Error decoding JSON: %v", readErr) - return - } - log.Debugf("Updating user data implicitly for user %v", userID) - return -} diff --git a/internalsdk/pro/proxy_test.go b/internalsdk/pro/proxy_test.go deleted file mode 100644 index 24addaf0b..000000000 --- a/internalsdk/pro/proxy_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package pro - -// func TestProxy(t *testing.T) { -// uc := common.NewUserConfigData(common.DefaultAppName, "device", 0, "token", nil, "en-US") -// m := &testutils.MockRoundTripper{Header: http.Header{}, Body: strings.NewReader("GOOD")} -// // httpClient := &http.Client{Transport: m} -// l, err := net.Listen("tcp", "localhost:0") -// if !assert.NoError(t, err) { -// return -// } - -// addr := l.Addr() -// url := fmt.Sprintf("http://%s/pro/abc", addr) -// t.Logf("Test server listening at %s", url) -// go http.Serve(l, APIHandler(addr.String(), uc)) - -// req, err := http.NewRequest("OPTIONS", url, nil) -// if !assert.NoError(t, err) { -// return -// } - -// origin := "http://localhost:48933" -// req.Header.Set("Origin", origin) -// resp, err := (&http.Client{}).Do(req) -// if assert.NoError(t, err, "OPTIONS request should succeed") { -// assert.Equal(t, 200, resp.StatusCode, "should respond 200 to OPTIONS") -// assert.Equal(t, origin, resp.Header.Get("Access-Control-Allow-Origin"), "should respond with correct header") -// _ = resp.Body.Close() -// } -// assert.Nil(t, m.Req, "should not pass the OPTIONS request to origin server") - -// req, err = http.NewRequest("GET", url, nil) -// if !assert.NoError(t, err) { -// return -// } -// req.Header.Set("Origin", origin) -// resp, err = (&http.Client{}).Do(req) -// if assert.NoError(t, err, "GET request should have no error") { -// assert.Equal(t, 200, resp.StatusCode, "should respond 200 ok") -// assert.Equal(t, origin, resp.Header.Get("Access-Control-Allow-Origin"), "should respond with correct header") -// assert.NotEmpty(t, resp.Header.Get("Access-Control-Allow-Methods"), "should respond with correct header") -// msg, _ := ioutil.ReadAll(resp.Body) -// _ = resp.Body.Close() -// assert.Equal(t, "GOOD", string(msg), "should respond expected body") -// } -// if assert.NotNil(t, m.Req, "should pass through non-OPTIONS requests to origin server") { -// t.Log(m.Req) -// assert.Equal(t, origin, resp.Header.Get("Access-Control-Allow-Origin"), "should respond with correct header") -// assert.NotEmpty(t, resp.Header.Get("Access-Control-Allow-Methods"), "should respond with correct header") -// } - -// url = fmt.Sprintf("http://%s/pro/user-data", addr) -// msg, _ := json.Marshal(&protos.User{Email: "a@a.com"}) -// m.Body = bytes.NewReader(msg) -// req, err = http.NewRequest("GET", url, nil) -// if !assert.NoError(t, err) { -// return -// } -// req.Header.Set("X-Lantern-User-Id", "1234") -// resp, err = (&http.Client{}).Do(req) -// if assert.NoError(t, err, "GET request should have no error") { -// assert.Equal(t, 200, resp.StatusCode, "should respond 200 ok") -// } -// } - -// // APIHandler returns an HTTP handler that specifically looks for and properly handles pro server requests. -// func APIHandler(proAPIHost, proAPIPath string, userConfig common.UserConfig) http.Handler { -// log.Debugf("Returning pro API handler hitting host: %v", proAPIHost) -// return &httputil.ReverseProxy{ -// Transport: &proxyTransport{}, -// Director: func(r *http.Request) { -// // Strip /pro from path. -// if strings.HasPrefix(r.URL.Path, "/pro/") { -// r.URL.Path = r.URL.Path[4:] -// } -// prepareProRequest(r, proAPIHost, proAPIPath, userConfig) -// }, -// } -// } From 93d38a057a6a16f15da1b1efe952a40ac84cb6ee Mon Sep 17 00:00:00 2001 From: Harry Harpham Date: Sun, 29 Sep 2024 09:36:11 -0600 Subject: [PATCH 6/6] Specify pro server via URL rather than separate host and path --- desktop/app/integration_test.go | 3 +-- desktop/lib.go | 2 +- internalsdk/common/const.go | 12 ++++++------ internalsdk/pro/pro.go | 16 +++++++++------- internalsdk/pro/pro_test.go | 2 +- internalsdk/session_model.go | 2 +- 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/desktop/app/integration_test.go b/desktop/app/integration_test.go index 6f33ae715..b156de5e5 100644 --- a/desktop/app/integration_test.go +++ b/desktop/app/integration_test.go @@ -6,7 +6,6 @@ package app import ( "context" "crypto/tls" - "fmt" "io/ioutil" "net/http" "net/url" @@ -200,7 +199,7 @@ func startApp(t *testing.T, helper *integrationtest.Helper) (*App, error) { return settings.UserConfig(ss) }, } - proClient := pro.NewClient(fmt.Sprintf("https://%s", common.ProAPIHost), webclientOpts) + proClient := pro.NewClient(ProAPIBaseURL, webclientOpts) a := NewApp(flags, helper.ConfigDir, proClient, ss) id := ss.GetUserID() diff --git a/desktop/lib.go b/desktop/lib.go index 98ef14099..b0998aefa 100644 --- a/desktop/lib.go +++ b/desktop/lib.go @@ -68,7 +68,7 @@ func init() { userConfig := func() common.UserConfig { return settings.UserConfig(ss) } - proClient = proclient.NewClient(common.ProAPIHost, common.ProAPIPath, &webclient.Opts{ + proClient = proclient.NewClient(common.ProAPIBaseURL, &webclient.Opts{ UserConfig: userConfig, }) authClient = auth.NewClient(fmt.Sprintf("https://%s", common.APIBaseURL), userConfig) diff --git a/internalsdk/common/const.go b/internalsdk/common/const.go index 69d3bd19a..ee0ea2a12 100644 --- a/internalsdk/common/const.go +++ b/internalsdk/common/const.go @@ -40,11 +40,14 @@ var ( // GlobalStagingURL is the URL for fetching the global config in a staging environment. GlobalStagingURL = "https://globalconfig.flashlightproxy.com/global.yaml.gz" - ProAPIHost = "df.iantem.io" - ProAPIPath = "/api/pro-server" + // ProAPIBaseURL is the URL for all requests to the back-end pro server. Paths at this URL can + // be hit directly (not recommended due to censorship), through proxies, or through domain + // fronting. + ProAPIBaseURL = "df.iantem.io/api/pro-server" // APIBaseURL is the URL for all requests to the back-end "API service". Paths at this URL can - // be hit directly, through proxies, or through domain fronting. + // be hit directly (not recommended due to censorship), through proxies, or through domain + // fronting. APIBaseURL = "df.iantem.io/api/v1" log = golog.LoggerFor("flashlight.common") @@ -65,9 +68,6 @@ func ForceStaging() { func initInternal() { isStaging := IsStagingEnvironment() log.Debugf("****************************** stagingMode: %v", isStaging) - if isStaging { - ProAPIHost = "api-staging.getiantem.org" - } forceAds, _ = strconv.ParseBool(os.Getenv("FORCEADS")) } diff --git a/internalsdk/pro/pro.go b/internalsdk/pro/pro.go index 1278e2356..6a2d4f1e3 100644 --- a/internalsdk/pro/pro.go +++ b/internalsdk/pro/pro.go @@ -57,7 +57,7 @@ type ProClient interface { } // NewClient creates a new instance of ProClient -func NewClient(baseHost, basePath string, opts *webclient.Opts) ProClient { +func NewClient(baseURL string, opts *webclient.Opts) ProClient { if opts.HttpClient == nil { opts.HttpClient = &http.Client{ // The default http.RoundTripper used by the ProClient is ParallelForIdempotent which @@ -70,24 +70,26 @@ func NewClient(baseHost, basePath string, opts *webclient.Opts) ProClient { if opts.OnBeforeRequest == nil { opts.OnBeforeRequest = func(client *resty.Client, req *http.Request) error { - prepareProRequest(req, baseHost, basePath, opts.UserConfig()) + prepareProRequest(req, opts.UserConfig()) return nil } } + + if opts.BaseURL == "" { + opts.BaseURL = baseURL + } + return &proClient{ userConfig: opts.UserConfig, RESTClient: webclient.NewRESTClient(opts), } } -// prepareProRequest normalizes requests to the pro server with device ID, user ID, etc set. The -// host is always set to baseHost and basePath is prepended to the request path. -func prepareProRequest(r *http.Request, baseHost, basePath string, userConfig common.UserConfig) { +// prepareProRequest normalizes requests to the pro server with device ID, user ID, etc set. +func prepareProRequest(r *http.Request, userConfig common.UserConfig) { if r.URL.Scheme == "" { r.URL.Scheme = "http" } - r.URL.Host = baseHost - r.URL.Path = basePath + r.URL.Path r.RequestURI = "" // http: Request.RequestURI can't be set in client requests. r.Header.Set("Access-Control-Allow-Headers", strings.Join([]string{ common.DeviceIdHeader, diff --git a/internalsdk/pro/pro_test.go b/internalsdk/pro/pro_test.go index e7ea13f95..9a9890b20 100644 --- a/internalsdk/pro/pro_test.go +++ b/internalsdk/pro/pro_test.go @@ -26,7 +26,7 @@ package pro // }, // } -// proClient := NewClient(fmt.Sprintf("https://%s", common.ProAPIHost), webclientOpts) +// proClient := NewClient(common.ProAPIBaseURL, webclientOpts) // puchaseData := map[string]interface{}{ // "idempotencyKey": strconv.FormatInt(time.Now().UnixNano(), 10), diff --git a/internalsdk/session_model.go b/internalsdk/session_model.go index cce6368db..3701eb821 100644 --- a/internalsdk/session_model.go +++ b/internalsdk/session_model.go @@ -180,7 +180,7 @@ func NewSessionModel(mdb minisql.DB, opts *SessionModelOpts) (*SessionModel, err ) }, } - m.proClient = pro.NewClient(common.ProAPIHost, common.ProAPIPath, webclientOpts) + m.proClient = pro.NewClient(common.ProAPIBaseURL, webclientOpts) m.authClient = auth.NewClient(common.APIBaseURL, webclientOpts.UserConfig)