Repository: samuong/alpaca (go)

Issue:
Feature request: Direct mode
Hi!
Thanks for this great project!

It would be nice to have the feature to start alpaca in a mode where all requests are routed as "direct". This way I could always keep the proxy configured and start alpaca with this flag when I'm connected to a network without a proxy.

Pull request:
Remove dodgy connection check
This behaviour worked well on some corporate networks, but breaks on others. From now on, users who use a custom PAC file with a file:// URL will need to do this check themselves, before returning a PROXY directive.

Fixes #106 

Patch:
diff --git a/README.md b/README.md
index e134a60..4117a53 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,10 @@ $ go get -v -u github.com/samuong/alpaca
 
 Alpaca can be downloaded from the [GitHub releases page][1].
 
+## Install from distribution packages
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/alpaca-proxy.svg)](https://repology.org/project/alpaca-proxy/versions)
+
 ## Usage
 
 Start Alpaca by running the `alpaca` binary.
@@ -88,5 +92,5 @@ Once you've set this environment variable, you can start Alpaca by running
 
 [1]: https://github.com/samuong/alpaca/releases
 [2]: https://img.shields.io/github/v/tag/samuong/alpaca.svg?logo=github&label=latest
-[3]: https://img.shields.io/github/workflow/status/samuong/alpaca/Continuous%20Integration/master
+[3]: https://img.shields.io/github/actions/workflow/status/samuong/alpaca/ci.yml?branch=master
 [4]: https://img.shields.io/github/downloads/samuong/alpaca/latest/total
diff --git a/pacfetcher.go b/pacfetcher.go
index 6708c5f..4162e74 100644
--- a/pacfetcher.go
+++ b/pacfetcher.go
@@ -16,11 +16,9 @@ package main
 
 import (
 	"bytes"
-	"context"
 	"fmt"
 	"io"
 	"log"
-	"net"
 	"net/http"
 	"runtime"
 	"strings"
@@ -38,7 +36,6 @@ type pacFetcher struct {
 	pacFinder  *pacFinder
 	monitor    netMonitor
 	client     *http.Client
-	lookupAddr func(context.Context, string) ([]string, error)
 	connected  bool
 	//cache  []byte
 	//modified time.Time
@@ -50,7 +47,9 @@ type pacFetcher struct {
 func newPACFetcher(pacurl string) *pacFetcher {
 	client := &http.Client{Timeout: 30 * time.Second}
 	if strings.HasPrefix(pacurl, "file:") {
-		log.Printf("Warning: Alpaca supports file:// PAC URLs, but Windows and macOS don't")
+		log.Print("Warning: When using a local PAC file, the online/offline status can't ",
+			"be determined by the fact that the PAC file is downloaded. Make sure you ",
+			"check for proxy connectivity in your PAC file!")
 		if runtime.GOOS == "windows" {
 			client.Transport = http.NewFileTransport(http.Dir("C:"))
 		} else {
@@ -67,7 +66,6 @@ func newPACFetcher(pacurl string) *pacFetcher {
 		pacFinder:  newPacFinder(pacurl),
 		monitor:    newNetMonitor(),
 		client:     client,
-		lookupAddr: net.DefaultResolver.LookupAddr,
 	}
 }
 
@@ -114,23 +112,7 @@ func (pf *pacFetcher) download() []byte {
 	var buf bytes.Buffer
 	_, err = io.CopyN(&buf, resp.Body, maxResponseBytes)
 	if err == io.EOF {
-		if strings.HasPrefix(pacurl, "file:") {
-			// When using a local PAC file the online/offline status can't be determined
-			// by the fact that the PAC file is returned. Instead try reverse DNS
-			// resolution of Google's Public DNS Servers.
-			const timeout = 2 * time.Second
-			ctx, cancel := context.WithTimeout(context.TODO(), timeout)
-			defer cancel()
-			_, err1 := pf.lookupAddr(ctx, "8.8.8.8")
-			_, err2 := pf.lookupAddr(ctx, "2001:4860:4860::8888")
-			if err1 == nil || err2 == nil {
-				log.Printf("Successfully resolved public address; bypassing proxy")
-			} else {
-				pf.connected = true
-			}
-		} else {
-			pf.connected = true
-		}
+		pf.connected = true
 		return buf.Bytes()
 	} else if err != nil {
 		log.Printf("Error reading PAC JS from response body: %q", err)


Test patch:
diff --git a/pacfetcher_test.go b/pacfetcher_test.go
index 69e2bda..229c1a7 100644
--- a/pacfetcher_test.go
+++ b/pacfetcher_test.go
@@ -15,9 +15,6 @@
 package main
 
 import (
-	"context"
-	"fmt"
-	"net"
 	"net/http"
 	"net/http/httptest"
 	"net/url"
@@ -118,27 +115,6 @@ func TestResponseLimit(t *testing.T) {
 	assert.False(t, pf.isConnected())
 }
 
-type testNetwork struct {
-	connected bool
-}
-
-func (tn testNetwork) InterfaceAddrs() ([]net.Addr, error) {
-	addr := func(s string) *net.IPAddr { return &net.IPAddr{IP: net.ParseIP(s)} }
-	if tn.connected {
-		return []net.Addr{addr("127.0.0.1"), addr("192.0.2.1")}, nil
-	} else {
-		return []net.Addr{addr("127.0.0.1"), addr("198.51.100.1")}, nil
-	}
-}
-
-func (tn testNetwork) LookupAddr(ctx context.Context, addr string) ([]string, error) {
-	if tn.connected {
-		return []string{}, fmt.Errorf("lookup %s: Name or service not known", addr)
-	} else {
-		return []string{"dns.google."}, nil
-	}
-}
-
 func TestPacFromFilesystem(t *testing.T) {
 	// Set up a test PAC file
 	content := []byte(`function FindProxyForURL(url, host) { return "DIRECT" }`)
@@ -148,19 +124,8 @@ func TestPacFromFilesystem(t *testing.T) {
 	pacPath := path.Join(tempdir, "test.pac")
 	require.NoError(t, os.WriteFile(pacPath, content, 0644))
 	pacURL := &url.URL{Scheme: "file", Path: filepath.ToSlash(pacPath)}
-
-	tn := testNetwork{false}
 	pf := newPACFetcher(pacURL.String())
-	pf.monitor = &netMonitorImpl{
-		getAddrs: func() ([]net.Addr, error) { return tn.InterfaceAddrs() },
-	}
-	pf.lookupAddr = func(ctx context.Context, addr string) ([]string, error) {
-		return tn.LookupAddr(ctx, addr)
-	}
-
-	assert.Equal(t, content, pf.download())
-	assert.False(t, pf.isConnected())
-	tn.connected = true
+	pf.monitor = newNetMonitor()
 	assert.Equal(t, content, pf.download())
 	assert.True(t, pf.isConnected())
 }