让curl支持PAC自动代理

601 阅读1分钟

在MacOS或者Linux中使用命令行进行一些操作或者执行一些脚本当用到curl命令时会经常出现这样的一些问题:

  • 有部分链接需要使用代理才能访问到
  • 如果设置了代理则很多不需要代理的链接访问速度会变得很慢
  • 代理是按照流量收费的、不希望那些不需要代理的链接走代理通道

在系统代理中一般可以通过设置 PAC(Proxy auto-config) 脚本实现系统自动判断网络链接是否需要走代理,但是在命令行中由于curl没有JavaScript功能,因此curl不支持PAC实现自动代理。

原生curl虽然不支持pac,但是我们可以通过编写自定义脚本替代curl命令使得curl支持PAC功能。

在进行命令替换操作之前先安装 quickjs :

# homebrebrew 
brew install quickjs
# Ubuntu 原生使用
# apt install quickjs
# 其他系统按各自方法安装

具体替换用的curl实现代码如下:

#!/bin/bash

# 优先使用 PAC_PATH
PAC_PATH=~/.hosts/pac.loc/pac.js
PAC_URL=http://127.0.0.1/pac.js

CURL_BINARY_PATH=/usr/local/opt/curl/bin/curl
QJS_BINARY_PATH=/usr/local/bin/qjs

# main

REQUEST_URI=""
SKIP_NEXT=false
ARGS=""
for arg in "$@"; do
  ARGS="$ARGS $(sed -r 's:([() ;&~?]):\\\1:g' <<< "$arg")"
  if [[ $SKIP_NEXT == true ]]; then
    SKIP_NEXT=false
  else
    if [[ $arg =~ ^https?:// ]]; then
      REQUEST_URI="$arg"
    fi
  fi

  if [[ $arg == "--proxy" || $arg == "-x" ]]; then
    SKIP_NEXT=true
  fi
done

if [ "$REQUEST_URI" == "" ]; then
  sh -c "$CURL_BINARY_PATH $ARGS"
else
  SCRIPT="
    $([ "$PAC_PATH" == "" ] && $CURL_BINARY_PATH -s $PAC_URL || cat "$PAC_PATH")
    const args = '$REQUEST_URI'.match(/^[a-zA-Z]+:\/\/([^/]+)/);
    const proxy = FindProxyForURL(...args);
    if(proxy !== 'DIRECT') {
      const [proto,host] = proxy.split(/[ ;]+/);
      if(proto === 'SOCKS5') {
        console.log('--proxy socks5h://' + host);
      }
      if(proto === 'PROXY') {
        console.log('--proxy ' + host);
      }
    }
  "
  PROXY="$($QJS_BINARY_PATH -e "$SCRIPT")"
  sh -c "$CURL_BINARY_PATH $PROXY $ARGS"
fi

将以上代码保存为 ~/.curl_with_pac.sh 并添加执行权限 chmod +x ~/.curl_with_pac.sh 。

然后编辑 ~/.zshrc 文件新增如下配置: (根据终端类型自己选择配置文件)

alias curl='~/.curl_with_pac.sh'

原文链接: 让curl支持PAC自动代理 – qnnp⁶