Golang中如何发现系统代理设置

Golang中如何发现系统代理设置 我是Go语言的新手,正在考虑用Go重写一些我之前用Python编写的跨平台应用程序(支持Win/MacOS/Linux)的代码,这样我就可以使用相同的代码库为移动设备进行编译。我认为大部分功能我都能相当容易地复现,但有一个关键特性是自动发现宿主系统的代理设置。在Python中,我使用了urllib2.getproxies(),如果没有设置,我会查找并解析WPAD文件。

我找不到的是在Go中是否有任何方法可以查看宿主系统是否设置了任何代理。这与设置/读取http_proxy/https_proxy环境变量不同——它指的是读取操作系统特定的系统偏好设置的能力。

这能做到吗?


更多关于Golang中如何发现系统代理设置的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

非常感谢——这看起来太棒了!你知道它在安卓和iOS上也能用吗?

更多关于Golang中如何发现系统代理设置的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


现在我有机会更仔细地研究这个问题,发现存在一个问题。该方法在所有操作系统上都能获取系统代理,但如果代理是通过WPAD设置的,那么这仅在Windows上有效。我可以获取wpad.dat文件本身,但找不到它的解析器——具体来说,我需要确定wpad文件中可能定义的多个代理中,哪一个用于特定的URL。在Python中有一个pacparser脚本可以做到这一点。有谁知道是否有人用Go编写了类似的东西?

或许可以看看这个:

GitHub GitHub

Avatar

rapid7/go-get-proxied

跨平台获取系统代理配置 - rapid7/go-get-proxied

在Go中,可以通过golang.org/x/net/http/httpproxy包的FromEnvironment函数来获取系统代理设置。这个函数会检查环境变量(如HTTP_PROXYHTTPS_PROXYNO_PROXY),但不会直接读取操作系统级别的代理配置。

对于跨平台的系统代理发现,目前Go标准库没有提供直接的方法。不过,你可以通过调用系统命令或使用第三方库来实现。以下是一个示例,展示如何在Windows、macOS和Linux上获取系统代理设置:

package main

import (
    "fmt"
    "os/exec"
    "runtime"
    "strings"
)

func getSystemProxy() (string, error) {
    switch runtime.GOOS {
    case "windows":
        // 使用reg命令查询Windows注册表
        cmd := exec.Command("reg", "query", "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "/v", "ProxyServer")
        output, err := cmd.Output()
        if err != nil {
            return "", err
        }
        lines := strings.Split(string(output), "\n")
        for _, line := range lines {
            if strings.Contains(line, "ProxyServer") {
                parts := strings.Fields(line)
                if len(parts) >= 3 {
                    return parts[2], nil
                }
            }
        }
    case "darwin":
        // 使用networksetup命令获取macOS代理设置
        cmd := exec.Command("networksetup", "-getwebproxy", "Wi-Fi")
        output, err := cmd.Output()
        if err != nil {
            return "", err
        }
        lines := strings.Split(string(output), "\n")
        for _, line := range lines {
            if strings.Contains(line, "Server") {
                parts := strings.Fields(line)
                if len(parts) >= 2 {
                    return parts[1], nil
                }
            }
        }
    case "linux":
        // 检查gsettings(GNOME)或kwriteconfig(KDE)等Linux桌面环境设置
        // 这里以gsettings为例
        cmd := exec.Command("gsettings", "get", "org.gnome.system.proxy", "http", "host")
        output, err := cmd.Output()
        if err == nil {
            host := strings.Trim(string(output), "' \n")
            if host != "" {
                cmd := exec.Command("gsettings", "get", "org.gnome.system.proxy", "http", "port")
                portOutput, err := cmd.Output()
                if err == nil {
                    port := strings.Trim(string(portOutput), "' \n")
                    return fmt.Sprintf("%s:%s", host, port), nil
                }
            }
        }
    }
    return "", nil
}

func main() {
    proxy, err := getSystemProxy()
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    if proxy != "" {
        fmt.Printf("System proxy: %s\n", proxy)
    } else {
        fmt.Println("No system proxy found")
    }
}

这个示例代码通过执行系统命令来查询各操作系统的代理设置。在Windows上,它查询注册表;在macOS上,使用networksetup命令;在Linux上,尝试使用gsettings获取GNOME桌面环境的代理设置。

需要注意的是,这种方法依赖于系统命令,可能无法覆盖所有情况(例如不同的Linux桌面环境)。对于更全面的解决方案,可以考虑使用第三方库,如github.com/elazarl/goproxygithub.com/mattn/go-ieproxy(专门针对Windows)。

回到顶部