diff --git a/cmd/common.go b/cmd/common.go index 03db1e74..a03ab436 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "io" + "net/url" "os" "path/filepath" "strings" @@ -24,6 +25,7 @@ import ( var dependencies = Dependencies{} var keychainPassphrase string +var proxyUrl string type Dependencies struct { Logger log.Logger @@ -107,11 +109,21 @@ func initWithCommand(cmd *cobra.Command) { dependencies.Machine = machine.New(machine.Args{OS: dependencies.OS}) dependencies.CookieJar = newCookieJar(dependencies.Machine) dependencies.Keychain = newKeychain(dependencies.Machine, dependencies.Logger, interactive) + var proxyUrlParsed *url.URL + if proxyUrl != "" { + parsedUrl, err := url.Parse(proxyUrl) + if err != nil { + fmt.Fprintf(os.Stderr, "error: invalid proxy url: %v\n", proxyUrl) + os.Exit(1) + } + proxyUrlParsed = parsedUrl + } dependencies.AppStore = appstore.NewAppStore(appstore.Args{ CookieJar: dependencies.CookieJar, OperatingSystem: dependencies.OS, Keychain: dependencies.Keychain, Machine: dependencies.Machine, + ProxyUrl: proxyUrlParsed, }) util.Must("", createConfigDirectory(dependencies.OS, dependencies.Machine)) diff --git a/cmd/root.go b/cmd/root.go index fa746c0f..1ec8452c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -40,6 +40,7 @@ func rootCmd() *cobra.Command { cmd.PersistentFlags().BoolVar(&verbose, "verbose", false, "enables verbose logs") cmd.PersistentFlags().BoolVarP(&nonInteractive, "non-interactive", "", false, "run in non-interactive session") cmd.PersistentFlags().StringVar(&keychainPassphrase, "keychain-passphrase", "", "passphrase for unlocking keychain") + cmd.PersistentFlags().StringVar(&proxyUrl, "proxy", "", "url of a HTTP proxy to be used") cmd.AddCommand(authCmd()) cmd.AddCommand(downloadCmd()) diff --git a/pkg/appstore/appstore.go b/pkg/appstore/appstore.go index f6b15f48..cf867711 100644 --- a/pkg/appstore/appstore.go +++ b/pkg/appstore/appstore.go @@ -1,6 +1,8 @@ package appstore import ( + "net/url" + "github.com/majd/ipatool/v2/pkg/http" "github.com/majd/ipatool/v2/pkg/keychain" "github.com/majd/ipatool/v2/pkg/util/machine" @@ -47,13 +49,14 @@ type Args struct { CookieJar http.CookieJar OperatingSystem operatingsystem.OperatingSystem Machine machine.Machine + ProxyUrl *url.URL } func NewAppStore(args Args) AppStore { clientArgs := http.Args{ CookieJar: args.CookieJar, + ProxyUrl: args.ProxyUrl, } - return &appstore{ keychain: args.Keychain, loginClient: http.NewClient[loginResult](clientArgs), diff --git a/pkg/http/client.go b/pkg/http/client.go index a6369b40..e734167f 100644 --- a/pkg/http/client.go +++ b/pkg/http/client.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net/http" + "net/url" "strings" "howett.net/plist" @@ -29,6 +30,7 @@ type client[R interface{}] struct { type Args struct { CookieJar CookieJar + ProxyUrl *url.URL } type AddHeaderTransport struct { @@ -49,6 +51,12 @@ func (t *AddHeaderTransport) RoundTrip(req *http.Request) (*http.Response, error } func NewClient[R interface{}](args Args) Client[R] { + var proxy http.RoundTripper + if args.ProxyUrl != nil { + proxy = &http.Transport{Proxy: http.ProxyURL(args.ProxyUrl)} + } else { + proxy = http.DefaultTransport + } return &client[R]{ internalClient: http.Client{ Timeout: 0, @@ -60,7 +68,7 @@ func NewClient[R interface{}](args Args) Client[R] { return nil }, - Transport: &AddHeaderTransport{http.DefaultTransport}, + Transport: &AddHeaderTransport{proxy}, }, cookieJar: args.CookieJar, }