Skip to content
52 changes: 42 additions & 10 deletions cmd/claws/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ import (
var version = "dev"

func main() {
// Parse command line flags
opts := parseFlags()

propagateAllProxy()

// Apply CLI options to global config
cfg := config.Global()

Expand Down Expand Up @@ -102,30 +103,29 @@ func parseFlags() cliOptions {

args := os.Args[1:]
for i := 0; i < len(args); i++ {
arg := args[i]
switch {
case arg == "-p" || arg == "--profile":
switch args[i] {
case "-p", "--profile":
if i+1 < len(args) {
i++
opts.profile = args[i]
}
case arg == "-r" || arg == "--region":
case "-r", "--region":
if i+1 < len(args) {
i++
opts.region = args[i]
}
case arg == "-ro" || arg == "--read-only":
case "-ro", "--read-only":
opts.readOnly = true
case arg == "-e" || arg == "--env":
case "-e", "--env":
opts.envCreds = true
case arg == "-l" || arg == "--log-file":
case "-l", "--log-file":
if i+1 < len(args) {
i++
opts.logFile = args[i]
}
case arg == "-h" || arg == "--help":
case "-h", "--help":
showHelp = true
case arg == "-v" || arg == "--version":
case "-v", "--version":
showVersion = true
}
}
Expand Down Expand Up @@ -167,4 +167,36 @@ func printUsage() {
fmt.Println()
fmt.Println("Environment Variables:")
fmt.Println(" CLAWS_READ_ONLY=1|true Enable read-only mode")
fmt.Println(" ALL_PROXY Propagated to HTTP_PROXY/HTTPS_PROXY if not set")
}

// propagateAllProxy copies ALL_PROXY to HTTP_PROXY/HTTPS_PROXY if not set.
// Go's net/http ignores ALL_PROXY, so we propagate it to the standard vars.
func propagateAllProxy() {
allProxy := os.Getenv("ALL_PROXY")
if allProxy == "" {
return
}

var propagated []string

if os.Getenv("HTTPS_PROXY") == "" {
if err := os.Setenv("HTTPS_PROXY", allProxy); err != nil {
log.Warn("failed to set HTTPS_PROXY", "error", err)
} else {
propagated = append(propagated, "HTTPS_PROXY")
}
}

if os.Getenv("HTTP_PROXY") == "" {
if err := os.Setenv("HTTP_PROXY", allProxy); err != nil {
log.Warn("failed to set HTTP_PROXY", "error", err)
} else {
propagated = append(propagated, "HTTP_PROXY")
}
}

if len(propagated) > 0 {
log.Debug("propagated ALL_PROXY", "to", propagated)
}
}
94 changes: 94 additions & 0 deletions cmd/claws/proxy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package main

import (
"os"
"testing"
)

func TestPropagateAllProxy(t *testing.T) {
// Note: Only uppercase ALL_PROXY is supported.
// Lowercase all_proxy is intentionally not supported to match
// the AWS SDK behavior and keep the implementation simple.
// Go's net/http.ProxyFromEnvironment also only checks uppercase
// for HTTP_PROXY and HTTPS_PROXY on non-CGI environments.

proxyVars := []string{
"ALL_PROXY",
"HTTP_PROXY",
"HTTPS_PROXY",
}

tests := []struct {
name string
envVars map[string]string
wantHTTPS string
wantHTTP string
}{
{
name: "ALL_PROXY propagates to both HTTP and HTTPS",
envVars: map[string]string{"ALL_PROXY": "socks5h://proxy:1080"},
wantHTTPS: "socks5h://proxy:1080",
wantHTTP: "socks5h://proxy:1080",
},
{
name: "HTTPS_PROXY already set - only HTTP propagated",
envVars: map[string]string{"ALL_PROXY": "http://all", "HTTPS_PROXY": "http://existing"},
wantHTTPS: "http://existing",
wantHTTP: "http://all",
},
{
name: "HTTP_PROXY already set - only HTTPS propagated",
envVars: map[string]string{"ALL_PROXY": "http://all", "HTTP_PROXY": "http://existing"},
wantHTTPS: "http://all",
wantHTTP: "http://existing",
},
{
name: "both already set - no propagation",
envVars: map[string]string{"ALL_PROXY": "http://all", "HTTP_PROXY": "http://h", "HTTPS_PROXY": "http://s"},
wantHTTPS: "http://s",
wantHTTP: "http://h",
},
{
name: "no ALL_PROXY - no action",
envVars: map[string]string{},
wantHTTPS: "",
wantHTTP: "",
},
{
name: "lowercase all_proxy not supported",
envVars: map[string]string{"all_proxy": "http://proxy:8080"},
wantHTTPS: "",
wantHTTP: "",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
clearEnvVars(t, proxyVars)
setEnvVars(t, tt.envVars)

propagateAllProxy()

if got := os.Getenv("HTTPS_PROXY"); got != tt.wantHTTPS {
t.Errorf("HTTPS_PROXY = %q, want %q", got, tt.wantHTTPS)
}
if got := os.Getenv("HTTP_PROXY"); got != tt.wantHTTP {
t.Errorf("HTTP_PROXY = %q, want %q", got, tt.wantHTTP)
}
})
}
}

func clearEnvVars(t *testing.T, keys []string) {
t.Helper()
for _, key := range keys {
os.Unsetenv(key)
}
}

func setEnvVars(t *testing.T, vars map[string]string) {
t.Helper()
for key, value := range vars {
t.Setenv(key, value)
}
}