Showing preview only (925K chars total). Download the full file or copy to clipboard to get everything.
Repository: docmirror/dev-sidecar
Branch: master
Commit: 5a9fa187a766
Files: 222
Total size: 863.1 KB
Directory structure:
gitextract_p0gsc863/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── 1_BUG_REPORT.md
│ │ ├── 2_STYLE_ISSUE.md
│ │ ├── 3_CONFIG_ISSUES.md
│ │ ├── 4_FEATURE_REQUEST.md
│ │ └── 5_OTHERS.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── build-and-release.yml
│ ├── npm-run-electron.yml
│ └── test-and-upload.yml
├── .gitignore
├── .npmrc
├── LICENSE
├── README.md
├── _script/
│ ├── 0、updateDependencies.bat
│ ├── 1、setupEnv.bat
│ ├── 2、installProject.bat
│ ├── 3、buildAndRun.bat
│ ├── 4.1、runTestCore.bat
│ ├── 4.2、runTestMitmproxy.bat
│ └── 5、generateSetupFile.bat
├── doc/
│ ├── caroot.md
│ ├── linux.md
│ ├── other.md
│ ├── recover.md
│ └── wiki/
│ ├── Home.md
│ ├── 加速服务使用说明.md
│ ├── 各平台安装说明.md
│ └── 解决Github访问不了或速度很慢的问题.md
├── eslint.config.js
├── package.json
├── packages/
│ ├── cli/
│ │ ├── LICENSE
│ │ ├── cli.js
│ │ ├── package.json
│ │ └── src/
│ │ ├── banner.txt
│ │ ├── index.js
│ │ ├── mitmproxy.js
│ │ └── user_config.json5
│ ├── core/
│ │ ├── LICENSE
│ │ ├── index.js
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── config/
│ │ │ │ ├── index.js
│ │ │ │ ├── local-config-loader.js
│ │ │ │ └── remote_config.json5
│ │ │ ├── config-api.js
│ │ │ ├── event.js
│ │ │ ├── expose.js
│ │ │ ├── index.js
│ │ │ ├── merge.js
│ │ │ ├── modules/
│ │ │ │ ├── index.js
│ │ │ │ ├── plugin/
│ │ │ │ │ ├── git/
│ │ │ │ │ │ ├── config.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── node/
│ │ │ │ │ │ ├── config.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── overwall/
│ │ │ │ │ │ ├── config.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── pip/
│ │ │ │ │ ├── config.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── proxy/
│ │ │ │ │ └── index.js
│ │ │ │ └── server/
│ │ │ │ └── index.js
│ │ │ ├── shell/
│ │ │ │ ├── index.js
│ │ │ │ ├── scripts/
│ │ │ │ │ ├── enable-loopback.js
│ │ │ │ │ ├── extra-path/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── get-npm-env.js
│ │ │ │ │ ├── get-system-env.js
│ │ │ │ │ ├── kill-by-port.js
│ │ │ │ │ ├── set-npm-env.js
│ │ │ │ │ ├── set-system-env.js
│ │ │ │ │ ├── set-system-proxy/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── refresh-internet.js
│ │ │ │ │ └── setup-ca.js
│ │ │ │ └── shell.js
│ │ │ ├── status.js
│ │ │ └── utils/
│ │ │ ├── util.date.js
│ │ │ ├── util.log-or-console.js
│ │ │ ├── util.log.core.js
│ │ │ ├── util.logger.js
│ │ │ └── util.version.js
│ │ └── test/
│ │ ├── configTest.js
│ │ ├── httpsVerifyTest.js
│ │ ├── macProxyTest.js
│ │ ├── mergeTest.js
│ │ ├── regex.test.js
│ │ ├── requestTest.js
│ │ └── versionTest.js
│ ├── gui/
│ │ ├── .editorconfig
│ │ ├── .gitignore
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── babel.config.js
│ │ ├── build/
│ │ │ ├── icons/
│ │ │ │ └── icon.icns
│ │ │ └── mac/
│ │ │ └── icon.icns
│ │ ├── extra/
│ │ │ ├── icons/
│ │ │ │ └── icon.icns
│ │ │ ├── pac/
│ │ │ │ └── pac.txt
│ │ │ ├── proxy/
│ │ │ │ └── domestic-domain-allowlist.txt
│ │ │ └── scripts/
│ │ │ ├── github.script
│ │ │ ├── google.js
│ │ │ └── tampermonkey.script
│ │ ├── package.json
│ │ ├── pkg/
│ │ │ ├── after-all-artifact-build.js
│ │ │ └── after-pack.js
│ │ ├── public/
│ │ │ └── index.html
│ │ ├── src/
│ │ │ ├── background/
│ │ │ │ └── powerMonitor.js
│ │ │ ├── background.js
│ │ │ ├── bridge/
│ │ │ │ ├── api/
│ │ │ │ │ ├── backend.js
│ │ │ │ │ └── open-enable-loopback.js
│ │ │ │ ├── auto-start/
│ │ │ │ │ ├── backend.js
│ │ │ │ │ └── front.js
│ │ │ │ ├── backend.js
│ │ │ │ ├── error/
│ │ │ │ │ └── front.js
│ │ │ │ ├── file-selector/
│ │ │ │ │ ├── backend.js
│ │ │ │ │ └── front.js
│ │ │ │ ├── front.js
│ │ │ │ ├── mitmproxy.js
│ │ │ │ ├── on-close/
│ │ │ │ │ └── front.js
│ │ │ │ ├── tongji/
│ │ │ │ │ ├── backend.js
│ │ │ │ │ └── front.js
│ │ │ │ └── update/
│ │ │ │ ├── backend.js
│ │ │ │ └── front.js
│ │ │ ├── main.js
│ │ │ ├── utils/
│ │ │ │ ├── util.apppath.js
│ │ │ │ └── util.log.gui.js
│ │ │ └── view/
│ │ │ ├── App.vue
│ │ │ ├── api.js
│ │ │ ├── components/
│ │ │ │ ├── container.vue
│ │ │ │ ├── mock-input.vue
│ │ │ │ ├── setup-ca.vue
│ │ │ │ └── tree-node.vue
│ │ │ ├── composables/
│ │ │ │ └── theme.js
│ │ │ ├── index.js
│ │ │ ├── mixins/
│ │ │ │ └── plugin.js
│ │ │ ├── pages/
│ │ │ │ ├── help.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── plugin/
│ │ │ │ │ ├── git.vue
│ │ │ │ │ ├── node.vue
│ │ │ │ │ ├── overwall.vue
│ │ │ │ │ └── pip.vue
│ │ │ │ ├── proxy.vue
│ │ │ │ ├── server.vue
│ │ │ │ └── setting.vue
│ │ │ ├── router/
│ │ │ │ ├── index.js
│ │ │ │ └── menu.js
│ │ │ ├── status.js
│ │ │ └── style/
│ │ │ ├── index.scss
│ │ │ └── theme/
│ │ │ └── dark.scss
│ │ └── vue.config.js
│ └── mitmproxy/
│ ├── LICENSE
│ ├── index.js
│ ├── package.json
│ ├── src/
│ │ ├── index.js
│ │ ├── json.js
│ │ ├── lib/
│ │ │ ├── choice/
│ │ │ │ ├── RequestCounter.js
│ │ │ │ └── index.js
│ │ │ ├── dns/
│ │ │ │ ├── base.js
│ │ │ │ ├── https.js
│ │ │ │ ├── index.js
│ │ │ │ ├── preset.js
│ │ │ │ ├── tcp.js
│ │ │ │ ├── tls.js
│ │ │ │ ├── udp.js
│ │ │ │ └── util/
│ │ │ │ └── dns-over-tls.js
│ │ │ ├── interceptor/
│ │ │ │ ├── impl/
│ │ │ │ │ ├── req/
│ │ │ │ │ │ ├── OPTIONS.js
│ │ │ │ │ │ ├── abort.js
│ │ │ │ │ │ ├── baiduOcr.js
│ │ │ │ │ │ ├── cacheRequest.js
│ │ │ │ │ │ ├── proxy.js
│ │ │ │ │ │ ├── redirect.js
│ │ │ │ │ │ ├── requestReplace.js
│ │ │ │ │ │ ├── sni.js
│ │ │ │ │ │ ├── success.js
│ │ │ │ │ │ └── unVerifySsl.js
│ │ │ │ │ └── res/
│ │ │ │ │ ├── AfterOPTIONSHeaders.js
│ │ │ │ │ ├── cacheResponse.js
│ │ │ │ │ ├── responseReplace.js
│ │ │ │ │ └── script.js
│ │ │ │ └── index.js
│ │ │ ├── monkey/
│ │ │ │ └── index.js
│ │ │ ├── proxy/
│ │ │ │ ├── common/
│ │ │ │ │ ├── ProxyHttpAgent.js
│ │ │ │ │ ├── ProxyHttpsAgent.js
│ │ │ │ │ ├── config.js
│ │ │ │ │ └── util.js
│ │ │ │ ├── compatible/
│ │ │ │ │ └── compatible.js
│ │ │ │ ├── index.js
│ │ │ │ ├── middleware/
│ │ │ │ │ ├── InsertScriptMiddleware.js
│ │ │ │ │ ├── overwall.js
│ │ │ │ │ └── source/
│ │ │ │ │ └── pac.js
│ │ │ │ ├── mitmproxy/
│ │ │ │ │ ├── createConnectHandler.js
│ │ │ │ │ ├── createFakeServerCenter.js
│ │ │ │ │ ├── createRequestHandler.js
│ │ │ │ │ ├── createUpgradeHandler.js
│ │ │ │ │ ├── dnsLookup.js
│ │ │ │ │ └── index.js
│ │ │ │ └── tls/
│ │ │ │ ├── CertAndKeyContainer.js
│ │ │ │ ├── FakeServersCenter.js
│ │ │ │ ├── sniUtil.js
│ │ │ │ └── tlsUtils.js
│ │ │ └── speed/
│ │ │ ├── SpeedTester.js
│ │ │ ├── config.js
│ │ │ └── index.js
│ │ ├── options.js
│ │ └── utils/
│ │ ├── util.js
│ │ ├── util.log.server.js
│ │ ├── util.match.js
│ │ └── util.process.js
│ └── test/
│ ├── baiduOcrTest.js
│ ├── dnsSpeedTest.js
│ ├── dnsTest-abroad-doh-sni.mjs
│ ├── dnsTest-abroad-dot-sni.mjs
│ ├── dnsTest-abroad.mjs
│ ├── dnsTest.mjs
│ ├── lodashTest.js
│ ├── matchTest.js
│ ├── matchUtilTest.js
│ ├── monkeyTest.js
│ ├── pacTest.js
│ ├── proxyTest.js
│ ├── responseReplaceTest.js
│ ├── sha256Test.js
│ └── utilTest.js
├── pnpm-workspace.yaml
└── test/
├── test.js
└── testDns.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/1_BUG_REPORT.md
================================================
---
name: 问题上报
about: 如果你在使用过程中发现问题,请使用此模板。
labels: Bug
---
<!-- 如果搜索过但未找到,请将 `[ ]` 替换为 `[x]` -->
- [ ] 你是否在现有 [Issue列表](/docmirror/dev-sidecar/issues) 中搜索过相同问题,但未找到?
### Ⅰ. 请说明操作系统及DS的版本号:
1. 操作系统:?
2. DS版本号:? <!-- 如:`1.8.6-node17` -->
### Ⅱ. 问题描述:
### Ⅲ. 期望的结果:
### Ⅳ. 如何复现问题?
1. xxx
2. xxx
3. xxx
### Ⅴ. 请提供相关的错误日志,尽可能的详细:(日志文件在 `${user.home}/.dev-sidecar/logs/` 目录下)
<details>
<summary>点击查看日志</summary>
```log
```
</details>
### Ⅵ. 有必要时,请提供 `${user.home}/.dev-sidecar/running.json` 文件内容:
<!-- 请将 'running.json' 文件的内容粘贴在这里,方便我们排查问题是否由配置错误导致。 -->
<details>
<summary>点击查看运行参数</summary>
```json
```
</details>
================================================
FILE: .github/ISSUE_TEMPLATE/2_STYLE_ISSUE.md
================================================
---
name: 样式问题
about: 如果你发现了一些页面样式问题,请使用此模板。
labels: Style Issue
---
<!-- 如果搜索过但未找到,请将 `[ ]` 替换为 `[x]` -->
- [ ] 你是否在现有 [Issue列表](/docmirror/dev-sidecar/issues) 中搜索过相同问题,但未找到?
### Ⅰ. 请说明操作系统及DS的版本号:
1. 操作系统:?
2. DS版本号:? <!-- 如:`1.8.6-node17` -->
### Ⅱ. 样式问题描述:
### Ⅲ. 样式问题截图:
================================================
FILE: .github/ISSUE_TEMPLATE/3_CONFIG_ISSUES.md
================================================
---
name: 配置问题
about: 如果你不知道如何配置DS来访问某个网站,请使用这个模板。
labels: Config Issue
---
### Ⅰ. 你对哪个功能的配置不了解?
<!-- 请选择一个或多个选项,将前面的 `[ ]` 修改为 `[x]` 即可。 -->
- [ ] 拦截设置:
- [ ] redirect
- [ ] proxy
- [ ] sni
- [ ] success
- [ ] abort
- [ ] cache
- [ ] options
- [ ] script
- [ ] requestReplace
- [ ] responseReplace
- [ ] DNS设置和IP测速
- [ ] 系统代理
- [ ] 远程配置
- [ ] 应用:
- [ ] NPM加速
- [ ] Git代理
- [ ] PIP加速
- [ ] 增强功能
### Ⅱ. 请详细描述你的问题:
### Ⅲ. 有必要时,请提供 `${user.home}/.dev-sidecar/running.json` 文件内容:
<!-- 请将 'running.json' 文件的内容粘贴在这里,方便我们排查问题是否由配置错误导致。 -->
<details>
<summary>点击查看运行参数</summary>
```json
```
</details>
================================================
FILE: .github/ISSUE_TEMPLATE/4_FEATURE_REQUEST.md
================================================
---
name: 提新需求
about: 如果你想提出一个新需求,请使用此模板。
labels: Feature Request
---
### Ⅰ. 请描述你想要的新功能:
<!-- 请简单描述你希望的新功能,例如:"在某某页面,添加一个按钮,点击按钮时,弹出一个某某对话框,用于xxx。" -->
### Ⅱ. 请描述你心目中新功能的样子:
<!-- 可以讲讲你对新功能的看法,可以解释更多关于该功能的输入和输出的信息,或贴上你设想的界面设计。 -->
### Ⅲ. 你希望该新功能修复哪个issue?
<!-- 请将相关issue的编号填写在下面,格式如:#123 -->
================================================
FILE: .github/ISSUE_TEMPLATE/5_OTHERS.md
================================================
---
name: 其他问题
about: 如果不是以上问题,请使用此模板。
---
### 请详细描述你的问题、需求或建议:
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
### Ⅰ. 描述此PR的作用:
### Ⅱ. 此PR修复了哪个issue吗?
<!-- 如果是的话,请在下一行写上 "fixes #xxx",比如:fixes #97 -->
### Ⅲ. 界面变化截屏
<!-- 如果存在界面上的变化,请截屏展示出来 -->
================================================
FILE: .github/workflows/build-and-release.yml
================================================
name: Build And Release
on:
push:
branches:
- release*
jobs:
# job 1
build-and-upload:
runs-on: ${{ matrix.os }}-latest
env:
ELECTRON_CACHE: ${{ github.workspace }}/.cache/electron
ELECTRON_BUILDER_CACHE: ${{ github.workspace }}/.cache/electron-builder
strategy:
fail-fast: false
matrix:
os:
- windows
- ubuntu
- macos
node:
- 22
steps:
- name: Checkout
uses: actions/checkout@v4.1.7
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: 'Setup Node.js "${{ matrix.node }}.x" environment'
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
registry-url: https://npm.pkg.github.com/
cache: pnpm
- name: Setup Python environment (Mac) Because of electron-builder install-app-deps requires Python setup tools
if: matrix.os == 'macos'
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Get package info
id: package-info
uses: luizfelipelaviola/get-package-info@v1
with:
path: ./packages/mitmproxy
- name: Print
run: |
echo "version = ${{ steps.package-info.outputs.version }}";
echo "github.ref_type = ${{ github.ref_type }}";
echo "github.ref = ${{ github.ref }}";
echo "github.ref_name = ${{ github.ref_name }}";
- name: 'npm -v | pnpm -v | python --version'
run: |
echo "======================================================================";
echo "npm -v";
echo "--------------------";
npm -v;
echo "======================================================================";
echo "pnpm -v";
echo "--------------------";
pnpm -v;
echo "======================================================================";
echo "python --version";
echo "--------------------";
python --version;
- name: Setup electron cahce
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cache/electron
key: ${{ runner.os }}-electron-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-electron-cache-
- name: Setup electron-builder cahce
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cache/electron-builder
key: ${{ runner.os }}-electron-builder-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-electron-builder-cache-
- name: "'pnpm install' Because we need to install optional dependencies"
run: |
echo "======================================================================";
dir || ls -lah;
echo "======================================================================";
echo "pnpm install";
echo "--------------------";
pnpm install;
- name: 'test packages/core'
run: |
cd packages/core;
pnpm run test;
- name: 'test packages/mitmproxy'
run: |
cd packages/mitmproxy;
pnpm run test;
- name: 'npm run electron:build'
run: |
echo "======================================================================";
echo "cd packages/gui";
echo "--------------------";
cd packages/gui;
dir || ls -lah;
echo "======================================================================";
echo "npm run electron:build";
echo "--------------------";
npm run electron:build;
- name: 'Print dir "packages/gui/dist_electron/"'
run: |
echo "======================================================================";
echo "cd packages/gui/dist_electron";
echo "--------------------";
cd packages/gui/dist_electron;
dir || ls -lah;
# Rename artifacts
- name: 'Rename artifacts - Windows'
if: ${{ matrix.os == 'windows' }}
run: |
cd packages/gui/dist_electron;
ren DevSidecar-${{ steps.package-info.outputs.version }}-x64.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-x64.exe;
ren DevSidecar-${{ steps.package-info.outputs.version }}-ia32.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe;
ren DevSidecar-${{ steps.package-info.outputs.version }}-arm64.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe;
ren DevSidecar-${{ steps.package-info.outputs.version }}.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe;
dir;
- name: 'Rename artifacts - Linux'
if: ${{ matrix.os == 'ubuntu' }}
run: |
cd packages/gui/dist_electron;
mv DevSidecar-${{ steps.package-info.outputs.version }}-amd64.deb DevSidecar-${{ steps.package-info.outputs.version }}-linux-amd64.deb;
mv DevSidecar-${{ steps.package-info.outputs.version }}-x86_64.AppImage DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.AppImage;
mv DevSidecar-${{ steps.package-info.outputs.version }}-x64.tar.gz DevSidecar-${{ steps.package-info.outputs.version }}-linux-x64.tar.gz;
#-------------------------------------------------------------------------------------------------------------------------
mv DevSidecar-${{ steps.package-info.outputs.version }}-arm64.deb DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.deb;
mv DevSidecar-${{ steps.package-info.outputs.version }}-arm64.AppImage DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.AppImage;
mv DevSidecar-${{ steps.package-info.outputs.version }}-arm64.tar.gz DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.tar.gz;
#-------------------------------------------------------------------------------------------------------------------------
mv DevSidecar-${{ steps.package-info.outputs.version }}-armv7l.deb DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.deb;
mv DevSidecar-${{ steps.package-info.outputs.version }}-armv7l.AppImage DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.AppImage;
mv DevSidecar-${{ steps.package-info.outputs.version }}-armv7l.tar.gz DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.tar.gz;
ls -lah;
- name: 'Rename artifacts - macOS'
if: ${{ matrix.os == 'macos' }}
run: |
cd packages/gui/dist_electron;
mv DevSidecar-${{ steps.package-info.outputs.version }}-x64.dmg DevSidecar-${{ steps.package-info.outputs.version }}-macos-x64.dmg;
mv DevSidecar-${{ steps.package-info.outputs.version }}-arm64.dmg DevSidecar-${{ steps.package-info.outputs.version }}-macos-arm64.dmg;
mv DevSidecar-${{ steps.package-info.outputs.version }}-universal.dmg DevSidecar-${{ steps.package-info.outputs.version }}-macos-universal.dmg;
ls -lah;
#region Upload artifacts - Windows
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-windows-x64.exe'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'windows' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-windows-x64.exe
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-x64.exe'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'windows' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'windows' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'windows' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe'
if-no-files-found: error
#endregion Upload artifacts - Windows
#region Upload artifacts - Linux
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-amd64.deb'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-amd64.deb
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-amd64.deb'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.AppImage'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.AppImage
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.AppImage'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-x64.tar.gz'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-x64.tar.gz
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-x64.tar.gz'
if-no-files-found: error
#-------------------------------------------------------------------------------------------------------------------------
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.deb'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.deb
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.deb'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.AppImage'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.AppImage
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.AppImage'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.tar.gz'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.tar.gz
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.tar.gz'
if-no-files-found: error
#-------------------------------------------------------------------------------------------------------------------------
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.deb'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.deb
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.deb'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.AppImage'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.AppImage
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.AppImage'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.tar.gz'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.tar.gz
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.tar.gz'
if-no-files-found: error
#endregion Upload artifacts - Linux
# Upload artifacts - macOS
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-macos-x64.dmg'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'macos' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-macos-x64.dmg
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-macos-x64.dmg'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-macos-arm64.dmg'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'macos' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-macos-arm64.dmg
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-macos-arm64.dmg'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-macos-universal.dmg'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'macos' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-macos-universal.dmg
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-macos-universal.dmg'
if-no-files-found: error
# job 2
download-and-release:
runs-on: ubuntu-latest
needs:
- build-and-upload
steps:
- name: Checkout
uses: actions/checkout@v4.1.7
- name: Get package info
id: package-info
uses: luizfelipelaviola/get-package-info@v1
with:
path: ./packages/mitmproxy
- name: 'Make "release" dir'
run: mkdir release
# Download artifacts
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-windows-x64.exe'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-x64.exe'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-linux-amd64.deb'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-amd64.deb'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.AppImage'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.AppImage'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-linux-x64.tar.gz'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-x64.tar.gz'
path: release
#-------------------------------------------------------------------------------------------------------------------------
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.deb'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.deb'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.AppImage'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.AppImage'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.tar.gz'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.tar.gz'
path: release
#-------------------------------------------------------------------------------------------------------------------------
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.deb'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.deb'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.AppImage'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.AppImage'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.tar.gz'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.tar.gz'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-macos-x64.dmg'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-macos-x64.dmg'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-macos-arm64.dmg'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-macos-arm64.dmg'
path: release
- name: 'Download DevSidecar-${{ steps.package-info.outputs.version }}-macos-universal.dmg'
uses: actions/download-artifact@v4.1.8
with:
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-macos-universal.dmg'
path: release
- name: 'Print files from "release" dir'
run: |
ls -lah release;
- name: Create a draft release
uses: wangliang181230/github-action-ghr@master
env:
GITHUB_TOKEN: ${{ github.token }}
GHR_PATH: release/
GHR_TITLE: ${{ github.ref_name }}
GHR_REPLACE: true
GHR_DRAFT: true
================================================
FILE: .github/workflows/npm-run-electron.yml
================================================
name: npm run electron
on:
push:
branches:
- run*
- test*
- release*
paths-ignore:
- '_script/**'
- 'doc/**'
- '**/*.md'
- '**/.gitignore'
- '**/LICENSE'
jobs:
npm-run-electron:
runs-on: ${{ matrix.os }}-latest
env:
ELECTRON_CACHE: ${{ github.workspace }}/.cache/electron
ELECTRON_BUILDER_CACHE: ${{ github.workspace }}/.cache/electron-builder
strategy:
fail-fast: false
matrix:
os:
- windows
- ubuntu
- macos
node:
- 22
steps:
- name: Checkout
uses: actions/checkout@v4.1.7
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: 'Setup Node.js "${{ matrix.node }}.x" environment'
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
registry-url: https://npm.pkg.github.com/
cache: pnpm
- name: Setup Python environment (Mac) Because of electron-builder install-app-deps requires Python setup tools
if: matrix.os == 'macos'
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Print
run: |
echo "github.ref_type = ${{ github.ref_type }}";
echo "github.ref = ${{ github.ref }}";
echo "github.ref_name = ${{ github.ref_name }}";
- name: 'npm -v | pnpm -v | python --version'
run: |
echo "======================================================================";
echo "npm -v";
echo "--------------------";
npm -v;
echo "======================================================================";
echo "pnpm -v";
echo "--------------------";
pnpm -v;
echo "======================================================================";
echo "python --version";
echo "--------------------";
python --version;
- name: Setup electron cahce
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cache/electron
key: ${{ runner.os }}-electron-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-electron-cache-
- name: Setup electron-builder cahce
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cache/electron-builder
key: ${{ runner.os }}-electron-builder-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-electron-builder-cache-
- name: pnpm install
run: |
echo "======================================================================";
dir || ls -lah;
echo "======================================================================";
echo "pnpm install";
echo "--------------------";
pnpm install;
- name: npm run electron
run: |
echo "======================================================================";
echo "cd packages/gui";
echo "--------------------";
cd packages/gui;
dir || ls -lah;
echo "======================================================================";
echo "npm run electron";
echo "--------------------";
npm run electron;
================================================
FILE: .github/workflows/test-and-upload.yml
================================================
name: Test And Upload
on:
push:
branches:
- master
- 1.x
- develop
- test*
paths-ignore:
- '_script/**'
- 'doc/**'
- '**/*.md'
- '**/.gitignore'
- '**/LICENSE'
pull_request:
branches:
- master
- develop
- 1.x
paths-ignore:
- '_script/**'
- 'doc/**'
- '**/*.md'
- '**/.gitignore'
- '**/LICENSE'
jobs:
test-and-upload:
runs-on: ${{ matrix.os }}-latest
env:
ELECTRON_CACHE: ${{ github.workspace }}/.cache/electron
ELECTRON_BUILDER_CACHE: ${{ github.workspace }}/.cache/electron-builder
strategy:
fail-fast: false
matrix:
os:
- windows
- ubuntu
- macos
node:
- 22
steps:
- name: Checkout
uses: actions/checkout@v4.1.7
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: 'Setup Node.js "${{ matrix.node }}.x" environment'
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
registry-url: https://npm.pkg.github.com/
cache: pnpm
- name: Setup Python environment (Mac) Because of electron-builder install-app-deps requires Python setup tools
if: matrix.os == 'macos'
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Get package info
id: package-info
uses: luizfelipelaviola/get-package-info@v1
with:
path: ./packages/mitmproxy
- name: Print
run: |
echo "version = ${{ steps.package-info.outputs.version }}";
echo "github.ref_type = ${{ github.ref_type }}";
echo "github.ref = ${{ github.ref }}";
echo "github.ref_name = ${{ github.ref_name }}";
- name: 'npm -v | pnpm -v | python --version'
run: |
echo "======================================================================";
echo "npm -v";
echo "--------------------";
npm -v;
echo "======================================================================";
echo "pnpm -v";
echo "--------------------";
pnpm -v;
echo "======================================================================";
echo "python --version";
echo "--------------------";
python --version;
- name: Setup electron cahce
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cache/electron
key: ${{ runner.os }}-electron-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-electron-cache-
- name: Setup electron-builder cahce
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.cache/electron-builder
key: ${{ runner.os }}-electron-builder-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-electron-builder-cache-
- name: "'pnpm install' Because we need to install optional dependencies"
run: |
echo "======================================================================";
dir || ls -lah;
echo "======================================================================";
echo "pnpm install";
echo "--------------------";
pnpm install;
- name: 'test packages/core'
run: |
cd packages/core;
pnpm run test;
- name: 'test packages/mitmproxy'
run: |
cd packages/mitmproxy;
pnpm run test;
- name: 'npm run electron:build'
run: |
echo "======================================================================";
echo "cd packages/gui";
echo "--------------------";
cd packages/gui;
dir || ls -lah;
echo "======================================================================";
echo "npm run electron:build";
echo "--------------------";
npm run electron:build;
- name: 'Print dir "packages/gui/dist_electron/"'
run: |
echo "======================================================================";
echo "cd packages/gui/dist_electron";
echo "--------------------";
cd packages/gui/dist_electron;
dir || ls -lah;
# Rename artifacts
- name: 'Rename artifacts - Windows'
if: ${{ matrix.os == 'windows' }}
run: |
cd packages/gui/dist_electron;
ren DevSidecar-${{ steps.package-info.outputs.version }}-x64.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-x64.exe;
ren DevSidecar-${{ steps.package-info.outputs.version }}-ia32.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe;
ren DevSidecar-${{ steps.package-info.outputs.version }}-arm64.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe;
ren DevSidecar-${{ steps.package-info.outputs.version }}.exe DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe;
dir;
- name: 'Rename artifacts - Linux'
if: ${{ matrix.os == 'ubuntu' }}
run: |
cd packages/gui/dist_electron;
mv DevSidecar-${{ steps.package-info.outputs.version }}-amd64.deb DevSidecar-${{ steps.package-info.outputs.version }}-linux-amd64.deb;
mv DevSidecar-${{ steps.package-info.outputs.version }}-x86_64.AppImage DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.AppImage;
mv DevSidecar-${{ steps.package-info.outputs.version }}-x64.tar.gz DevSidecar-${{ steps.package-info.outputs.version }}-linux-x64.tar.gz;
#-------------------------------------------------------------------------------------------------------------------------
mv DevSidecar-${{ steps.package-info.outputs.version }}-arm64.deb DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.deb;
mv DevSidecar-${{ steps.package-info.outputs.version }}-arm64.AppImage DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.AppImage;
mv DevSidecar-${{ steps.package-info.outputs.version }}-arm64.tar.gz DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.tar.gz;
#-------------------------------------------------------------------------------------------------------------------------
mv DevSidecar-${{ steps.package-info.outputs.version }}-armv7l.deb DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.deb;
mv DevSidecar-${{ steps.package-info.outputs.version }}-armv7l.AppImage DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.AppImage;
mv DevSidecar-${{ steps.package-info.outputs.version }}-armv7l.tar.gz DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.tar.gz;
ls -lah;
- name: 'Rename artifacts - macOS'
if: ${{ matrix.os == 'macos' }}
run: |
cd packages/gui/dist_electron;
mv DevSidecar-${{ steps.package-info.outputs.version }}-x64.dmg DevSidecar-${{ steps.package-info.outputs.version }}-macos-x64.dmg;
mv DevSidecar-${{ steps.package-info.outputs.version }}-arm64.dmg DevSidecar-${{ steps.package-info.outputs.version }}-macos-arm64.dmg;
mv DevSidecar-${{ steps.package-info.outputs.version }}-universal.dmg DevSidecar-${{ steps.package-info.outputs.version }}-macos-universal.dmg;
ls -lah;
#region Upload artifacts - Windows
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-windows-x64.exe'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'windows' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-windows-x64.exe
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-x64.exe'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'windows' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-ia32.exe'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'windows' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-arm64.exe'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'windows' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-windows-universal.exe'
if-no-files-found: error
#endregion Upload artifacts - Windows
#region Upload artifacts - Linux
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-amd64.deb'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-amd64.deb
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-amd64.deb'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.AppImage'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.AppImage
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-x86_64.AppImage'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-x64.tar.gz'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-x64.tar.gz
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-x64.tar.gz'
if-no-files-found: error
#-------------------------------------------------------------------------------------------------------------------------
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.deb'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.deb
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.deb'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.AppImage'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.AppImage
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.AppImage'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.tar.gz'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.tar.gz
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-arm64.tar.gz'
if-no-files-found: error
#-------------------------------------------------------------------------------------------------------------------------
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.deb'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.deb
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.deb'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.AppImage'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.AppImage
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.AppImage'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.tar.gz'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'ubuntu' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.tar.gz
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-linux-armv7l.tar.gz'
if-no-files-found: error
#endregion Upload artifacts - Linux
# Upload artifacts - macOS
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-macos-x64.dmg'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'macos' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-macos-x64.dmg
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-macos-x64.dmg'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-macos-arm64.dmg'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'macos' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-macos-arm64.dmg
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-macos-arm64.dmg'
if-no-files-found: error
- name: 'Upload DevSidecar-${{ steps.package-info.outputs.version }}-macos-universal.dmg'
uses: actions/upload-artifact@v4.4.0
if: ${{ matrix.os == 'macos' }}
with:
path: packages/gui/dist_electron/DevSidecar-${{ steps.package-info.outputs.version }}-macos-universal.dmg
name: 'DevSidecar-${{ steps.package-info.outputs.version }}-macos-universal.dmg'
if-no-files-found: error
================================================
FILE: .gitignore
================================================
# IntelliJ project files
.idea
*.iml
# vscode settings files
.vscode
# Mac
.DS_Store
# Node files
node_modules/
*.lock
package-lock.json
# Other files
out
gen
*.log
*.lnk
================================================
FILE: .npmrc
================================================
shamefully-hoist=true
================================================
FILE: LICENSE
================================================
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
================================================
FILE: README.md
================================================
# dev-sidecar
开发者边车,命名取自service-mesh的service-sidecar,意为为开发者打辅助的边车工具(以下简称ds)
通过本地代理的方式将https请求代理到一些国内的加速通道上
<a href='https://github.com/docmirror/dev-sidecar'><img alt="GitHub stars" src="https://img.shields.io/github/stars/docmirror/dev-sidecar?logo=github"></a>
[](https://www.star-history.com/#docmirror/dev-sidecar&type=date&legend=top-left)
> Gitee上的同步项目已被封禁,请认准本项目唯一官方仓库地址[https://github.com/docmirror/dev-sidecar](https://github.com/docmirror/dev-sidecar) 【狗头保命】
>
> 我将继续奋战在开源一线,为社区贡献更多更好的开源项目。
>
> 感兴趣的可以关注我的主页 [【github】](https://github.com/greper) [【gitee】](https://gitee.com/greper)
## 打个广告
> [https://github.com/certd/certd](https://github.com/certd/certd)
>
> 我的开源证书管理工具项目,全自动申请和部署证书,有需求的可以去试试,帮忙点个star
## 重要提醒
> ------------------------------重要提醒1---------------------------------
>
> 注意:由于electron无法监听windows的关机事件,开着ds情况下直接重启电脑,会导致无法上网,你可以手动启动ds即可恢复网络,你也可以将ds设置为开机自启。
>
> 关于此问题的更多讨论请前往:[https://github.com/docmirror/dev-sidecar/issues/109](https://github.com/docmirror/dev-sidecar/issues/109)
>
> 注:此问题已在 `1.8.9` 版本中得到解决。
> ------------------------------重要提醒2---------------------------------
>
> 注意:本应用启动会自动修改系统代理,所以会与其他代理软件有冲突,一起使用时请谨慎使用。
>
> 与Watt Toolkit(原Steam++)共用时,请以hosts模式启动Watt Toolkit
>
> 与TUN网卡模式运行的游戏加速器可以共用
>
> 本应用主要目的在于直连访问github,如果你已经有飞机了,那建议还是不要用这个自行车(ds)了
## 一、 特性
### 1.1、 dns优选(解决\*\*\*污染问题)
- 根据网络状况智能解析最佳域名ip地址,获取最佳网络速度
- 解决一些网站和库无法访问或访问速度慢的问题
- 建议遇到打开比较慢的国外网站,可以优先尝试将该域名添加到dns设置中(注意:被\*\*\*封杀的无效)
### 1.2、 请求拦截
- 拦截打不开的网站,代理到加速镜像站点上去。
- 可配置多个镜像站作为备份
- 具备测速机制,当访问失败或超时之后,自动切换到备用站点,使得目标服务高可用
### 1.3、 github加速
- github 直连加速 (通过修改sni实现,感谢 [fastGithub](https://github.com/dotnetcore/FastGithub) 提供的思路)
- release、source、zip下载加速
- clone 加速
- 头像加速
- 解决readme中图片引用无法加载的问题
- gist.github.com 加速
- 解决git push 偶尔失败需要输入账号密码的问题(fatal: TaskCanceledException encountered / fatal: HttpRequestException encountered)
- raw/blame加速
> 以上部分功能通过 `X.I.U` 的油猴脚本实现, 以下是仓库和脚本下载链接,大家可以去支持一下。
>
> - [https://github.com/XIU2/UserScript](https://github.com/XIU2/UserScript)
>
> - [https://greasyfork.org/scripts/412245](https://greasyfork.org/scripts/412245)
>
> 由于此脚本在ds中是打包在本地的,更新会不及时,你可以直接通过浏览器安装油猴插件使用此脚本,从而获得最新更新(ds本地的可以通过 `加速服务->基本设置->启用脚本` 进行关闭)。
### 1.4、 Stack Overflow 加速
- 将ajax.google.com代理到加速CDN上
- recaptcha 图片验证码加速
### 1.5、 npm加速
- 支持开启npm代理
- 官方与淘宝npm registry一键切换
- 某些npm install的时候,并且使用cnpm也无法安装时,可以尝试开启npm代理再试
**_安全警告_**:
- 请勿使用来源不明的服务/远程配置地址,有隐私和账号泄露风险
- 本应用及服务/默认远程配置端承诺不收集任何信息。介意者请使用安全模式。
## 二、快速开始
支持windows、Mac、Linux(Ubuntu)
### 2.1、DevSidecar桌面应用
#### 1)下载安装包
- release下载
[Github Release](https://github.com/docmirror/dev-sidecar/releases)
> Windows: 请选择DevSidecar-x.x.x-windows-universal.exe
>
> Mac: 请选择DevSidecar-x.x.x-macos-universal.dmg
>
> Debian系及其他支持deb安装包的Linux: 请选择DevSidecar-x.x.x-linux-[架构].deb
>
> 其他Linux: 请选择DevSidecar-x.x.x-linux-[架构].AppImage (未做测试,不保证能用)
> linux安装说明请参考 [linux安装文档](./doc/linux.md)
> 注意:由于没有买应用证书,所以应用在下载安装时会有“未知发行者”等安全提示,选择保留即可。
#### 2)安装后打开
界面应大致如下图所示:
> 注意:mac版安装需要在“系统偏好设置->安全性与隐私->通用”中解锁并允许应用安装

#### 3)安装根证书
第一次打开会提示安装证书,根据提示操作即可
更多有关根证书的说明,请参考 [为什么要安装根证书?](./doc/caroot.md)
> 根证书是本地随机生成的,所以不用担心根证书的安全问题(本应用不收集任何用户信息)
>
> 你也可以在加速服务设置中自定义根证书(PEM格式的证书与私钥)
> 火狐浏览器需要[手动安装证书](#3火狐浏览器火狐浏览器不走系统的根证书需要在选项中添加根证书)
#### 4)开始加速吧
去试试打开github、huggingface、docker hub吧
### 2.2、开启前 vs 开启后
| | 开启前 | 开启后 |
| -------- | ------------------------------ | ----------------------------------------------- |
| 头像 |  |  |
| clone |  |  |
| zip 下载 |  | 秒下的,实在截不到速度的图 |
## 三、模式说明
### 3.1、安全模式
- 此模式:关闭拦截、关闭增强、不使用远程配置、开启dns优选、开启测速
- 最安全,无需安装证书,可以在浏览器地址栏左侧查看域名证书
- 功能也最弱,只有特性1,相当于查询github的国外ip,手动改hosts一个意思。
- github的可访问性不稳定,取决于IP测速,如果有绿色ip存在,就 `有可能` 可以直连访问。

### 3.2、默认模式
- 此模式:开启拦截、关闭增强、使用远程配置、开启dns优选、开启测速
- 需要安装证书,通过修改sni直连访问github
- 功能上包含特性1/2/3/4。
## 四、 最佳实践
- 把dev-sidecar一直开着就行了
- 建议遇到打开比较慢的国外网站,可以尝试将该域名添加到dns设置中(注意:被\*\*\*封杀的无效)
### 其他加速
#### 1)git clone 加速
- 方式1:快捷复制:
> 开启脚本支持,然后在复制clone链接下方,即可复制到加速链接
- 方式2:
> 1. 使用方式:用实际的名称替换 `{}` 的内容,即可加速clone [https://hub.fastgit.org/{username}/{reponame}.git](https://hub.fastgit.org/%7Busername%7D/%7Breponame%7D.git)
> 2. clone 出来的 remote "origin" 为fastgit的地址,需要手动改回来
> 3. 你也可以直接使用他们的clone加速工具 [fgit-go](https://github.com/FastGitORG/fgit-go)
#### 2)`github.com` 的镜像网站(注意:部分镜像网站不能登录)
> 1. [hub.fastgit.org](https://hub.fastgit.org/) (2024/11/18:这个好像失效了?)
> 2. [github.com.cnpmjs.org](https://github.com.cnpmjs.org/) 这个很容易超限(2024/11/18:这个好像失效了?)
> 3. [dgithub.xyz](https://dgithub.xyz/)
## 五、api
### 5.1、拦截配置
没有配置域名的不会拦截,其他根据配置进行拦截处理。
在【加速服务-拦截设置】中配置,格式如下:(更多内容参见[wiki](https://github.com/docmirror/dev-sidecar/wiki/%E5%8A%A0%E9%80%9F%E6%9C%8D%E5%8A%A1%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E))
```jsonc
{
// 要拦截的域名
'github.com': {
// 需要拦截url的正则表达式
'/.*/.*/releases/download/': {
// 拦截类型
// redirect: url, // 临时重定向(url会变,一些下载资源可以通过此方式配置)
// proxy: url, // 代理(url不会变,没有跨域问题)
// abort: true, // 取消请求(适用于被***封锁的资源,找不到替代,直接取消请求,快速失败,节省时间)
// success: true, // 直接返回成功请求(某些请求不想发出去,可以伪装成功返回)
// cacheDays: 1, // GET请求的使用缓存,单位:天(常用于一些静态资源)
// options: true, // OPTIONS请求直接返回成功请求(该功能存在一定风险,请谨慎使用)
// optionsMaxAge: 2592000, // OPTIONS请求缓存时间,默认:2592000(一个月)
redirect: 'download.fastgit.org'
},
'.*': {
proxy: 'github.com',
sni: 'baidu.com' // 修改sni,规避***握手拦截
}
},
'ajax.googleapis.com': {
'.*': {
proxy: 'ajax.loli.net', // 代理请求,url不会变
backup: ['ajax.proxy.ustclug.org'], // 备份,当前代理请求失败后,将会切换到备用地址
test: 'ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js',
replace: '/(.*)/xxx'// 当加速地址的链接和原链接不是完全相同时,可以通过正则表达式replace,此时proxy通过$1$2来重组url, proxy:'ajax.loli.net/xxx/$1'
}
},
'clients*.google.com': {
'.*': {
abort: true // 取消请求,被***封锁的资源,找不到替代,直接取消请求,快速失败,节省时间
}
}
}
```
### 5.2、DNS优选配置
某些域名解析出来的ip会无法访问,(比如api.github.com会被解析到新加坡的ip上,新加坡的服务器在上午挺好,到了晚上就卡死,基本不可用)
通过从dns上获取ip列表,切换不同的ip进行尝试,最终会挑选到一个最快的ip(该功能需要事先配置好所用DNS),更多说明参见[wiki](https://github.com/docmirror/dev-sidecar/wiki/%E5%8A%A0%E9%80%9F%E6%9C%8D%E5%8A%A1%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E)
```json
{
"dns": {
"mapping": {
"api.github.com": "cloudflare", // "解决push的时候需要输入密码的问题",
"gist.github.com": "cloudflare", // 解决gist无法访问的问题
"*.githubusercontent.com": "cloudflare" // 解决github头像经常下载不到的问题
}
}
}
```
注意:暂时只支持IPv4的解析
## 六、问题排查
### 6.1、dev-sidecar的前两个开关没有处于打开状态
1. 尝试将开关按钮手动打开
2. 请尝试右键dev-sidecar图标,点退出。再重新打开
3. 如果还不行,请将日志发送给作者
如果是mac系统,可能是下面的原因
#### 1)Mac系统使用时,首页的系统代理开关无法打开
出现这个问题可能是没有开启系统代理命令的执行权限
```
networksetup -setwebproxy 'WiFi' 127.0.0.1 31181
#看是否有如下错误提示
** Error: Command requires admin privileges.
```
如果有上面的错误提示,请尝试如下方法:
> 取消访问偏好设置需要管理员密码
>
> 系统偏好设置—>安全性与隐私—> 通用—> 高级—> 访问系统范围的偏好设置需要输入管理员密码(取消勾选)
### 6.2、没有加速效果
1. 本应用默认仅开启https加速,一般足够覆盖需求。
如果你访问的是仅支持http协议的网站,请手动在【系统代理】中打开【代理HTTP请求】
2. 检查浏览器是否装了什么插件,与ds有冲突
3. 检查是否安装了其他代理软件,与ds有冲突
4. 请确认浏览器的代理设置为使用IE代理/或者使用系统代理状态
5. 可以尝试换个浏览器试试
6. 请确认网络代理设置处于勾选状态
正常情况下ds在“系统代理”开关打开时,会自动设置系统代理。
### 6.3、浏览器打开提示证书不受信任

一般是证书安装位置不对,重新安装根证书后,重启浏览器
#### 1)windows: 请确认证书已正确安装在“本地计算机-将所有的证书都放入下列存储:受信任的根证书颁发机构”下
#### 2)mac: 请确认证书已经被安装并已经设置信任
#### 3)火狐浏览器:火狐浏览器不走系统的根证书,需要在选项中添加根证书
1. 火狐浏览器->选项->隐私与安全->证书->查看证书

2. 证书颁发机构->导入
3. 选择证书文件 `C:\Users(用户)\Administrator(你的账号)\.dev-sidecar\dev-sidecar.ca.crt`(Mac或linux为 `~/.dev-sidecar` 目录)

4. 勾选信任由此证书颁发机构来标识网站,确定即可

### 6.4、打开github显示连接超时
```html
DevSidecar Warning: Error: www.github.com:443, 代理请求超时
```
1. 检查测速界面github.com是否有ip ,如果没有ip,则可能是由于你的网络提供商封锁了dns服务商的ip(试试能否ping通:1.1.1.1 / 9.9.9.9 )
2. 如果是安全模式,则是因为不稳定导致的,等一会再刷新试试
3. 如果是增强模式,则是由于访问人数过多,正常现象
### 6.5、查看日志是否有报错
如果还是不行,请在下方加官方QQ群或提issue,附上服务日志(server.log)以便进行分析
日志打开方式:加速服务->右边日志按钮->打开日志文件夹

### 6.6、某些原本可以打开的网站打不开了
1. 可以尝试关闭pac
2. 可以将域名加入白名单
### 6.7、应用意外关闭导致没有网络了
应用开启后会自动修改系统代理设置,正常退出会自动关闭系统代理
当应用意外关闭时,可能会因为没有将系统代理恢复,从而导致完全无法上网。
对于此问题有如下几种解决方案可供选择:
1. 重新打开应用即可(右键应用托盘图标可完全退出,将会正常关闭系统代理设置)
2. 如果应用被卸载了,此时需要[手动关闭系统代理设置](./doc/recover.md)
3. 如果你是因为开着ds的情况下重启电脑导致无法上网,你可以设置ds为开机自启
### 6.8、卸载应用后上不了网,git请求不了
如果你在卸载应用前,没有正常退出app,就有可能无法上网。请按如下步骤操作恢复您的网络:
1、关闭系统代理设置,参见:[手动关闭系统代理设置](./doc/recover.md)
2、执行下面的命令关闭git的代理设置(如果你开启过 `Git.exe代理` 的开关)
```shell
git config --global --unset http.proxy
git config --global --unset https.proxy
git config --global --unset http.sslVerify
```
3、执行下面的命令关闭npm的代理设置(如果你开启过npm加速的开关)
```shell
npm config delete proxy
npm config delete https-proxy
```
### 6.9、其他问题
请查阅[wiki](https://github.com/docmirror/dev-sidecar/wiki)
也可以查阅[有文档tag的issue](https://github.com/docmirror/dev-sidecar/issues?q=is%3Aissue%20label%3ADocumentation),它们被开发者认证为相当于文档级别的参考issue。
## 七、在其他程序使用
- [java程序使用](./doc/other.md#Java程序使用)
## 八、贡献代码
### 8.1、准备环境
#### 1)安装 `nodejs`
推荐安装 nodejs `22.x.x` 的版本,其他版本未做测试
#### 2)安装 `pnpm`
运行如下命令即可安装所需依赖:
```shell
npm install -g pnpm --registry=https://registry.npmmirror.com
```
### 8.2、开发调试模式启动
运行如下命令即可开发模式启动
```shell
# 拉取代码
git clone https://github.com/docmirror/dev-sidecar
cd dev-sidecar
# 注意不要使用 `npm install` 来安装依赖,因为 `pnpm` 会自动安装依赖
pnpm install
# 运行DevSidecar
cd packages/gui
npm run electron
```
> 如果electron依赖包下载不动,可以开启ds的npm加速
### 8.3、打包成可执行文件
```shell
# 先执行上面的步骤,然后运行如下命令打包成可执行文件
npm run electron:build
```
### 8.4、提交pr
如果你想将你的修改贡献出来,请提交pr
## 九、联系作者
欢迎bug反馈,需求建议,技术交流等
加官方QQ群(请备注dev-sidecar,或简称DS)
- QQ 1群:390691483,人数:499 / 500(满)
- QQ 2群:667666069,人数:500 / 500(满)
- QQ 3群:419807815,人数:493 / 500(满)
- QQ 4群:[438148299](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=i_NCBB5f_Bkm2JsEV1tLs2TkQ79UlCID&authKey=nMsVJbJ6P%2FGNO7Q6vsVUadXRKnULUURwR8zvUZJnP3IgzhHYPhYdcBCHvoOh8vYr&noverify=0&group_code=438148299),人数:700 / 1000
- QQ 5群:[767622917](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=nAWi_Rxj7mM4Unp5LMiatmUWhGimtbcB&authKey=aswmlWGjbt3GIWXtvjB2GJqqAKuv7hWjk6UBs3MTb%2Biyvr%2Fsbb1kA9CjF6sK7Hgg&noverify=0&group_code=767622917),人数:200 / 200(new)
## 十、求star
我的其他项目求star
- [fast-crud](https://github.com/fast-crud/fast-crud) : 开发crud快如闪电
- [certd](https://github.com/certd/certd) : 让你的证书永不过期
- [trident-sync](https://github.com/handsfree-work/trident-sync) : 二次开发项目同步升级工具
## 十一、感谢
本项目使用lerna包管理工具
[](https://lerna.js.org/)
本项目参考如下开源项目
- [node-mitmproxy](https://github.com/wuchangming/node-mitmproxy)
- [ReplaceGoogleCDN](https://github.com/justjavac/ReplaceGoogleCDN)
特别感谢
- [github增强油猴脚本](https://greasyfork.org/zh-CN/scripts/412245-github-%E5%A2%9E%E5%BC%BA-%E9%AB%98%E9%80%9F%E4%B8%8B%E8%BD%BD) 本项目部分加速功能完全复制该脚本。
- [中国域名白名单](https://github.com/pluwen/china-domain-allowlist),本项目的系统代理排除域名功能中,使用了该白名单。
本项目部分加速资源由如下组织提供
- [FastGit UK](https://fastgit.org/)
================================================
FILE: _script/0、updateDependencies.bat
================================================
node -v
# 安装ncu
# npm install -g npm-check-updates
cd ../packages/core
ncu -u
# cd ../packages/gui
# ncu -u
# cd ../packages/mitmproxy
# ncu -u
================================================
FILE: _script/1、setupEnv.bat
================================================
node -v
cd ../
npm install -g pnpm --registry=https://registry.npmmirror.com
================================================
FILE: _script/2、installProject.bat
================================================
node -v
cd ../
chcp 65001
pnpm install
================================================
FILE: _script/3、buildAndRun.bat
================================================
node -v
cd ../packages/gui
chcp 65001
npm run electron
================================================
FILE: _script/4.1、runTestCore.bat
================================================
node -v
cd ../packages/core
pnpm run test
================================================
FILE: _script/4.2、runTestMitmproxy.bat
================================================
node -v
cd ../packages/mitmproxy
pnpm run test
================================================
FILE: _script/5、generateSetupFile.bat
================================================
node -v
cd ../packages/gui
if not exist "dist_electron" mkdir "dist_electron"
start dist_electron
npm run electron:build
================================================
FILE: doc/caroot.md
================================================
# 关于信任根证书的说明
## 一、为什么要信任根证书。
要回答这个问题需要先掌握下面两个知识点
### 知识点1:什么是根证书
[百度百科-什么是根证书](https://baike.baidu.com/item/%E6%A0%B9%E8%AF%81%E4%B9%A6/9874620?fr=aladdin)
当访问目标网站是https协议时,服务器会发送一个由根证书签发的网站ssl证书给浏览器,让浏览器用这个ssl证书给数据加密。
浏览器需要先验证这个证书的真伪,之后才会使用证书加密。
证书的真伪是通过验证证书的签发机构的证书是否可信,一直追溯到最初始的签发机构的证书(根证书)。
浏览器只需信任根证书,间接的就信任了这条证书链下签发的所有证书。
windows、mac、linux或者浏览器他们都内置了市面上可信的大型证书颁发机构的根证书。
### 知识点2:中间人攻击
本应用的实现原理如下图:

> 简单来说就是DevSidecar在本地启动了一个代理服务器帮你访问目标网站。
> 实际上就是 [中间人攻击](https://baike.baidu.com/item/%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB/1739730?fr=aladdin) 的原理,只是本应用没有用它来干坏事,而是帮助开发者加速目标网站的访问。
### 现在可以回答为什么要信任根证书
当目标网站不需要加速拦截时,直接走TCP转发,不需要中间人攻击,没有安全风险,在此不多做讨论。
当目标网站需要拦截时(例如github),就需要通过中间人攻击修改请求或者请求其他替代网站,从而达到加速的目的。
例如加速github就需要修改如下几处
1. 直连访问github需要修改tls握手时的sni域名,规避\*\*\*的sni阻断问题。
2. asserts.github.com等静态资源拦截替换成fastgit.org的镜像地址
DevSidecar在第一次启动时会在本地随机生成一份根证书,当有用户访问github时,就用这份根证书来签发一份假的叫github.com的证书。
如果浏览器事先信任了这份根证书,那么就可以正常访问DevSidecar返回的网页内容了。
## 二、信任根证书有安全风险吗
1. 根证书是DevSidecar第一次启动时本地随机生成的,除了你这台电脑没人知道这份根证书的内容。
2. 代理请求目标网站时会校验目标网站的证书(除非关闭了`代理校验ssl`)。
> 两段链路都是安全的,所以信任根证书没有问题。
> 但如果应用本身来源不明,或者`拦截配置`里的替代网站作恶,则有安全风险。
> 对于应用来源风险:
> 请勿从未知网站下载DevSidecar应用,认准官方版本发布地址
> [Github Release](https://github.com/docmirror/dev-sidecar/releases)
>
> 或者从源码自行编译安装
> 对于拦截配置里的替代网站风险:
>
> 1. 尽量缩小替代配置的范围
> 2. 不使用来源不明的镜像地址,尽量使用知名度较高的镜像地址
> 3. 你甚至可以将其他拦截配置全部删除,只保留github相关配置
================================================
FILE: doc/linux.md
================================================
# Linux 支持
`Linux`使用说明,目前仅官方支持`Ubuntu x86_64 GNOME桌面版(原版)`,其他`Linux`未测试
> 注意:需要开启 [sudo 免密支持](https://www.jianshu.com/p/5d02428f313d),否则请自行安装证书
## 一、安装
### 1.1. Ubuntu / Debian或其衍生版(未测试)
- 下载`DevSidecar-x.x.x.deb`
- 使用 root 执行命令安装 `dpkg -i DevSidecar-x.x.x.deb`
- 去应用列表里面找到 dev-sidecar 应用,打开即可
### 1.2. 其他基于glibc的Linux系统(未测试)
- 下载 `DevSidecar-x.x.x.AppImage`
- 设置可执行权限 `chmod +x DevSidecar-x.x.x.AppImage`
- 双击运行
### 1.3. 特殊的Linux系统(如Alpine和Chimera Linux)
> 此处默认用户有较专业的Linux知识,故不详细描述,请参考并自行试验
- 创建Debian(最方便且省空间)容器,可使用distrobox(推荐),接下来以此为例说明
- 下载deb包并在容器内安装
- 穿透系统设置:
在容器内 `/usr/bin/gsettings` 文件写入:
```bash
#!/bin/sh
distrobox-host-exec gsettings "$@"
```
并设置可执行权限
简化版命令(请在容器内执行):
```
echo -e '#!/bin/sh\ndistrobox-host-exec gsettings "$@"' >/usr/bin/gsettings
```
- 使用命令启动应用,使用“自动安装证书”功能,回到终端,找到输出里含有 `sudo` 的两句命令,复制到主系统执行,如失败(或使用其他证书系统),请自行安装证书,可参考 [议题 #204](https://github.com/docmirror/dev-sidecar/issues/204)
### 1.4. 版本选择
不同CPU架构,选择对应的版本,如果安装失败,请下载 `universal` 版本
## 二、证书安装
默认模式和增强模式需要系统信任CA证书。
由于Linux上火狐和Chrome都不走系统证书,所以除了安装系统证书之外,还需要给浏览器安装证书
### 2.1. 系统证书安装
根据弹出的提示:
- 点击首页右上角“安装根证书”按钮
- 点击“点此去安装”
- 提示安装成功即可
### 2.2. 火狐浏览器安装证书
- 火狐浏览器->选项->隐私与安全->证书->查看证书
- 证书颁发机构->导入
- 选择证书文件在 `~/.dev-sidecar` 目录下
- 勾选信任由此证书颁发机构来标识网站,确定即可
### 2.3. Chrome浏览器安装证书
证书文件目录为 `~/.dev-sidecar`

================================================
FILE: doc/other.md
================================================
# 其他程序使用
## Java程序使用
> 由 [Enaium](https://github.com/Enaium) 提供,未做验证,可供参考
1. 先通过keytool安装证书:
```shell
keytool -import -alias dev-sidecar -keystore "jdk路径\security\cacerts" -file 用户目录\.dev-sidecar\dev-sidecar.ca.crt
```
默认密码为 `changeit`
2. 启动时还需要设置参数,例:
```shell
java -Dhttp.proxyHost=localhost -Dhttp.proxyPort=31181 -Dhttps.proxyHost=localhost -Dhttps.proxyPort=31181 -jar xxxx.jar
```
3. Gradle还需在`用户目录/.gradle/gradle.properties`创建配置文件:
```properties
systemProp.http.proxyHost=localhost
systemProp.http.proxyPort=31181
systemProp.https.proxyHost=localhost
systemProp.https.proxyPort=31181
```
================================================
FILE: doc/recover.md
================================================
# 卸载与恢复网络
由于应用启动后会自动设置系统代理,正常退出时会关闭系统代理。
当应用意外关闭,或者未正常退出后被卸载,此时会因为系统代理没有恢复从而导致完全上不了网。
目前electron在windows系统上无法监听系统重启事件。更多相关资料 [electron issues](https://github.com/electron/electron/pull/24261)
## 恢复代理设置
### 1、windows 代理关闭
如何打开查看windows代理设置:
- win10: 开始->设置->网络和Internet->最下方代理
- win7: 开始->控制面板->网络和Internet->网络和共享中心->左下角Internet选项->连接选项卡->局域网设置

### 2、mac 代理关闭
网络->网卡->代理->去掉http和https的两个勾

### 3、Linux(Ubuntu)
网络->代理->选择禁用
================================================
FILE: doc/wiki/Home.md
================================================
> **给作者打个广告:**<br>
> [https://github.com/certd/certd](https://github.com/certd/certd) 我的开源证书管理工具项目,全自动申请和部署证书,有需求的可以去试试,帮忙点个star
> 注:Wiki还在完善中,敬请期待更多内容。<br>
> 说明:以下文档均以最新版本进行编写,请下载最新版DS后,再参考以下文档使用!<br>
# 一、下载安装:
访问 https://github.com/docmirror/dev-sidecar/releases 页面,下载对应操作系统的安装程序进行安装。
如安装有问题,请查看 [各平台安装说明](https://github.com/docmirror/dev-sidecar/wiki/%E5%90%84%E5%B9%B3%E5%8F%B0%E5%AE%89%E8%A3%85%E8%AF%B4%E6%98%8E)
# 二、功能使用说明:
1. [`加速服务`使用说明](https://github.com/docmirror/dev-sidecar/wiki/%E5%8A%A0%E9%80%9F%E6%9C%8D%E5%8A%A1%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E)
2. 系统代理使用说明:
3. 通用功能使用说明:
1. 开机自启动:
2. 远程配置:
3. 主题设置:
4. 窗口设置:
5. 检查更新:
4. 应用使用说明:
1. NPM加速:
2. Git.exe加速:
3. PIP加速:
4. 彩蛋(功能增强):
5. 帮助中心
6. 反馈问题
# 三、解决问题:
1. [解决Github访问不了或速度很慢的问题](https://github.com/docmirror/dev-sidecar/wiki/%E8%A7%A3%E5%86%B3Github%E8%AE%BF%E9%97%AE%E4%B8%8D%E4%BA%86%E6%88%96%E9%80%9F%E5%BA%A6%E5%BE%88%E6%85%A2%E7%9A%84%E9%97%AE%E9%A2%98)
2. [Linux安装证书失败的避坑](https://github.com/docmirror/dev-sidecar/issues/238)
3. [解决Linux(deb)系统下无法安装根证书的问题](https://github.com/docmirror/dev-sidecar/issues/135)
4. [在Arch/Fedora下的证书安装](https://github.com/docmirror/dev-sidecar/issues/204)
5. [Mac安装:`无法打开“dev-sidecar”,因为无法验证开发者。` 的解决方案](https://github.com/docmirror/dev-sidecar/issues/147)
6. [在 WSL 中的使用方法](https://github.com/docmirror/dev-sidecar/issues/73)
[> 点击前往Issue区查找更多帮助信息](https://github.com/docmirror/dev-sidecar/issues)
# 四、DevSidecar技术交流群
- QQ 1群:[390691483](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=hIG_VClE1CU2gHuLSSTaazMlo6M760iL&authKey=5VUMMwzH5FeabLDbZNZJbqmZk1gfmB%2B%2FlotO%2Brszz%2BW3E8xwKD2hTg2%2FV2LJEKL7&noverify=0&group_code=390691483),人数:496 / 500
- QQ 2群:[667666069](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=n4nksr4sji93vZtD5e8YEHRT6qbh6VyQ&authKey=XKBZnzmoiJrAFyOT4V%2BCrgX5c13ds59b84g%2FVRhXAIQd%2FlAiilsuwDRGWJct%2B570&noverify=0&group_code=667666069),人数:488 / 500
- QQ 3群:[419807815](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=zRkm0eHUhRmWWJA5O35C7BOKPZ4_gmrz&authKey=X9JHezR1BOalcEmvV6If04TN%2BIbzjAayBDaOSiuOg1SPpPguA7RqoLSHVEeo7A4e&noverify=0&group_code=419807815),人数:494 / 500
- QQ 4群:[438148299](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=i_NCBB5f_Bkm2JsEV1tLs2TkQ79UlCID&authKey=nMsVJbJ6P%2FGNO7Q6vsVUadXRKnULUURwR8zvUZJnP3IgzhHYPhYdcBCHvoOh8vYr&noverify=0&group_code=438148299),人数:295 / 1000
- QQ 5群:[767622917](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=nAWi_Rxj7mM4Unp5LMiatmUWhGimtbcB&authKey=aswmlWGjbt3GIWXtvjB2GJqqAKuv7hWjk6UBs3MTb%2Biyvr%2Fsbb1kA9CjF6sK7Hgg&noverify=0&group_code=767622917),人数:068 / 200(new)
# 五、版本更新日志
https://github.com/docmirror/dev-sidecar/releases
================================================
FILE: doc/wiki/加速服务使用说明.md
================================================
# 1. 加速服务:
1. 什么是 `加速服务`?
- `加速服务` 即 `代理服务`,它通过中间人攻击的方式,将网络请求拦截下来,并经过DNS加速、修改、重定向、代理等一系列的功能,达到加速访问、或访问原本无法访问的站点等目的。<br>
2. 如何启动加速服务:<br>
- 点击首页的【代理服务】右侧的开关按钮,即可启动/关闭加速服务。<br>
- 点击首页的【系统代理】右侧的开关按钮,即可将dev-sidecar设置/不设置为系统默认代理。(系统只能有一个默认代理,在将dev-sidecar与其他网络辅助软件共用时请谨慎开启本开关)<br>
- 点击首页的【NPM加速】和【Git.exe代理】右侧的开关按钮,即可启动/关闭dev-sidecar为对应软件提供的加速服务。如果你的电脑上并未安装NPM或Git,则这两个按钮将不可用,这是正常情况。
# 2. 根证书使用说明:
1. 什么是根证书:TODO
2. [为什么需要安装根证书这么高风险性的步骤](https://github.com/docmirror/dev-sidecar/blob/master/doc/caroot.md)
3. 如何安装根证书:参见dev-sidecar【首页】的【安装根证书】按钮(注意Firefox浏览器还需要一次手动导入根证书)
# 3. 模式:
1. 安全模式:TODO
2. 默认模式:TODO
3. 增强模式(彩蛋):TODO
# 4. 拦截功能使用和配置说明:
## 4.1. 拦截器类型:
### 1)请求拦截器:
| 请求拦截器名称 | 拦截器配置名 | 请求拦截优先级 | 作用 |
| ----------------- | -------------- | ------------- | --------- |
| OPTIONS请求拦截器 | options | 101 | 直接响应200,不发送该OPTIONS请求 |
| 快速成功拦截器 | success | 102 | 直接响应200,不发送该请求 |
| 快速失败拦截器 | abort | 103 | 直接响应403,不发送该请求 |
| 缓存请求拦截器 | cacheXxx | 104 | 如果缓存还生效,直接响应304,不发送该请求<br>如果缓存已过期或无缓存,则发送请求<br>注:只对GET请求生效! |
| 重定向拦截器 | redirect | 105 | 重定向到指定地址,直接响应302,不发送该请求 |
| 请求篡改拦截器 | requestReplace | 111 | 篡改请求头,达到想要的目的 |
| 代理拦截器 | proxy | 121 | 将请求转发到指定地址 |
| SNI拦截器 | sni | 122 | 设置 `servername`,用于避开GFW |
### 2)响应拦截器:
| 响应拦截器名称 | 拦截器配置名 | 响应拦截优先级 | 作用 |
| ---------------- | --------------- | ------------- | --------- |
| OPTIONS响应拦截器 | options | 201 | 设置跨域所需的响应头,避免被浏览器的跨域策略阻拦 |
| 缓存响应拦截器 | cacheXxx | 202 | 设置缓存所需的响应头,使浏览器缓存当前请求<br>注:只对GET请求生效! |
| 响应篡改拦截器 | responseReplace | 203 | 篡改响应头,避免被浏览器的安全策略阻拦 |
| 脚本拦截器 | script | 211 | 注入JavaScript脚本到页面中,如:Github油猴脚本 |
## 4.2. 拦截配置说明书:
TODO:内容待完善
# 5. 域名白名单:
选择哪些域名不会被dev-sidecar处理。
**注意:** 该设置与【系统代理-自定义排除域名】的区别在于:
1. 前者只是被dev-sidecar自身忽略,后者则是写入系统设置、不会被(任何的)系统代理处理,在手动修改系统代理设置时务必小心后者可能残留的作用!
2. 在条目较多时,前者的性能不如后者,可能产生明显延迟。<br>
在config.json的 `proxy.excludeIpList:object` 中设置,**该字段**格式如下:<br>
> 注意:这里点号用来作为JSON object嵌套关系的缩写,冒号指明该条目的类型(主要用来区分object和list),并没有哪一个Object的key为 `proxy.excludeIpList`。为避免歧义,配置中object和list的key总不应包含点号。下同)
```json
{
"proxy": {
"excludeIpList": {
"example1.com": true,
"example2.com": false,
"example3.com": null,
"example4.com": {
"desc1": "域名对应字段设置为false时会被处理,null会移除现有设置(多用于远程配置)",
"desc2": "其他情况下就和设置true一样,不会被处理。因而你可以像这样插入注释",
"desc3": "同样的技巧可以用在其他本应设置一个bool值的地方",
"desc4": "原则上来说config.json不支持//形式的注释,但下文为了方便阅读,还是这么写了"
}
}
}
}
```
# 6. DNS服务管理:
用来配置在dev-sidecar中需要的指定DNS,出于保密和可靠起见建议使用DoH和DoT。<br>
在 `server.dns.provider:object` 中设置,**其中的每个条目** 格式如下:
## 6.1. 配置 `DNS-over-HTTPS`(简称DoH):
> 注:并非被所有DNS支持,但是保证只要能使用就一定匿名且可靠的DNS服务。
```json
"cloudflare": {
"type": "https", // 如果server上以"https://"开头指明了协议,就不需要写type了
"server": "https://1.1.1.1/dns-query",
"cacheSize": 1000
}
```
## 6.2. 配置 `DNS-over-TLS`(简称DoT):
> 并非被所有DNS支持,但是保证只要能使用就一定匿名且可靠的DNS服务。
```json
"cloudflareTLS": {
"type": "tls", // 如果server上以"tls://"开头指明了协议,就不需要写type了
"server": "1.1.1.1",
"port": 853, // 不配置时,默认端口为:853
"servername": "cloudflare-dns.com", // 需要伪造成的SNI
//"sni": "cloudflare-dns.com", // SNI缩写配置
"cacheSize": 1000
}
```
## 6.3. 配置 `TCP` 的DNS服务:
> 并非被所有DNS支持,该方法既不保密也不可靠
```json
"googleTCP": {
"type": "tcp", // 如果server上以"tcp://"开头指明了协议,就不需要写type了
"server": "8.8.8.8",
"port": 53, // 不配置时,默认端口为:53
"cacheSize": 1000
}
```
## 6.4. 配置 `UDP` 的DNS服务:
> 所有DNS服务器均支持UDP方式,但该方法既不保密也不可靠
```json
"google": {
"type": "udp", // 如果server上以"udp://"开头指明了协议,就不需要写type了
"server": "8.8.8.8",
"port": 53, // 不配置时,默认端口为:53
"cacheSize": 1000
}
```
# 7. DNS设置:
选择哪些域名需要使用指定的DNS(需要先在【DNS服务管理】中设置)获取IP。<br>
在config.json中的 `server.dns.mapping:key-value` 中设置,**其中的每个条目**格式如下:
```json
"*.example.com": "your-dns-name"
```
# 8. IP预设置:
为一些DNS无法获取的域名手动设置ip,起到类似于hosts的作用(仅在dev-sidecar开启时生效)。<br>
在config.json中的 `server.preSetIpList:object` 中设置,**其中的每个条目**格式如下:
```json
{
"example.com": {
"1.1.1.1": true, // 如果有多个IP,可以继续添加
"1.0.0.1": false, // 指定为false时,不使用该IP
"2.2.2.2": {
"desc": "这样可以合法的在配置中插入注释。上面使用的//注释方式在文件中是不允许的"
}
}
}
```
# 9. IP测速:
用来对从指定的DNS与IP预设置中获取到的IP测试TCP延迟,也可以用来测试DoH和DoT服务器的可用性,后者操作如下:先在【DNS服务管理】中配置好需要测试的DNS设置,然后在【IP测速】里添加一个没有设置【IP预设置】的辅助域名,并选择使用需检测的DNS进行解析。<br>
对于DoH/DoT而言,由于答案不能被篡改和窃听,所以辅助域名要么获得真实IP(说明可用)要么没有收到答案(说明不可用)。该方法不适用于常规TCP/UDP的DNS,因为它们没有加密,即使收到答案也可能被篡改而不可用)。<br>
在config.json中的 `server.dns.speedTest:object`中设置,**该条目** 格式如下:
```json
"speedTest": {
"hostnameList": [
"example1.com",
"example2.com"
],
"dnsProviders": [
"your-DNS-name-used-in-test1",
"your-DNS-name-used-in-test2"
]
}
```
================================================
FILE: doc/wiki/各平台安装说明.md
================================================
|平台|安装说明 |
|---|---|
| 【Windows】 | 下载后提示无法验证发行者时,选择保留即可 <br/>注意:开着ds重启电脑会导致无法上网,你可以再次打开ds,然后右键小图标退出ds即可。[更多说明](https://github.com/docmirror/dev-sidecar/issues/109)|
| 【Mac】 |安装时提示无法验证开发者时,请先取消<br/>然后去系统偏好设置->安全与隐私->下方已阻止使用DevSidecar<br/>选择仍要打开 |
| 【Ubuntu】 | [安装说明](https://github.com/docmirror/dev-sidecar/blob/master/doc/linux.md)|
|【其他Linux】| |
================================================
FILE: doc/wiki/解决Github访问不了或速度很慢的问题.md
================================================
> 注:请使用 `v2.0.0-RC2` 及以上版本,下载地址:https://github.com/docmirror/dev-sidecar/releases
目前,Github通过预设置的IP来访问的,选取测速排在前的IP。
可是,虽然IP测速延迟很低,但是依然会存在不同地区访问部分预设IP不通或很慢的问题。
如果碰到此问题,可以通过将预设IP设置为 `false` 来禁用访问慢的IP,以此达到切换IP的目的,如下图:
如果访问还慢,再将测速排在第1的IP再禁用掉,以此循环,将访问慢的IP都禁掉,直到选取到的IP访问Github速度很快为止。
> 假如:测速排第1的IP为 `20.27.177.113`,则将其配置为 `false`,或者删除该IP

================================================
FILE: eslint.config.js
================================================
import antfu from '@antfu/eslint-config'
export default antfu(
{
vue: {
vueVersion: 2,
},
rules: {
'style/brace-style': ['error', '1tbs'],
'style/space-before-function-paren': ['error', 'always'],
'import/newline-after-import': 'off',
'import/first': 'off',
'perfectionist/sort-imports': 'off',
'node/prefer-global/buffer': 'off',
'node/prefer-global/process': 'off',
'no-console': 'off',
},
ignores: [
'**/build/*',
'**/dist_electron',
],
formatters: {
css: true,
html: true,
markdown: 'prettier',
},
},
)
================================================
FILE: package.json
================================================
{
"name": "dev-sidecar-parent",
"type": "module",
"private": false,
"packageManager": "pnpm@9.13.2",
"author": "Greper",
"license": "MPL-2.0",
"scripts": {
"lint": "eslint .",
"lint:fix": "eslint . --fix"
},
"devDependencies": {
"@antfu/eslint-config": "^3.9.1",
"eslint": "^9.15.0",
"eslint-plugin-format": "^0.1.2"
},
"pnpm": {
"supportedArchitectures": {
"os": ["current"],
"cpu": ["x64", "arm64", "ia32"]
}
}
}
================================================
FILE: packages/cli/LICENSE
================================================
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
================================================
FILE: packages/cli/cli.js
================================================
#!/usr/bin/env node
require('./src')
================================================
FILE: packages/cli/package.json
================================================
{
"name": "@docmirror/dev-sidecar-cli",
"version": "2.0.1",
"private": false,
"description": "给开发者的加速代理工具",
"author": "docmirror.cn",
"license": "MPL-2.0",
"keywords": [
"dev-sidecar",
"github加速",
"google加速",
"代理"
],
"main": "src/index.js",
"bin": "./cli.js",
"scripts": {
"start": "node ./src"
},
"dependencies": {
"@docmirror/dev-sidecar": "workspace:*",
"@docmirror/mitmproxy": "workspace:*"
}
}
================================================
FILE: packages/cli/src/banner.txt
================================================
____ _____ _ __
/ __ \___ _ __ / ___/(_)___/ /__ _________ ______
/ / / / _ \ | / /_____\__ \/ / __ / _ \/ ___/ __ `/ ___/
/ /_/ / __/ |/ /_____/__/ / / /_/ / __/ /__/ /_/ / /
/_____/\___/|___/ /____/_/\__,_/\___/\___/\__,_/_/
==================== 开发者边车 ====================
================================================
FILE: packages/cli/src/index.js
================================================
const fs = require('node:fs')
const DevSidecar = require('@docmirror/dev-sidecar')
const jsonApi = require('@docmirror/mitmproxy/src/json')
// 启动服务
const mitmproxyPath = './mitmproxy'
async function startup () {
const banner = fs.readFileSync('./banner.txt')
console.log(banner.toString())
const configPath = './user_config.json5'
if (fs.existsSync(configPath)) {
const file = fs.readFileSync(configPath)
let userConfig
try {
userConfig = jsonApi.parse(file.toString())
console.info(`读取和解析 user_config.json5 成功:${configPath}`)
} catch (e) {
console.error(`读取或解析 user_config.json5 失败: ${configPath}, error:`, e)
userConfig = {}
}
DevSidecar.api.config.set(userConfig)
}
await DevSidecar.api.startup({ mitmproxyPath })
console.log('dev-sidecar 已启动')
}
async function onClose () {
console.log('on sigint ')
await DevSidecar.api.shutdown()
console.log('on closed ')
process.exit(0)
}
process.on('SIGINT', onClose)
startup()
================================================
FILE: packages/cli/src/mitmproxy.js
================================================
const fs = require('node:fs')
const path = require('node:path')
const server = require('@docmirror/mitmproxy')
const jsonApi = require('@docmirror/mitmproxy/src/json')
const log = require('@docmirror/mitmproxy/src/utils/util.log.server') // 当前脚本是在 server 的进程中执行的,所以使用 mitmproxy 中的logger
const home = process.env.USER_HOME || process.env.HOME || 'C:/Users/Administrator/'
let configPath
if (process.argv && process.argv.length > 3) {
configPath = process.argv[2]
} else {
configPath = path.join(home, '.dev-sidecar/running.json')
}
const configJson = fs.readFileSync(configPath)
log.info('读取 running.json by cli 成功:', configPath)
let config
try {
config = jsonApi.parse(configJson.toString())
} catch (e) {
log.error(`running.json 文件内容格式不正确,文件路径:${configPath},文件内容: ${configJson.toString()}, error:`, e)
config = {}
}
// const scriptDir = '../../gui/extra/scripts/'
// config.setting.script.defaultDir = path.join(__dirname, scriptDir)
// const pacFilePath = '../../gui/extra/pac/pac.txt'
// config.plugin.overwall.pac.customPacFilePath = path.join(__dirname, pacFilePath)
config.setting.rootDir = path.join(__dirname, '../../gui/')
log.info(`start mitmproxy by cli, configPath: ${configPath}`)
server.start(config)
================================================
FILE: packages/cli/src/user_config.json5
================================================
{
"app": {
"autoStart": {
"enabled": true
},
"mode": "default"
},
"plugin": {
"node": {
"setting": {
"yarnRegistry": "null"
}
},
"git": {
"enabled": true
},
"overwall": {
"enabled": false,
"targets": {
"*gagedigital.com": true,
"*yonsz.net": true,
"*bootstrapcdn.com": true,
"*cloudflare.com": true,
"help.yonsz.net": true
}
}
},
"server": {
"intercepts": {
"dev-sidecar.docmirror.cn": {
".*": {
"proxy": "dev-sidecar-preview.docmirror.cn"
}
},
"test1111.gagedigital.com": {
".*": {
"proxy": "test1.gagedigital.com"
}
}
}
}
}
================================================
FILE: packages/core/LICENSE
================================================
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
================================================
FILE: packages/core/index.js
================================================
module.exports = require('./src')
// TODO 这是一个解谜游戏 ↓ ↓ ↓ ↓ ↓ ↓ ,如果你破解了它,请不要公开,好好用它来学习和查资料吧(特别注意:为了你的人身安全,请不要用它来查看和发表不当言论,你懂得)。
/**
\u0061\u0048\u0052\u0030\u0063\u0044\u006f\u0076\u004c\u0032\u0052\u006c\u0064\u0069\u0031\u007a\u0061\u0057\u0052\u006c\u0059\u0032\u0046\u0079\u004c\u006d\u0052\u0076\u0059\u0032\u0031\u0070\u0063\u006e\u004a\u0076\u0063\u0069\u0035\u006a\u0062\u0069\u0039\u0035\u0062\u0033\u0056\u006d\u0061\u0057\u0035\u006b\u0061\u0058\u0051\u0076\u0061\u0057\u0035\u006b\u005a\u0058\u0067\u0075\u0061\u0048\u0052\u0074\u0062\u0041\u003d\u003d
*/
// 这个项目里有一点点解谜提示: https://github.com/fast-crud/fast-crud (打开拉到最下面)
================================================
FILE: packages/core/package.json
================================================
{
"name": "@docmirror/dev-sidecar",
"version": "2.0.1",
"private": false,
"description": "给开发者的加速代理工具",
"author": "docmirror.cn",
"license": "MPL-2.0",
"keywords": [
"dev-sidecar",
"github加速",
"google加速",
"代理"
],
"main": "src/index.js",
"scripts": {
"test": "mocha"
},
"dependencies": {
"@starknt/sysproxy": "^0.0.3",
"@vscode/sudo-prompt": "^9.3.1",
"fix-path": "^3.0.0",
"iconv-lite": "^0.6.3",
"lodash": "^4.17.21",
"log4js": "^6.9.1",
"node-powershell": "^4.0.0",
"spawn-sync": "^2.0.0",
"winreg": "^1.2.5"
},
"devDependencies": {
"chai": "^4.3.4",
"mocha": "^8.2.1"
}
}
================================================
FILE: packages/core/src/config/index.js
================================================
const path = require('node:path')
const configLoader = require('./local-config-loader')
function getRootCaCertPath () {
return path.join(configLoader.getUserBasePath(), '/dev-sidecar.ca.crt')
}
function getRootCaKeyPath () {
return path.join(configLoader.getUserBasePath(), '/dev-sidecar.ca.key.pem')
}
const defaultConfig = {
app: {
mode: 'default',
autoStart: {
enabled: false,
},
remoteConfig: {
enabled: true,
// 共享远程配置地址
url: 'https://gitee.com/wangliang181230/dev-sidecar/raw/docmirror2.x/packages/core/src/config/remote_config.json',
// 个人远程配置地址
personalUrl: '',
},
startShowWindow: true, // 启动时是否打开窗口:true=打开窗口, false=隐藏窗口
needCheckHideWindow: true, // 是否需要在隐藏窗口时做检查
showHideShortcut: 'Alt + S', // 显示/隐藏窗口快捷键
windowSize: { width: 900, height: 750 }, // 启动时,窗口的尺寸
theme: 'dark', // 主题:light=亮色, dark=暗色
autoChecked: true, // 是否自动检查更新
skipPreRelease: true, // 是否忽略预发布版本
dock: {
hideWhenWinClose: false,
},
closeStrategy: 0,
showShutdownTip: true,
// 日志相关配置
logFileSavePath: path.join(configLoader.getUserBasePath(), '/logs'), // 日志文件保存路径
keepLogFileCount: 15, // 保留日志文件数
maxLogFileSize: 1, // 最大日志文件大小
maxLogFileSizeUnit: 'GB', // 最大日志文件大小单位
},
server: {
enabled: true,
host: '127.0.0.1',
port: 31181,
setting: {
NODE_TLS_REJECT_UNAUTHORIZED: true,
verifySsl: true,
script: {
enabled: true,
defaultDir: './extra/scripts/',
},
userBasePath: configLoader.getUserBasePath(),
rootCaFile: {
certPath: getRootCaCertPath(),
keyPath: getRootCaKeyPath(),
},
// 默认超时时间配置
defaultTimeout: 20000, // 请求超时时间
defaultKeepAliveTimeout: 30000, // 连接超时时间
// 指定域名超时时间配置
timeoutMapping: {
'github.com': {
timeout: 20000,
keepAliveTimeout: 30000,
},
},
// 慢速IP延迟时间:测速超过该值时,则视为延迟高,显示为橙色
lowSpeedDelay: 200,
},
compatible: {
// **** 自定义兼容配置 **** //
// connect阶段所需的兼容性配置
connect: {
// 参考配置(无path)
// 'xxx.xxx.xxx.xxx:443': {
// ssl: false
// }
},
// request阶段所需的兼容性配置
request: {
// 参考配置(配置方式同 `拦截配置`)
// 'xxx.xxx.xxx.xxx:443': {
// '.*': {
// rejectUnauthorized: false
// }
// }
},
},
intercept: {
enabled: true,
},
intercepts: {
'github.com': {
'.*': {
sni: 'baidu.com',
},
'^(/[\\w-.]+){2,}/?(\\?.*)?$': {
// 篡改猴插件地址,以下是高速镜像地址
tampermonkeyScript: 'https://gitee.com/wangliang181230/dev-sidecar/raw/scripts/tampermonkey.js',
// Github油猴脚本地址,以下是高速镜像地址
script: 'https://gitee.com/wangliang181230/dev-sidecar/raw/scripts/GithubEnhanced-High-Speed-Download.user.js',
remark: '注:上面所使用的脚本地址,为高速镜像地址。',
desc: '油猴脚本:高速下载 Git Clone/SSH、Release、Raw、Code(ZIP) 等文件 (公益加速)、项目列表单文件快捷下载、添加 git clone 命令',
},
// 以下三项暂时先注释掉,因为已经有油猴脚本提供高速下载地址了。
// '/.*/.*/releases/download/': {
// redirect: 'gh.api.99988866.xyz/https://github.com',
// desc: 'release文件加速下载跳转地址'
// },
// '/.*/.*/archive/': {
// redirect: 'gh.api.99988866.xyz/https://github.com'
// },
// 以下代理地址不支持该类资源的代理,暂时注释掉
// '/.*/.*/blame/': {
// redirect: 'gh.api.99988866.xyz/https://github.com'
// },
'/fluidicon.png': {
cacheDays: 365,
desc: 'Github那只猫的图片,缓存1年',
},
'^(/[^/]+){2}/pull/\\d+/open_with_menu.*$': {
cacheDays: 7,
desc: 'PR详情页:标题右边那个Code按钮的HTML代码请求地址,感觉上应该可以缓存。暂时先设置为缓存7天',
},
'^((/[^/]+){2,})/raw((/[^/]+)+\\.(jpg|jpeg|png|gif))(\\?.*)?$': {
// eslint-disable-next-line no-template-curly-in-string
proxy: 'https://raw.githubusercontent.com${m[1]}${m[3]}',
sni: 'baidu.com',
cacheDays: 7,
desc: '仓库内图片,重定向改为代理,并缓存7天。',
},
'^((/[^/]+){2,})/raw((/[^/]+)+\\.js)(\\?.*)?$': {
// eslint-disable-next-line no-template-curly-in-string
proxy: 'https://raw.githubusercontent.com${m[1]}${m[3]}',
sni: 'baidu.com',
responseReplace: { headers: { 'content-type': 'application/javascript; charset=utf-8' } },
desc: '仓库内脚本,重定向改为代理,并设置响应头Content-Type。作用:方便script拦截器直接使用,避免引起跨域问题和脚本内容限制问题。',
},
},
'github.githubassets.com': {
'.*': {
sni: 'baidu.com',
},
},
'camo.githubusercontent.com': {
'^[a-zA-Z0-9/]+(\\?.*)?$': {
cacheDays: 365,
desc: '图片,缓存1年',
},
},
'collector.github.com': {
'.*': {
sni: 'baidu.com',
},
},
'customer-stories-feed.github.com': {
'.*': { proxy: 'customer-stories-feed.fastgit.org' },
},
'user-images.githubusercontent.com': {
'^/.*\\.png(\\?.*)?$': {
cacheDays: 365,
desc: '用户在PR或issue等内容中上传的图片,缓存1年。注:每张图片都有唯一的ID,不会重复,可以安心缓存',
},
},
'private-user-images.githubusercontent.com': {
'^/.*\\.png(\\?.*)?$': {
cacheDays: 30,
cacheHours: null,
desc: '用户在PR或issue等内容中上传的图片,缓存30天',
},
},
'avatars.githubusercontent.com': {
'^/u/\\d+(\\?.*)?$': {
cacheDays: 365,
desc: '用户头像,缓存1年',
},
},
'api.github.com': {
'^/_private/browser/stats$': {
success: true,
desc: 'github的访问速度分析上传,没有必要,直接返回成功',
},
'.*': {
sni: 'baidu.com',
},
},
'*.docker.com': {
'.*': {
sni: 'baidu.com',
},
},
'login.docker.com': {
'/favicon.ico': {
proxy: 'hub.docker.com',
sni: 'baidu.com',
desc: '登录页面的ico,采用hub.docker.com的',
},
},
// google cdn
'www.google.com': {
'/recaptcha/.*': { proxy: 'www.recaptcha.net' },
// '.*': {
// proxy: 'gg.docmirror.top/_yxorp',
// desc: '呀,被你发现了,偷偷的用,别声张'
// }
},
'www.gstatic.com': {
'/recaptcha/.*': { proxy: 'www.recaptcha.net' },
},
'ajax.googleapis.com': {
'.*': {
proxy: 'ajax.lug.ustc.edu.cn',
backup: ['gapis.geekzu.org'],
test: 'ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js',
},
},
'fonts.googleapis.com': {
'.*': {
proxy: 'fonts.loli.net',
test: 'https://fonts.googleapis.com/css?family=Oswald',
},
},
'themes.googleapis.com': {
'.*': {
proxy: 'themes.loli.net',
backup: ['themes.proxy.ustclug.org'],
},
},
'themes.googleusercontent.com': {
'.*': { proxy: 'google-themes.proxy.ustclug.org' },
},
// 'fonts.gstatic.com': {
// '.*': {
// proxy: 'gstatic.loli.net',
// backup: ['fonts-gstatic.proxy.ustclug.org']
// }
// },
'clients*.google.com': { '.*': { abort: false, desc: '设置abort:true可以快速失败,节省时间' } },
'www.googleapis.com': { '.*': { abort: false, desc: '设置abort:true可以快速失败,节省时间' } },
'lh*.googleusercontent.com': { '.*': { abort: false, desc: '设置abort:true可以快速失败,节省时间' } },
// mapbox-node-binary.s3.amazonaws.com/sqlite3/v5.0.0/napi-v3-win32-x64.tar.gz
'*.s3.1amazonaws1.com': {
'/sqlite3/.*': {
redirect: 'npm.taobao.org/mirrors',
},
},
// 'packages.elastic.co': { '.*': { proxy: 'elastic.proxy.ustclug.org' } },
// 'ppa.launchpad.net': { '.*': { proxy: 'launchpad.proxy.ustclug.org' } },
// 'archive.cloudera.com': { '.*': { regexp: '/cdh5/.*', proxy: 'cloudera.proxy.ustclug.org' } },
// 'downloads.lede-project.org': { '.*': { proxy: 'lede.proxy.ustclug.org' } },
// 'downloads.openwrt.org': { '.*': { proxy: 'openwrt.proxy.ustclug.org' } },
// 'secure.gravatar.com': { '.*': { proxy: 'gravatar.proxy.ustclug.org' } },
'*.carbonads.com': {
'/carbon.*': {
abort: true,
desc: '广告拦截',
},
},
'*.buysellads.com': {
'/ads/.*': {
abort: true,
desc: '广告拦截',
},
},
},
// 预设置IP列表
preSetIpList: {
'github.com': {
'4.237.22.38': true,
'20.26.156.215': true,
'20.27.177.113': true,
'20.87.245.0': true,
'20.200.245.247': true,
'20.201.28.151': true,
'20.205.243.166': true,
'140.82.113.3': true,
'140.82.114.4': true,
'140.82.116.3': true,
'140.82.116.4': true,
'140.82.121.3': true,
'140.82.121.4': true,
},
'api.github.com': {
'20.26.156.210': true,
'20.27.177.116': true,
'20.87.245.6': true,
'20.200.245.245': true,
'20.201.28.148': true,
'20.205.243.168': true,
'20.248.137.49': true,
'140.82.112.5': true,
'140.82.113.6': true,
'140.82.116.6': true,
'140.82.121.6': true,
},
'codeload.github.com': {
'20.26.156.216': true,
'20.27.177.114': true,
'20.87.245.7': true,
'20.200.245.246': true,
'20.201.28.149': true,
'20.205.243.165': true,
'20.248.137.55': true,
'140.82.113.9': true,
'140.82.114.10': true,
'140.82.116.10': true,
'140.82.121.9': true,
},
'*.githubusercontent.com': {
'146.75.92.133': true,
'199.232.88.133': true,
'199.232.144.133': true,
},
'viewscreen.githubusercontent.com': {
'140.82.112.21': true,
'140.82.112.22': true,
'140.82.113.21': true,
'140.82.113.22': true,
'140.82.114.21': true,
'140.82.114.22': true,
},
'github.io': {
'185.199.108.153': true,
'185.199.109.153': true,
'185.199.110.153': true,
'185.199.111.153': true,
},
'*.githubassets.com': {
'185.199.108.154': true,
'185.199.109.154': true,
'185.199.110.154': true,
'185.199.111.154': true,
},
'^(analytics|ghcc)\\.githubassets\\.com$': {
'185.199.108.153': true,
'185.199.110.153': true,
'185.199.109.153': true,
'185.199.111.153': true,
},
'*.pixiv.net': {
// 以下为 `cdn-origin.pixiv.net` 域名的IP
'210.140.139.154': true,
'210.140.139.157': true,
'210.140.139.160': true,
},
'hub.docker.com': {
'44.221.37.199': true,
'52.44.227.212': true,
'54.156.140.159': true,
},
'sessions-bugsnag.docker.com': {
'44.221.37.199': true,
'52.44.227.212': true,
'54.156.140.159': true,
},
},
whiteList: {
'*.cn': true,
'cn.*': true,
'*china*': true,
'*.dingtalk.com': true,
'*.apple.com': true,
'*.microsoft.com': true,
'*.alipay.com': true,
'*.qq.com': true,
'*.baidu.com': true,
'192.168.*': true,
},
dns: {
providers: {
aliyun: {
type: 'https',
server: 'https://dns.alidns.com/dns-query',
cacheSize: 1000,
},
cloudflare: {
type: 'https',
server: 'https://1.1.1.1/dns-query',
cacheSize: 1000,
},
quad9: {
type: 'https',
server: 'https://9.9.9.9/dns-query',
cacheSize: 1000,
},
safe360: {
type: 'https',
server: 'https://doh.360.cn/dns-query',
cacheSize: 1000,
forSNI: true,
},
rubyfish: {
type: 'https',
server: 'https://rubyfish.cn/dns-query',
cacheSize: 1000,
},
},
mapping: {
'*.github.com': 'quad9',
'*github*.com': 'quad9',
'*.github.io': 'quad9',
'*.docker.com': 'quad9',
'*.stackoverflow.com': 'quad9',
'*.electronjs.org': 'quad9',
'*.amazonaws.com': 'quad9',
'*.yarnpkg.com': 'quad9',
'*.cloudfront.net': 'quad9',
'*.cloudflare.com': 'quad9',
'img.shields.io': 'quad9',
'*.vuepress.vuejs.org': 'quad9',
'*.gh.docmirror.top': 'quad9',
'*.v2ex.com': 'quad9',
'*.pypi.org': 'quad9',
'*.jetbrains.com': 'quad9',
'*.azureedge.net': 'quad9',
},
speedTest: {
enabled: true,
interval: 300000,
hostnameList: ['github.com'],
dnsProviders: ['cloudflare', 'safe360', 'rubyfish'],
},
},
},
proxy: {},
plugin: {},
help: {
dataList: [
{
title: '查看DevSidecar的说明文档(Wiki)',
url: 'https://github.com/docmirror/dev-sidecar/wiki',
},
{
title: '为了展示更多帮助信息,请启用 “远程配置” 功能!!!',
},
],
},
}
// 从本地文件中加载配置
defaultConfig.configFromFiles = configLoader.getConfigFromFiles(configLoader.getUserConfig(), defaultConfig)
module.exports = defaultConfig
================================================
FILE: packages/core/src/config/local-config-loader.js
================================================
const fs = require('node:fs')
const path = require('node:path')
const lodash = require('lodash')
const jsonApi = require('@docmirror/mitmproxy/src/json')
const mergeApi = require('../merge')
const logOrConsole = require('../utils/util.log-or-console')
function getUserBasePath (autoCreate = true) {
const userHome = process.env.USERPROFILE || process.env.HOME || '/'
const dir = path.resolve(userHome, './.dev-sidecar')
// 自动创建目录
if (autoCreate && !fs.existsSync(dir)) {
fs.mkdirSync(dir)
}
return dir
}
function loadConfigFromFile (configFilePath) {
if (configFilePath == null) {
logOrConsole.error('配置文件地址为空')
return {}
}
if (!fs.existsSync(configFilePath)) {
logOrConsole.info('配置文件不存在:', configFilePath)
return {} // 文件不存在,返回空配置
}
// 读取配置文件
let configStr
try {
configStr = fs.readFileSync(configFilePath)
} catch (e) {
logOrConsole.error('读取配置文件失败:', configFilePath, ', error:', e)
return {}
}
// 解析配置文件
try {
const config = jsonApi.parse(configStr)
logOrConsole.info('读取配置文件成功:', configFilePath)
return config
} catch (e) {
logOrConsole.error(`解析配置文件失败,文件内容格式不正确,文件路径: ${configFilePath},文件内容:${configStr},error:`, e)
return {}
}
}
function getUserConfigPath () {
const dir = getUserBasePath()
// 兼容1.7.3及以下版本的配置文件处理逻辑
const newFilePath = path.join(dir, '/config.json')
const oldFilePath = path.join(dir, '/config.json5')
if (!fs.existsSync(newFilePath) && fs.existsSync(oldFilePath)) {
return oldFilePath // 如果新文件不存在,但旧文件存在,则返回旧文件路径
}
return newFilePath
}
function getUserConfig () {
const configFilePath = getUserConfigPath()
return loadConfigFromFile(configFilePath)
}
function getRemoteConfigPath (suffix = '') {
const dir = getUserBasePath()
return path.join(dir, `/remote_config${suffix}.json5`)
}
function getRemoteConfig (suffix = '') {
const remoteConfigFilePath = getRemoteConfigPath(suffix)
return loadConfigFromFile(remoteConfigFilePath)
}
function getAutomaticCompatibleConfigPath () {
const dir = getUserBasePath()
return path.join(dir, '/automaticCompatibleConfig.json')
}
/**
* 从文件读取配置
*
* @param userConfig 用户配置
* @param defaultConfig 默认配置
*/
function getConfigFromFiles (userConfig, defaultConfig) {
const merged = userConfig != null ? lodash.cloneDeep(userConfig) : {}
const personalRemoteConfig = getRemoteConfig('_personal')
const shareRemoteConfig = getRemoteConfig()
mergeApi.doMerge(merged, personalRemoteConfig) // 先合并一次个人远程配置,使配置顺序在前
mergeApi.doMerge(merged, shareRemoteConfig) // 先合并一次共享远程配置,使配置顺序在前
mergeApi.doMerge(merged, defaultConfig) // 合并默认配置,顺序排在最后
mergeApi.doMerge(merged, shareRemoteConfig) // 再合并一次共享远程配置,使配置生效
mergeApi.doMerge(merged, personalRemoteConfig) // 再合并一次个人远程配置,使配置生效
if (userConfig != null) {
mergeApi.doMerge(merged, userConfig) // 再合并一次用户配置,使用户配置重新生效
}
// 删除为null及[delete]的项
mergeApi.deleteNullItems(merged)
logOrConsole.info('加载及合并远程配置完成')
return merged
}
module.exports = {
getUserBasePath,
loadConfigFromFile,
getUserConfigPath,
getUserConfig,
getRemoteConfigPath,
getRemoteConfig,
getAutomaticCompatibleConfigPath,
getConfigFromFiles,
}
================================================
FILE: packages/core/src/config/remote_config.json5
================================================
{
"server": {
"compatible": {
"connect": {
"218.18.106.132:443": {
"ssl": true
}
},
"request": {
"218.18.106.132:443": {
"rejectUnauthorized": false
}
}
},
"intercepts": {
"github.com": {
"^(/[\\w-.]+){2,}/?(\\?.*)?$": {
"tampermonkeyScript": "https://gitee.com/wangliang181230/dev-sidecar/raw/scripts/tampermonkey.js",
"script": "https://gitee.com/wangliang181230/dev-sidecar/raw/scripts/GithubEnhanced-High-Speed-Download.user.js"
},
"^(/[^/]+){2}/releases/download/.*$": {
"redirect": "ghp.ci/https://github.com",
"desc": "release文件加速下载重定向地址"
},
"^(/[^/]+){2}/archive/.*\\.(zip|tar.gz)$": {
"redirect": "ghp.ci/https://github.com",
"desc": "release源代码加速下载重定向地址"
},
"^((/[^/]+){2,})/raw((/[^/]+)+\\.(jpg|jpeg|png|gif))(\\?.*)?$": {
"sni": "baidu.com" // proxy拦截器不会使用 .* 中的sni配置,故补充此配置
},
"^((/[^/]+){2,})/raw((/[^/]+)+\\.js)(\\?.*)?$": {
"sni": "baidu.com" // proxy拦截器不会使用 .* 中的sni配置,故补充此配置
}
},
"api.github.com": {
".*": {
"sni": "baidu.com"
}
},
"github.githubassets.com": {
".*": {
"sni": "baidu.com"
}
},
"avatars.githubusercontent.com": {
".*": {
"sni": "baidu.com"
}
},
"camo.githubusercontent.com": {
".*": {
"sni": "baidu.com"
}
},
"collector.github.com": {
".*": {
"sni": "baidu.com"
}
},
"www.gstatic.com": {
"/recaptcha/.*": {
"proxy": "www.recaptcha.net"
}
}
},
"preSetIpList": {
"github.com": [
"4.237.22.38",
"20.26.156.215",
"20.27.177.113",
"20.87.245.0",
"20.200.245.247",
"20.201.28.151",
"20.205.243.166",
"140.82.113.3",
"140.82.114.4",
"140.82.116.3",
"140.82.116.4",
"140.82.121.3",
"140.82.121.4"
],
"hub.docker.com": null // 1.8.2版本中,该域名的预设IP有问题,现在远程配置中删除
},
"dns": {
"mapping": {
"*.jetbrains.com": "quad9",
"*.azureedge.net": "quad9",
"*.stackoverflow.com": "quad9"
},
"speedTest": {
"interval": 300000
}
},
"whiteList": {
"*.icloud.com": true,
"*.lenovo.net": true
}
},
"proxy": {
"remoteDomesticDomainAllowListFileUrl": "https://raw.kkgithub.com/pluwen/china-domain-allowlist/main/allow-list.sorl",
"excludeIpList": {
// Github文件上传所使用的域名,被DS代理会导致文件上传经常失败,从系统代理中排除掉
"objects-origin.githubusercontent.com": true,
// Github通过Actions上传的文件,下载时所需的域名,从系统代理中排除掉,否则下载会失败
"*.windows.net": true,
// Github下载release文件的高速镜像地址
"*.ghproxy.net": true,
"*.ghp.ci": true,
"*.kkgithub.com": true,
// Github建站域名
"*.github.io": true,
// bilibili相关
"*.bilicomic.com": true,
// 中国移动云盘登录API
"[2049:8c54:813:10c::140]": true,
"[2409:8a0c:a442:ff40:a51f:4b9c:8b41:25ea]": true,
"[2606:2800:147:120f:30c:1ba0:fc6:265a]": true,
// 移动云盘相关
"*.cmicapm.com": true,
// cloudflare:排除以下域名,cloudflare的人机校验会更快,成功率更高。
"*.cloudflare.com": true,
"*.cloudflare-cn.com": true,
// VS相关
"*.microsoftonline.com": true, // 此域名不排除的话,部分功能将出现异常
"*.msecnd.net": true,
"*.msedge.net": true,
// 卡巴斯基升级域名
"*kaspersky*.com": true,
"*.upd.kaspersky.com": true,
// sandbox沙盒域名
"*.sandboxie-plus.com": true,
// 无忧论坛
"*.wuyou.net": true,
// python建图包域名(浏览器)
"*.pyecharts.org": true,
// 教育网站
"*.bcloudlink.com": true,
// 奇迹秀(资源)
"*.qijishow.com": true,
// Z-Library
"*.z-lib.fo": true,
// Finalshell(Linux学习网)
"*.finalshell.com": true,
// MineBBS(我的世界中文论坛)
"*.minebbs.com": true,
// 我的世界插件网
"*.spigotmc.org": true,
// bd测试
"*.virustotal.com": true,
// 未知
"*.youdemai.com": true,
"*.casualthink.com": true,
"44.239.165.12": true,
"3.164.110.117": true
}
},
"plugin": {
"overwall": {
"targets": {
"*.github.com": true,
"*github*.com": true,
"*.nodejs.org": true,
"*.npmjs.com": true,
"*.wikimedia.org": true,
"*.v2ex.com": true,
"*.azureedge.net": true,
"*.cloudfront.net": true,
"*.bing.com": true,
"*.discourse-cdn.com": true,
"*.gravatar.com": true,
"*.docker.com": true,
"*.vueuse.org": true,
"*.elastic.co": true,
"*.optimizely.com": true,
"*.stackpathcdn.com": true,
"*.fastly.net": true,
"*.cloudflare.com": true,
"*.233v2.com": true,
"*.v2fly.org": true,
"*.telegram.org": true,
"*.amazon.com": true,
"*.googleapis.com": true,
"*.google-analytics.com": true,
"*.cloudflareinsights.com": true,
"*.intlify.dev": true,
"*.segment.io": true,
"*.shields.io": true,
"*.jsdelivr.net": true,
"*.z-library.sk": true,
"*.zlibrary*.se": true,
// 维基百科
"*.wikipedia-on-ipfs.org": true,
// ChatGPT
"*.oaiusercontent.com": true, // 在ChatGPT中生成文件并下载所需的域名
// Pixiv相关
"*.pixiv.org": true,
"*.fanbox.cc": true,
"*.onesignal.com": true // pixiv站点,会加载该域名下的js脚本
},
"pac": {
"pacFileUpdateUrl": "https://raw.kkgithub.com/gfwlist/gfwlist/master/gfwlist.txt"
}
}
}
}
================================================
FILE: packages/core/src/config-api.js
================================================
const fs = require('node:fs')
const jsonApi = require('@docmirror/mitmproxy/src/json')
const lodash = require('lodash')
const request = require('request')
const defConfig = require('./config/index.js')
const mergeApi = require('./merge.js')
const Shell = require('./shell')
const log = require('./utils/util.log.core')
const configLoader = require('./config/local-config-loader')
let configTarget = lodash.cloneDeep(defConfig)
function get () {
return configTarget
}
let timer
const configApi = {
async startAutoDownloadRemoteConfig () {
if (timer != null) {
clearInterval(timer)
}
const download = async () => {
try {
await configApi.downloadRemoteConfig()
configApi.reload()
} catch (e) {
log.error('定时下载远程配置并重载配置失败', e)
}
}
await download()
timer = setInterval(download, 24 * 60 * 60 * 1000) // 1天
},
async downloadRemoteConfig () {
if (get().app.remoteConfig.enabled !== true) {
// 删除保存的远程配置文件
configApi.deleteRemoteConfigFile()
configApi.deleteRemoteConfigFile('_personal')
return
}
const remoteConfig = get().app.remoteConfig
await configApi.doDownloadRemoteConfig(remoteConfig.url)
await configApi.doDownloadRemoteConfig(remoteConfig.personalUrl, '_personal')
},
doDownloadRemoteConfig (remoteConfigUrl, suffix = '') {
if (!remoteConfigUrl) {
// 删除保存的远程配置文件
configApi.deleteRemoteConfigFile(suffix)
return
}
return new Promise((resolve, reject) => {
log.info('开始下载远程配置:', remoteConfigUrl)
const headers = {
'Cache-Control': 'no-cache', // 禁止使用缓存
'Pragma': 'no-cache', // 禁止使用缓存
}
if (remoteConfigUrl.startsWith('https://raw.githubusercontent.com/')) {
headers['Server-Name'] = 'baidu.com'
}
request(remoteConfigUrl, { headers }, (error, response, body) => {
if (error) {
log.error(`下载远程配置失败: ${remoteConfigUrl}, error:`, error, ', response:', response, ', body:', body)
reject(error)
return
}
if (response && response.statusCode === 200) {
if (body == null || body.length < 2) {
log.warn('下载远程配置成功,但内容为空:', remoteConfigUrl)
resolve()
return
} else {
log.info('下载远程配置成功:', remoteConfigUrl)
}
// 尝试解析远程配置,如果解析失败,则不保存它
let remoteConfig
try {
remoteConfig = jsonApi.parse(body)
} catch {
log.error(`远程配置内容格式不正确, url: ${remoteConfigUrl}, body: ${body}`)
remoteConfig = null
}
if (remoteConfig != null) {
const remoteSavePath = configLoader.getRemoteConfigPath(suffix)
try {
fs.writeFileSync(remoteSavePath, body)
log.info('保存远程配置文件成功:', remoteSavePath)
} catch (e) {
log.error('保存远程配置文件失败:', remoteSavePath, ', error:', e)
reject(new Error(`保存远程配置文件失败: ${e.message}`))
return
}
} else {
log.warn('远程配置对象为空:', remoteConfigUrl)
}
resolve()
} else {
log.error(`下载远程配置失败: ${remoteConfigUrl}, response:`, response, ', body:', body)
let message
if (response) {
message = `下载远程配置失败: ${remoteConfigUrl}, message: ${response.message}, code: ${response.statusCode}`
} else {
message = `下载远程配置失败: response: ${response}`
}
reject(new Error(message))
}
})
})
},
deleteRemoteConfigFile (suffix = '') {
const remoteSavePath = configLoader.getRemoteConfigPath(suffix)
if (fs.existsSync(remoteSavePath)) {
fs.unlinkSync(remoteSavePath)
log.info('删除远程配置文件成功:', remoteSavePath)
}
},
readRemoteConfigStr (suffix = '') {
try {
const path = configLoader.getRemoteConfigPath(suffix)
if (fs.existsSync(path)) {
const file = fs.readFileSync(path)
log.info('读取远程配置文件内容成功:', path)
return file.toString()
} else {
log.info('远程配置文件不存在:', path)
}
} catch (e) {
log.error('读取远程配置文件内容失败:', e)
}
return '{}'
},
/**
* 保存自定义的 config
* @param newConfig
*/
save (newConfig) {
// 对比默认config的异同
const defConfig = configApi.cloneDefault()
// 如果开启了远程配置,则读取远程配置,合并到默认配置中
if (get().app.remoteConfig.enabled === true) {
if (get().app.remoteConfig.url) {
mergeApi.doMerge(defConfig, configLoader.getRemoteConfig())
}
if (get().app.remoteConfig.personalUrl) {
mergeApi.doMerge(defConfig, configLoader.getRemoteConfig('_personal'))
}
}
// 计算新配置与默认配置(启用远程配置时,含远程配置)的差异
const diffConfig = mergeApi.doDiff(defConfig, newConfig)
// 将差异作为用户配置保存到 config.json 中
const configPath = configLoader.getUserConfigPath()
try {
fs.writeFileSync(configPath, jsonApi.stringify(diffConfig))
log.info('保存 config.json 自定义配置文件成功:', configPath)
} catch (e) {
log.error('保存 config.json 自定义配置文件失败:', configPath, ', error:', e)
throw e
}
// 重载配置
const allConfig = configApi.set(diffConfig)
return {
diffConfig,
allConfig,
}
},
doMerge: mergeApi.doMerge,
doDiff: mergeApi.doDiff,
/**
* 读取 config.json 后,合并配置
*/
reload () {
const userConfig = configLoader.getUserConfig()
return configApi.set(userConfig) || {}
},
update (partConfig) {
const newConfig = lodash.merge(configApi.get(), partConfig)
configApi.save(newConfig)
},
get,
set (newConfig) {
if (newConfig == null) {
log.warn('newConfig 为空,不做任何操作')
return configTarget
}
return configApi.load(newConfig)
},
load (newConfig) {
const config = configLoader.getConfigFromFiles(newConfig, defConfig)
configTarget = config
return config
},
cloneDefault () {
return lodash.cloneDeep(defConfig)
},
addDefault (key, defValue) {
lodash.set(defConfig, key, defValue)
},
// 移除用户配置,用于恢复出厂设置功能
async removeUserConfig () {
const configPath = configLoader.getUserConfigPath()
if (fs.existsSync(configPath)) {
// 读取 config.json 文件内容
const fileOriginalStr = fs.readFileSync(configPath).toString()
// 判断文件内容是否为空或空配置
const fileStr = fileOriginalStr.replace(/\s/g, '')
if (fileStr.length < 5) {
try {
fs.writeFileSync(configPath, '{}')
} catch (e) {
log.warn('简化用户配置文件失败:', configPath, ', error:', e)
}
return false // config.json 内容为空,或为空json
}
// 备份用户自定义配置文件
const bakConfigPath = `${configPath}.${Date.now()}.bak.json`
try {
fs.writeFileSync(bakConfigPath, fileOriginalStr)
log.info('备份用户配置文件成功:', bakConfigPath)
} catch (e) {
log.error('备份用户配置文件失败:', bakConfigPath, ', error:', e)
throw e
}
// 原配置文件内容设为空
try {
fs.writeFileSync(configPath, '{}')
} catch (e) {
log.error('初始化用户配置文件失败:', configPath, ', error:', e)
throw e
}
// 重新加载配置
configApi.load(null)
return true // 删除并重新加载配置成功
} else {
return false // config.json 文件不存在
}
},
resetDefault (key) {
if (key) {
let value = lodash.get(defConfig, key)
value = lodash.cloneDeep(value)
lodash.set(configTarget, key, value)
} else {
configTarget = lodash.cloneDeep(defConfig)
}
return configTarget
},
async getVariables (type) {
const method = type === 'npm' ? Shell.getNpmEnv : Shell.getSystemEnv
const currentMap = await method()
const list = []
const map = configTarget.variables[type]
for (const key in map) {
const exists = currentMap[key] != null
list.push({
key,
value: map[key],
exists,
})
}
return list
},
async setVariables (type) {
const list = await configApi.getVariables(type)
const noSetList = list.filter((item) => {
return !item.exists
})
if (list.length > 0) {
const context = {
root_ca_cert_path: configApi.get().server.setting.rootCaFile.certPath,
}
for (const item of noSetList) {
if (item.value.includes('${')) {
for (const key in context) {
item.value = item.value.replcace(new RegExp(`\${${key}}`, 'g'), context[key])
}
}
}
const method = type === 'npm' ? Shell.setNpmEnv : Shell.setSystemEnv
return method({ list: noSetList })
}
},
}
module.exports = configApi
================================================
FILE: packages/core/src/event.js
================================================
const listener = {}
let index = 1
function register (channel, handle, order = 10) {
let handles = listener[channel]
if (handles == null) {
handles = listener[channel] = []
}
handles.push({ id: index, handle, order })
handles.sort((a, b) => {
return a.order - b.order
})
return index++
}
function fire (channel, event) {
const handles = listener[channel]
if (handles == null) {
return
}
for (const item of handles) {
item.handle(event)
}
}
function unregister (id) {
for (const key in listener) {
const handlers = listener[key]
for (let i = 0; i < handlers.length; i++) {
const handle = handlers[i]
if (handle.id === id) {
handlers.splice(i)
return
}
}
}
}
const EventHub = {
register,
fire,
unregister,
}
module.exports = EventHub
================================================
FILE: packages/core/src/expose.js
================================================
const lodash = require('lodash')
const config = require('./config-api')
const event = require('./event')
const modules = require('./modules')
const shell = require('./shell')
const status = require('./status')
const log = require('./utils/util.log.core')
const context = {
config,
shell,
status,
event,
log,
}
function setupPlugin (key, plugin, context, config) {
const pluginConfig = plugin.config
const PluginClass = plugin.plugin
const pluginStatus = plugin.status
const api = PluginClass(context)
config.addDefault(key, pluginConfig)
if (pluginStatus) {
lodash.set(status, key, pluginStatus)
}
return api
}
const proxy = setupPlugin('proxy', modules.proxy, context, config)
const plugin = {}
for (const key in modules.plugin) {
const target = modules.plugin[key]
const api = setupPlugin(`plugin.${key}`, target, context, config)
plugin[key] = api
}
config.resetDefault()
const server = modules.server
const serverStart = server.start
function newServerStart ({ mitmproxyPath }) {
return serverStart({ mitmproxyPath, plugins: plugin })
}
server.start = newServerStart
async function startup ({ mitmproxyPath }) {
const conf = config.get()
if (conf.server.enabled) {
try {
await server.start({ mitmproxyPath })
} catch (err) {
log.error('代理服务启动失败:', err)
}
}
if (conf.proxy.enabled) {
try {
await proxy.start()
} catch (err) {
log.error('开启系统代理失败:', err)
}
}
try {
const plugins = []
for (const key in plugin) {
if (conf.plugin[key].enabled) {
const start = async () => {
try {
await plugin[key].start()
log.info(`插件【${key}】已启动`)
} catch (err) {
log.error(`插件【${key}】启动失败:`, err)
}
}
plugins.push(start())
}
}
if (plugins && plugins.length > 0) {
await Promise.all(plugins)
}
} catch (err) {
log.error('开启插件失败:', err)
}
}
async function shutdown () {
try {
const plugins = []
for (const key in plugin) {
if (status.plugin[key] && status.plugin[key].enabled && plugin[key].close) {
const close = async () => {
try {
await plugin[key].close()
log.info(`插件【${key}】已关闭`)
} catch (err) {
log.error(`插件【${key}】关闭失败:`, err)
}
}
plugins.push(close())
}
}
if (plugins.length > 0) {
await Promise.all(plugins)
}
} catch (error) {
log.error('插件关闭失败:', error)
}
if (status.proxy.enabled) {
try {
await proxy.close()
log.info('系统代理已关闭')
} catch (err) {
log.error('系统代理关闭失败:', err)
}
}
if (status.server.enabled) {
try {
await server.close()
log.info('代理服务已关闭')
} catch (err) {
log.error('代理服务关闭失败:', err)
}
}
}
const api = {
startup,
shutdown,
status: {
get () {
return status
},
},
config,
event,
shell,
server,
proxy,
plugin,
log,
}
module.exports = {
status,
api,
}
================================================
FILE: packages/core/src/index.js
================================================
const expose = require('./expose.js')
const log = require('./utils/util.log.core')
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
// 避免异常崩溃
process.on('uncaughtException', (err) => {
log.error('Process Uncaught Exception:', err)
})
process.on('unhandledRejection', (reason, p) => {
log.error('Process Unhandled Rejection at: Promise:', p, ', reason:', reason)
// application specific logging, throwing an error, or other logic here
})
module.exports = expose
================================================
FILE: packages/core/src/merge.js
================================================
const lodash = require('lodash')
/**
* 找出 newObj 相对于 oldObj 有差异的部分
*
* @param oldObj
* @param newObj
* @returns {{}|*}
*/
function doDiff (oldObj, newObj) {
if (newObj == null) {
return oldObj
}
// 临时的对象,用于找出被删除的数据
const tempObj = { ...oldObj }
// 删除空项,使差异对象更干净一些,体现出用户自定义内容
deleteNullItems(tempObj)
// 保存差异的对象
const diffObj = {}
// 读取新对象,并解析
for (const key in newObj) {
const newValue = newObj[key]
const oldValue = oldObj[key]
// 新值不为空,旧值为空时,直接取新值
if (newValue != null && oldValue == null) {
diffObj[key] = newValue
continue
}
// 新旧值相等时,忽略
if (lodash.isEqual(newValue, oldValue)) {
delete tempObj[key]
continue
}
// 新的值为数组时,直接取新值
if (lodash.isArray(newValue)) {
diffObj[key] = newValue
delete tempObj[key]
continue
}
// 新的值为对象时,递归合并
if (lodash.isObject(newValue)) {
diffObj[key] = doDiff(oldValue, newValue)
delete tempObj[key]
continue
}
// 基础类型,直接覆盖
delete tempObj[key]
diffObj[key] = newValue
}
// tempObj 里面剩下的是被删掉的数据
lodash.forEach(tempObj, (oldValue, key) => {
// 将被删除的属性设置为null,目的是为了merge时,将被删掉的对象设置为null,达到删除的目的
diffObj[key] = null
})
return diffObj
}
function deleteNullItems (target) {
lodash.forEach(target, (item, key) => {
if (item == null || item === '[delete]') {
delete target[key]
}
if (lodash.isObject(item)) {
deleteNullItems(item)
}
})
}
module.exports = {
doMerge (oldObj, newObj) {
return lodash.mergeWith(oldObj, newObj, (objValue, srcValue) => {
if (lodash.isArray(objValue)) {
return srcValue
}
})
},
doDiff,
deleteNullItems,
}
================================================
FILE: packages/core/src/modules/index.js
================================================
module.exports = {
server: require('./server'),
proxy: require('./proxy'),
plugin: require('./plugin'),
}
================================================
FILE: packages/core/src/modules/plugin/git/config.js
================================================
module.exports = {
name: 'Git.exe代理',
enabled: false,
tip: '如果你没有安装git命令行则不需要启动它',
setting: {
sslVerify: true, // Git.exe 是否关闭sslVerify,true=关闭 false=开启
noProxyUrls: {
'https://gitee.com': true, // 码云
'https://e.coding.net': true, // Coding(腾讯云)
'https://codeup.aliyun.com': true, // 云效 Codeup (阿里云)
},
},
}
================================================
FILE: packages/core/src/modules/plugin/git/index.js
================================================
const pluginConfig = require('./config')
const Plugin = function (context) {
const { config, shell, event, log } = context
const pluginApi = {
async start () {
const ip = '127.0.0.1'
const port = config.get().server.port
await pluginApi.setProxy(ip, port)
return { ip, port }
},
async close () {
return pluginApi.unsetProxy()
},
async restart () {
await pluginApi.close()
await pluginApi.start()
},
isEnabled () {
return config.get().plugin.git.enabled
},
async save (newConfig) {
},
async setProxy (ip, port) {
const cmds = [
`git config --global http.proxy http://${ip}:${port - 1} `,
`git config --global https.proxy http://${ip}:${port} `,
]
if (config.get().plugin.git.setting.sslVerify === true) {
cmds.push('git config --global http.sslVerify false ')
}
if (config.get().plugin.git.setting.noProxyUrls != null) {
for (const url in config.get().plugin.git.setting.noProxyUrls) {
cmds.push(`git config --global http."${url}".proxy "" `)
}
}
const ret = await shell.exec(cmds, { type: 'cmd' })
event.fire('status', { key: 'plugin.git.enabled', value: true })
log.info('开启【Git】代理成功')
return ret
},
// 当手动修改过 `~/.gitconfig` 时,`unset` 可能会执行失败,所以除了第一条命令外,其他命令都添加了try-catch,防止关闭Git代理失败
async unsetProxy () {
const ret = await shell.exec(['git config --global --unset http.proxy '], { type: 'cmd' })
try {
await shell.exec(['git config --global --unset https.proxy '], { type: 'cmd' })
} catch {
}
if (config.get().plugin.git.setting.sslVerify === true) {
try {
await shell.exec(['git config --global --unset http.sslVerify '], { type: 'cmd' })
} catch {
}
}
if (config.get().plugin.git.setting.noProxyUrls != null) {
for (const url in config.get().plugin.git.setting.noProxyUrls) {
try {
await shell.exec([`git config --global --unset http."${url}".proxy `], { type: 'cmd' })
} catch {
}
}
}
event.fire('status', { key: 'plugin.git.enabled', value: false })
log.info('关闭【Git】代理成功')
return ret
},
}
return pluginApi
}
module.exports = {
key: 'git',
config: pluginConfig,
status: {
enabled: false,
},
plugin: Plugin,
}
================================================
FILE: packages/core/src/modules/plugin/index.js
================================================
module.exports = {
node: require('./node'),
git: require('./git'),
pip: require('./pip'),
overwall: require('./overwall'),
}
================================================
FILE: packages/core/src/modules/plugin/node/config.js
================================================
module.exports = {
name: 'NPM加速',
enabled: false,
tip: '如果你没有安装nodejs则不需要启动它',
startup: {
variables: true,
},
setting: {
'command': 'npm',
'strict-ssl': true,
'cafile': false,
'NODE_EXTRA_CA_CERTS': false,
'NODE_TLS_REJECT_UNAUTHORIZED': false,
'yarnRegistry': 'default',
'registry': 'https://registry.npmjs.org', // 可以选择切换官方或者淘宝镜像
},
variables: {
phantomjs_cdnurl: 'https://npmmirror.com/mirrors/phantomjs',
chromedriver_cdnurl: 'https://npmmirror.com/mirrors/chromedriver',
sass_binary_site: 'https://npmmirror.com/mirrors/node-sass',
ELECTRON_MIRROR: 'https://npmmirror.com/mirrors/electron/',
NVM_NODEJS_ORG_MIRROR: 'https://npmmirror.com/mirrors/node',
CHROMEDRIVER_CDNURL: 'https://npmmirror.com/mirrors/chromedriver',
OPERADRIVER: 'https://npmmirror.com/mirrors/operadriver',
ELECTRON_BUILDER_BINARIES_MIRROR: 'https://npmmirror.com/mirrors/electron-builder-binaries/',
PYTHON_MIRROR: 'https://npmmirror.com/mirrors/python',
},
}
================================================
FILE: packages/core/src/modules/plugin/node/index.js
================================================
const jsonApi = require('@docmirror/mitmproxy/src/json')
const nodeConfig = require('./config')
const NodePlugin = function (context) {
const { config, shell, event, log } = context
const nodeApi = {
async start () {
try {
await nodeApi.setVariables()
} catch (err) {
log.warn('set variables error:', err)
}
const ip = '127.0.0.1'
const port = config.get().server.port
await nodeApi.setProxy(ip, port)
return { ip, port }
},
async close () {
return nodeApi.unsetProxy()
},
async restart () {
await nodeApi.close()
await nodeApi.start()
},
async save (newConfig) {
nodeApi.setVariables()
},
async getNpmEnv () {
const command = config.get().plugin.node.setting.command || 'npm'
const ret = await shell.exec([`${command} config list --json`], { type: 'cmd' })
if (ret != null) {
const json = ret.substring(ret.indexOf('{'))
return jsonApi.parse(json)
}
return {}
},
async setNpmEnv (list) {
const command = config.get().plugin.node.setting.command || 'npm'
const cmds = []
for (const item of list) {
if (item.value != null && item.value.length > 0 && item.value !== 'default' && item.value !== 'null') {
cmds.push(`${command} config set ${item.key} ${item.value}`)
} else {
cmds.push(`${command} config delete ${item.key}`)
}
}
return await shell.exec(cmds, { type: 'cmd' })
},
async unsetNpmEnv (list) {
const command = config.get().plugin.node.setting.command || 'npm'
const cmds = []
for (const item of list) {
cmds.push(`${command} config delete ${item} `)
}
return await shell.exec(cmds, { type: 'cmd' })
},
async setYarnEnv (list) {
const cmds = []
log.debug('yarn set:', JSON.stringify(list))
for (const item of list) {
if (item.value != null && item.value.length > 0 && item.value !== 'default' && item.value !== 'null') {
cmds.push(`yarn config set ${item.key} ${item.value}`)
} else {
cmds.push(`yarn config delete ${item.key}`)
}
}
return await shell.exec(cmds, { type: 'cmd' })
},
async unsetYarnEnv (list) {
const cmds = []
for (const item of list) {
cmds.push(`yarn config delete ${item} `)
}
return await shell.exec(cmds, { type: 'cmd' })
},
async getVariables () {
const currentMap = await nodeApi.getNpmEnv()
const list = []
const map = config.get().plugin.node.variables
for (const key in map) {
const exists = currentMap[key] != null
list.push({
key,
value: map[key],
oldValue: currentMap[key],
exists,
hadSet: currentMap[key] === map[key],
})
}
return list
},
async setVariables () {
const list = await nodeApi.getVariables()
const noSetList = list.filter((item) => {
return !item.exists
})
if (noSetList.length > 0) {
return nodeApi.setNpmEnv(noSetList)
}
},
async setRegistry ({ registry, type }) {
if (type === 'npm') {
await nodeApi.setNpmEnv([{ key: 'registry', value: registry }])
} else {
await nodeApi.setYarnEnv([{ key: 'registry', value: registry }])
}
return true
},
async setProxy (ip, port) {
const command = config.get().plugin.node.setting.command || 'npm'
const cmds = [
`${command} config set proxy=http://${ip}:${port - 1}`,
`${command} config set https-proxy=http://${ip}:${port}`,
]
const env = []
/**
* 'strict-ssl': false,
cafile: true,
NODE_EXTRA_CA_CERTS: true,
NODE_TLS_REJECT_UNAUTHORIZED: false
*/
const nodeConfig = config.get().plugin.node
const rootCaCertFile = config.get().server.setting.rootCaFile.certPath
if (nodeConfig.setting['strict-ssl']) {
cmds.push(`${command} config set strict-ssl false`)
}
if (nodeConfig.setting.cafile) {
cmds.push(`${command} config set cafile "${rootCaCertFile}"`)
}
if (nodeConfig.setting.NODE_EXTRA_CA_CERTS) {
cmds.push(`${command} config set NODE_EXTRA_CA_CERTS "${rootCaCertFile}"`)
env.push({ key: 'NODE_EXTRA_CA_CERTS', value: rootCaCertFile })
}
if (nodeConfig.setting.NODE_TLS_REJECT_UNAUTHORIZED) {
cmds.push(`${command} config set NODE_TLS_REJECT_UNAUTHORIZED 0`)
env.push({ key: 'NODE_TLS_REJECT_UNAUTHORIZED', value: '0' })
}
const ret = await shell.exec(cmds, { type: 'cmd' })
if (env.length > 0) {
await shell.setSystemEnv({ list: env })
}
event.fire('status', { key: 'plugin.node.enabled', value: true })
log.info('开启【NPM】代理成功')
return ret
},
async unsetProxy () {
const command = config.get().plugin.node.setting.command || 'npm'
const cmds = [
`${command} config delete proxy`,
`${command} config delete https-proxy`,
`${command} config delete NODE_EXTRA_CA_CERTS`,
`${command} config delete strict-ssl`,
]
const ret = await shell.exec(cmds, { type: 'cmd' })
event.fire('status', { key: 'plugin.node.enabled', value: false })
log.info('关闭【NPM】代理成功')
return ret
},
}
return nodeApi
}
module.exports = {
key: 'node',
config: nodeConfig,
status: {
enabled: false,
},
plugin: NodePlugin,
}
================================================
FILE: packages/core/src/modules/plugin/overwall/config.js
================================================
module.exports = {
name: '梯子',
enabled: false, // 默认关闭梯子
server: {},
serverDefault: {
'ow-prod.docmirror.top': {
port: 443,
path: 'X2dvX292ZXJfd2FsbF8',
password: 'dev_sidecar_is_666',
},
},
targets: {
'*.github.com': true,
'*github*.com': true,
'*.wikimedia.org': true,
'*.v2ex.com': true,
'*.azureedge.net': true,
'*.cloudfront.net': true,
'*.bing.com': true,
'*.discourse-cdn.com': true,
'*.gravatar.com': true,
'*.docker.com': true,
'*.vueuse.org': true,
'*.elastic.co': true,
'*.optimizely.com': true,
'*.stackpathcdn.com': true,
'*.fastly.net': true,
'*.cloudflare.com': true,
'*.233v2.com': true,
'*.v2fly.org': true,
'*.telegram.org': true,
'*.amazon.com': true,
'*.googleapis.com': true,
'*.google-analytics.com': true,
'*.cloudflareinsights.com': true,
'*.intlify.dev': true,
'*.segment.io': true,
'*.shields.io': true,
'*.jsdelivr.net': true,
},
pac: {
enabled: true,
autoUpdate: true,
pacFileUpdateUrl: 'https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt',
pacFileAbsolutePath: null, // 自定义 pac.txt 文件位置,可以是本地文件路径
pacFilePath: './extra/pac/pac.txt', // 内置 pac.txt 文件路径
},
}
================================================
FILE: packages/core/src/modules/plugin/overwall/index.js
================================================
const pluginConfig = require('./config')
const Plugin = function (context) {
const { config, shell, event, log } = context
const api = {
async start () {
// event.fire('status', { key: 'plugin.overwall.enabled', value: true })
},
async close () {
// event.fire('status', { key: 'plugin.overwall.enabled', value: false })
},
async restart () {
await api.close()
await api.start()
},
async overrideRunningConfig_bak (serverConfig) {
const conf = config.get().plugin.overwall
if (!conf || !conf.enabled || !conf.targets) {
return
}
const server = conf.server
let i = 0
let main
const backup = []
for (const key in server) {
if (i === 0) {
main = key
} else {
backup.push(key)
}
i++
}
for (const key in conf.targets) {
serverConfig.intercepts[key] = {
'.*': {
proxy: `${main}/\${host}`,
backup,
},
}
}
},
}
return api
}
module.exports = {
key: 'overwall',
config: pluginConfig,
plugin: Plugin,
}
================================================
FILE: packages/core/src/modules/plugin/pip/config.js
================================================
module.exports = {
name: 'PIP加速',
statusOff: true,
enabled: null, // 没有开关
tip: '如果你没有安装pip则不需要启动它',
startup: {
},
setting: {
command: 'pip',
trustedHost: 'pypi.org',
registry: 'https://pypi.org/simple/', // 可以选择切换官方或者淘宝镜像
},
}
================================================
FILE: packages/core/src/modules/plugin/pip/index.js
================================================
const pipConfig = require('./config')
const PipPlugin = function (context) {
const { config, shell, event, log } = context
const api = {
async start () {
await api.setRegistry({ registry: config.get().plugin.pip.setting.registry })
await api.setTrustedHost(config.get().plugin.pip.setting.trustedHost)
},
async close () {
},
async restart () {
await api.close()
await api.start()
},
async save (newConfig) {
await api.setVariables()
},
async getPipEnv () {
const command = config.get().plugin.pip.setting.command
let ret = await shell.exec([`${command} config list`], { type: 'cmd' })
if (ret != null) {
ret = ret.trim()
const lines = ret.split('\n')
const vars = {}
for (const line of lines) {
if (!line.startsWith('global')) {
continue
}
const key = line.substring(0, line.indexOf('='))
let value = line.substring(line.indexOf('=') + 1)
if (value.startsWith('\'')) {
value = value.startsWith(1, value.length - 1)
}
vars[key] = value
}
return vars
}
return {}
},
async setPipEnv (list) {
const command = config.get().plugin.pip.setting.command
const cmds = []
for (const item of list) {
if (item.value != null) {
cmds.push(`${command} config set global.${item.key} ${item.value}`)
} else {
cmds.push(`${command} config unset global.${item.key}`)
}
}
return await shell.exec(cmds, { type: 'cmd' })
},
async unsetPipEnv (list) {
const command = config.get().plugin.pip.setting.command
const cmds = []
for (const item of list) {
cmds.push(`${command} config unset global.${item} `)
}
return await shell.exec(cmds, { type: 'cmd' })
},
async setRegistry ({ registry }) {
await api.setPipEnv([{ key: 'index-url', value: registry }])
return true
},
async setTrustedHost (host) {
await api.setPipEnv([{ key: 'trusted-host', value: host }])
return true
},
async setProxy (ip, port) {
},
async unsetProxy () {
},
}
return api
}
module.exports = {
key: 'pip',
config: pipConfig,
status: {
enabled: false,
},
plugin: PipPlugin,
}
================================================
FILE: packages/core/src/modules/proxy/index.js
================================================
const ProxyPlugin = function (context) {
const { config, event, shell, log } = context
const api = {
async start () {
return api.setProxy()
},
async close () {
return api.unsetProxy()
},
async restart () {
await api.close()
await api.start()
},
async setProxy () {
const ip = '127.0.0.1'
const port = config.get().server.port
const setEnv = config.get().proxy.setEnv
await shell.setSystemProxy({ ip, port, setEnv })
log.info(`开启系统代理成功:${ip}:${port}`)
event.fire('status', { key: 'proxy.enabled', value: true })
return { ip, port }
},
async unsetProxy (setEnv) {
if (setEnv) {
setEnv = config.get().proxy.setEnv
}
try {
await shell.setSystemProxy({ setEnv })
event.fire('status', { key: 'proxy.enabled', value: false })
log.info('关闭系统代理成功')
return true
} catch (err) {
log.error('关闭系统代理失败:', err)
return false
}
},
async setEnableLoopback () {
await shell.enableLoopback()
log.info('打开EnableLoopback成功')
return true
},
}
return api
}
module.exports = {
key: 'proxy',
config: {
enabled: true,
name: '系统代理',
use: 'local',
other: [],
proxyHttp: false, // false=只代理HTTPS请求 true=同时代理HTTP和HTTPS请求
setEnv: false,
// 排除国内域名 所需配置
excludeDomesticDomainAllowList: true, // 是否排除国内域名,默认:需要排除
autoUpdateDomesticDomainAllowList: true, // 是否自动更新国内域名
remoteDomesticDomainAllowListFileUrl: 'https://raw.githubusercontent.com/pluwen/china-domain-allowlist/refs/heads/main/allow-list.sorl',
domesticDomainAllowListFileAbsolutePath: null, // 自定义 domestic-domain-allowlist.txt 文件位置,可以是本地文件路径
domesticDomainAllowListFilePath: './extra/proxy/domestic-domain-allowlist.txt', // 内置国内域名文件
// 自定义系统代理排除列表
excludeIpList: {
// region 常用国内可访问域名
// 中国大陆
'*.cn': true,
'cn.*': true,
'*china*': true,
// Github加速源:以下加速源代理后反而出现问题,从系统代理中排除掉
'*.kkgithub.com': true,
'*.ghproxy.*': true,
// Github ssh
'ssh.github.com': true,
// DeepL
'www.deepl.com': true,
// CSDN
'*.csdn.net': true,
// 360 so
'*.so.com': true,
// 百度
'*.baidu.com': true,
'*.baiducontent.com': true,
'*.bdimg.com': true,
'*.bdstatic.com': true,
'*.bdydns.com': true,
// 腾讯
'*.tencent.com': true,
'*.qq.com': true,
'*.weixin.com': true,
'*.weixinbridge.com': true,
'*.wechat.com': true,
'*.idqqimg.com': true,
'*.gtimg.com': true,
'*.qpic.com': true,
'*.qlogo.com': true,
'*.myapp.com': true,
// 阿里
'*.aliyun.com': true,
'*.alipay.com': true,
'*.taobao.com': true,
'*.tmall.com': true,
'*.alipayobjects.com': true,
'*.dingtalk.com': true,
'*.mmstat.com': true,
'*.alicdn.com': true,
'*.hdslb.com': true,
// Gitee
'gitee.com': true,
'*.gitee.com': true,
'*.gitee.io': true,
'*.giteeusercontent.com': true,
// Mozilla Firefox
'*.mozilla.org': true,
'*.mozilla.com': true,
'*.mozilla.net': true,
'*.firefox.com': true,
'*.firefox.org': true,
'*.mozillademos.org': true,
'*.mozillians.org': true,
'*.mozillians.net': true,
'*.mozillians.com': true,
// OSS
'*.sonatype.org': true,
// Maven镜像
'*.maven.org': true,
// Maven Repository
'*.mvnrepository.com': true,
// 苹果
'*.apple.com': true,
'*.icloud.com': true,
// 微软
'*.microsoft.com': true,
'*.windows.com': true,
'*.office.com': true,
'*.office.net': true,
'*.live.com': true,
'*.msn.com': true,
// WPS
'*.wps.com': true,
'*.wps.net': true,
'*.ksord.com': true,
// 奇虎
'*.qihoo.com': true,
'*.qihucdn.com': true,
// 360
'*.360.com': true,
'*.360safe.com': true,
'*.360buyimg.com': true,
'*.360buy.com': true,
// 京东
'*.jd.com': true,
'*.jcloud.com': true,
'*.jcloudcs.com': true,
'*.jcloudcache.com': true,
'*.jcloudcdn.com': true,
'*.jcloudlb.com': true,
// 哔哩哔哩
'*.bilibili.com': true,
'*.bilivideo.com': true,
'*.biliapi.net': true,
// 移动
'*.10086.com': true,
'*.10086cloud.com': true,
// 移动:139邮箱
'*.139.com': true,
// 迅雷
'*.xunlei.com': true,
// 网站ICP备案查询
'*.icpapi.com': true,
// Navicat
'*.navicat.com': true,
// Github文件上传所使用的域名,被DS代理会导致文件上传经常失败,从系统代理中排除掉
'objects-origin.githubusercontent.com': true,
// cloudflare:排除以下域名,cloudflare的人机校验会更快,成功率更高。
'challenges.cloudflare.com': true,
// endregion
// 本地地址,无需代理
'localhost': true,
'localhost.*': true, // 部分VPN会在host中添加这种格式的域名指向127.0.0.1,所以也排除掉
'127.*.*.*': true,
'test.*': true, // 本地开发时,测试用的虚拟域名格式,无需代理
// 服务器端常用地址,无需代理
'10.*.*.*': true,
'172.16.*.*': true,
'172.17.*.*': true,
'172.18.*.*': true,
'172.19.*.*': true,
'172.20.*.*': true,
'172.21.*.*': true,
'172.22.*.*': true,
'172.23.*.*': true,
'172.24.*.*': true,
'172.25.*.*': true,
'172.26.*.*': true,
'172.27.*.*': true,
'172.28.*.*': true,
'172.29.*.*': true,
'172.30.*.*': true,
'172.31.*.*': true,
// 局域网地址,无需代理
'192.168.*.*': true,
},
},
status: {
enabled: false,
proxyTarget: '',
},
plugin: ProxyPlugin,
}
================================================
FILE: packages/core/src/modules/server/index.js
================================================
const fork = require('node:child_process').fork
const fs = require('node:fs')
const path = require('node:path')
const lodash = require('lodash')
const config = require('../../config-api')
const event = require('../../event')
const status = require('../../status')
const jsonApi = require('@docmirror/mitmproxy/src/json')
const log = require('../../utils/util.log.core')
let server = null
function fireStatus (status) {
event.fire('status', { key: 'server.enabled', value: status })
}
function sleep (time) {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, time)
})
}
const serverApi = {
async startup () {
if (config.get().server.startup) {
return this.start(config.get().server)
}
},
async shutdown () {
if (status.server) {
return this.close()
}
},
async start ({ mitmproxyPath, plugins }) {
const allConfig = config.get()
const serverConfig = lodash.cloneDeep(allConfig.server)
const intercepts = serverConfig.intercepts
const dnsMapping = serverConfig.dns.mapping
if (allConfig.plugin) {
lodash.each(allConfig.plugin, (value) => {
const plugin = value
if (!plugin.enabled) {
return
}
if (plugin.intercepts) {
lodash.merge(intercepts, plugin.intercepts)
}
if (plugin.dns) {
lodash.merge(dnsMapping, plugin.dns)
}
})
}
if (allConfig.app) {
serverConfig.app = allConfig.app
}
if (serverConfig.intercept.enabled === false) {
// 如果设置为关闭拦截
serverConfig.intercepts = {}
}
for (const key in plugins) {
const plugin = plugins[key]
if (plugin.overrideRunningConfig) {
plugin.overrideRunningConfig(serverConfig)
}
}
serverConfig.plugin = allConfig.plugin
if (allConfig.proxy && allConfig.proxy.enabled) {
serverConfig.proxy = allConfig.proxy
}
// fireStatus('ing') // 启动中
const basePath = serverConfig.setting.userBasePath
const runningConfigPath = path.join(basePath, '/running.json')
try {
fs.writeFileSync(runningConfigPath, jsonApi.stringify(serverConfig))
log.info('保存 running.json 运行时配置文件成功:', runningConfigPath)
} catch (e) {
log.error('保存 running.json 运行时配置文件失败:', runningConfigPath, ', error:', e)
throw e
}
const serverProcess = fork(mitmproxyPath, [runningConfigPath])
server = {
id: serverProcess.pid,
process: serverProcess,
close () {
serverProcess.send({ type: 'action', event: { key: 'close' } })
},
}
serverProcess.on('beforeExit', (code) => {
log.warn('server process beforeExit, code:', code)
})
serverProcess.on('SIGPIPE', (code, signal) => {
log.warn(`server process SIGPIPE, code: ${code}, signal:`, signal)
})
serverProcess.on('exit', (code, signal) => {
log.warn(`server process exit, code: ${code}, signal:`, signal)
})
serverProcess.on('uncaughtException', (err, origin) => {
log.error('server process uncaughtException:', err)
})
serverProcess.on('message', (msg) => {
log.debug('收到子进程消息:', JSON.stringify(msg))
if (msg.type === 'status') {
fireStatus(msg.event)
} else if (msg.type === 'error') {
let code = ''
if (msg.event.code) {
code = msg.event.code
}
fireStatus(false) // 启动失败
event.fire('error', { key: 'server', value: code, error: msg.event, message: msg.message })
} else if (msg.type === 'speed') {
event.fire('speed', msg.event)
}
})
return { port: serverConfig.port }
},
async kill () {
if (server) {
server.process.kill('SIGINT')
await sleep(1000)
}
fireStatus(false)
},
async close () {
return await serverApi.kill()
},
async close1 () {
return new Promise((resolve, reject) => {
if (server) {
// fireStatus('ing')// 关闭中
server.close((err) => {
if (err) {
log.warn('close error:', err)
if (err.code === 'ERR_SERVER_NOT_RUNNING') {
log.info('代理服务关闭成功')
resolve()
return
}
log.warn('代理服务关闭失败:', err)
reject(err)
} else {
log.info('代理服务关闭成功')
resolve()
}
})
} else {
log.info('server is null')
resolve()
}
})
},
async restart ({ mitmproxyPath }) {
await serverApi.kill()
await serverApi.start({ mitmproxyPath })
},
getServer () {
return server
},
getSpeedTestList () {
if (server) {
server.process.send({ type: 'speed', event: { key: 'getList' } })
}
},
reSpeedTest () {
if (server) {
server.process.send({ type: 'speed', event: { key: 'reTest' } })
}
},
}
module.exports = serverApi
================================================
FILE: packages/core/src/shell/index.js
================================================
const enableLoopback = require('./scripts/enable-loopback')
const extraPath = require('./scripts/extra-path')
const getNpmEnv = require('./scripts/get-npm-env')
const getSystemEnv = require('./scripts/get-system-env')
const killByPort = require('./scripts/kill-by-port')
const setNpmEnv = require('./scripts/set-npm-env')
const setSystemEnv = require('./scripts/set-system-env')
const setSystemProxy = require('./scripts/set-system-proxy')
const setupCa = require('./scripts/setup-ca')
const shell = require('./shell')
module.exports = {
killByPort,
setupCa,
getSystemEnv,
setSystemEnv,
getNpmEnv,
setNpmEnv,
setSystemProxy,
enableLoopback,
extraPath,
async exec (cmds, args) {
return shell.getSystemShell().exec(cmds, args)
},
getSystemPlatform: shell.getSystemPlatform,
}
================================================
FILE: packages/core/src/shell/scripts/enable-loopback.js
================================================
/**
*/
const Shell = require('../shell')
const extraPath = require('./extra-path')
const sudoPrompt = require('@vscode/sudo-prompt')
const log = require('../../utils/util.log.core')
const execute = Shell.execute
const executor = {
windows (exec) {
const loopbackPath = extraPath.getEnableLoopbackPath()
const sudoCommand = [`"${loopbackPath}"`]
const options = {
name: 'EnableLoopback',
}
return new Promise((resolve, reject) => {
sudoPrompt.exec(
sudoCommand.join(' '),
options,
(error, _, stderr) => {
if (stderr) {
log.error(`[sudo-prompt] 发生错误: ${stderr}`)
}
if (error) {
reject(error)
} else {
resolve(undefined)
}
},
)
})
},
async linux (exec, { port }) {
throw new Error('不支持此操作')
},
async mac (exec, { port }) {
throw new Error('不支持此操作')
},
}
module.exports = async function (args) {
return execute(executor, args)
}
================================================
FILE: packages/core/src/shell/scripts/extra-path/index.js
================================================
const path = require('node:path')
const log = require('../../../utils/util.log.core')
function getExtraPath () {
let extraPath = process.env.DS_EXTRA_PATH
log.info('extraPath:', extraPath)
if (!extraPath) {
extraPath = __dirname
}
return extraPath
}
function getProxyExePath () {
const extraPath = getExtraPath()
return path.join(extraPath, 'sysproxy.exe')
}
function getEnableLoopbackPath () {
const extraPath = getExtraPath()
return path.join(extraPath, 'EnableLoopback.exe')
}
module.exports = {
getProxyExePath,
getEnableLoopbackPath,
}
================================================
FILE: packages/core/src/shell/scripts/get-npm-env.js
================================================
/**
* 获取环境变量
*/
const jsonApi = require('@docmirror/mitmproxy/src/json')
const Shell = require('../shell')
const execute = Shell.execute
const executor = {
async windows (exec) {
const ret = await exec(['npm config list --json'], { type: 'cmd' })
if (ret != null) {
const json = ret.substring(ret.indexOf('{'))
return jsonApi.parse(json)
}
return {}
},
async linux (exec, { port }) {
throw new Error('暂未实现此功能')
},
async mac (exec, { port }) {
throw new Error('暂未实现此功能')
},
}
module.exports = async function (args) {
return execute(executor, args)
}
================================================
FILE: packages/core/src/shell/scripts/get-system-env.js
================================================
/**
* 获取环境变量
*/
const Shell = require('../shell')
const execute = Shell.execute
const executor = {
async windows (exec) {
const ret = await exec(['set'], { type: 'cmd' })
const map = {}
if (ret != null) {
const lines = ret.split('\r\n')
for (const item of lines) {
const kv = item.split('=')
if (kv.length > 1) {
map[kv[0].trim()] = kv[1].trim()
}
}
}
return map
},
async linux (exec, { port }) {
throw new Error('暂未实现此功能')
},
async mac (exec, { port }) {
throw new Error('暂未实现此功能')
},
}
module.exports = async function (args) {
return execute(executor, args)
}
================================================
FILE: packages/core/src/shell/scripts/kill-by-port.js
================================================
const Shell = require('../shell')
const execute = Shell.execute
const executor = {
async windows (exec, { port }) {
const cmds = [`for /f "tokens=5" %a in ('netstat -aon ^| find ":${port}" ^| find "LISTENING"') do (taskkill /f /pid %a & exit /B) `]
await exec(cmds, { type: 'cmd' })
return true
},
async linux (exec, { port }) {
await exec(`kill \`lsof -i:${port} |grep 'dev-sidecar\\|electron\\|@docmirro' |awk '{print $2}'\``)
return true
},
async mac (exec, { port }) {
await exec(`kill \`lsof -i:${port} |grep 'dev-side\\|Elect' |awk '{print $2}'\``)
return true
},
}
module.exports = async function (args) {
return execute(executor, args)
}
================================================
FILE: packages/core/src/shell/scripts/set-npm-env.js
================================================
/**
* 设置环境变量
*/
const Shell = require('../shell')
const execute = Shell.execute
const executor = {
async windows (exec, { list }) {
const cmds = []
for (const item of list) {
cmds.push(`npm config set ${item.key} ${item.value}`)
}
return await exec(cmds, { type: 'cmd' })
},
async linux (exec, { port }) {
throw new Error('暂未实现此功能')
},
async mac (exec, { port }) {
throw new Error('暂未实现此功能')
},
}
module.exports = async function (args) {
return execute(executor, args)
}
================================================
FILE: packages/core/src/shell/scripts/set-system-env.js
================================================
/**
* 设置环境变量
*/
const Shell = require('../shell')
const execute = Shell.execute
const executor = {
async windows (exec, { list }) {
const cmds = []
for (const item of list) {
// [Environment]::SetEnvironmentVariable('FOO', 'bar', 'Machine')
cmds.push(`[Environment]::SetEnvironmentVariable('${item.key}', '${item.value}', 'Machine')`)
}
const ret = await exec(cmds, { type: 'ps' })
const cmds2 = []
for (const item of list) {
// [Environment]::SetEnvironmentVariable('FOO', 'bar', 'Machine')
cmds2.push(`set ${item.key}=""`)
}
await exec(cmds2, { type: 'cmd' })
return ret
},
async linux (exec, { port }) {
throw new Error('暂未实现此功能')
},
async mac (exec, { port }) {
throw new Error('暂未实现此功能')
},
}
module.exports = async function (args) {
return execute(executor, args)
}
================================================
FILE: packages/core/src/shell/scripts/set-system-proxy/index.js
================================================
/**
* 获取环境变量
*/
const fs = require('node:fs')
const path = require('node:path')
const request = require('request')
const Registry = require('winreg')
const log = require('../../../utils/util.log.core')
const Shell = require('../../shell')
const extraPath = require('../extra-path')
const dateUtil = require('../../../utils/util.date')
const execute = Shell.execute
const execFile = Shell.execFile
let config = null
function loadConfig () {
if (config == null) {
config = require('../../../config-api.js')
}
}
function getDomesticDomainAllowListTmpFilePath () {
return path.join(config.get().server.setting.userBasePath, '/domestic-domain-allowlist.txt')
}
async function downloadDomesticDomainAllowListAsync () {
loadConfig()
const remoteFileUrl = config.get().proxy.remoteDomesticDomainAllowListFileUrl
log.info('开始下载远程 domestic-domain-allowlist.txt 文件:', remoteFileUrl)
request(remoteFileUrl, (error, response, body) => {
if (error) {
log.error(`下载远程 domestic-domain-allowlist.txt 文件失败: ${remoteFileUrl}, error:`, error, ', response:', response, ', body:', body)
return
}
if (response && response.statusCode === 200) {
if (body == null || body.length < 100) {
log.warn('下载远程 domestic-domain-allowlist.txt 文件成功,但内容为空或内容太短,判断为无效的 domestic-domain-allowlist.txt 文件:', remoteFileUrl, ', body:', body)
return
} else {
log.info('下载远程 domestic-domain-allowlist.txt 文件成功:', remoteFileUrl)
}
let fileTxt = body
try {
if (!fileTxt.includes('*.')) {
fileTxt = Buffer.from(fil
gitextract_p0gsc863/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── 1_BUG_REPORT.md
│ │ ├── 2_STYLE_ISSUE.md
│ │ ├── 3_CONFIG_ISSUES.md
│ │ ├── 4_FEATURE_REQUEST.md
│ │ └── 5_OTHERS.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── build-and-release.yml
│ ├── npm-run-electron.yml
│ └── test-and-upload.yml
├── .gitignore
├── .npmrc
├── LICENSE
├── README.md
├── _script/
│ ├── 0、updateDependencies.bat
│ ├── 1、setupEnv.bat
│ ├── 2、installProject.bat
│ ├── 3、buildAndRun.bat
│ ├── 4.1、runTestCore.bat
│ ├── 4.2、runTestMitmproxy.bat
│ └── 5、generateSetupFile.bat
├── doc/
│ ├── caroot.md
│ ├── linux.md
│ ├── other.md
│ ├── recover.md
│ └── wiki/
│ ├── Home.md
│ ├── 加速服务使用说明.md
│ ├── 各平台安装说明.md
│ └── 解决Github访问不了或速度很慢的问题.md
├── eslint.config.js
├── package.json
├── packages/
│ ├── cli/
│ │ ├── LICENSE
│ │ ├── cli.js
│ │ ├── package.json
│ │ └── src/
│ │ ├── banner.txt
│ │ ├── index.js
│ │ ├── mitmproxy.js
│ │ └── user_config.json5
│ ├── core/
│ │ ├── LICENSE
│ │ ├── index.js
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── config/
│ │ │ │ ├── index.js
│ │ │ │ ├── local-config-loader.js
│ │ │ │ └── remote_config.json5
│ │ │ ├── config-api.js
│ │ │ ├── event.js
│ │ │ ├── expose.js
│ │ │ ├── index.js
│ │ │ ├── merge.js
│ │ │ ├── modules/
│ │ │ │ ├── index.js
│ │ │ │ ├── plugin/
│ │ │ │ │ ├── git/
│ │ │ │ │ │ ├── config.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── node/
│ │ │ │ │ │ ├── config.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── overwall/
│ │ │ │ │ │ ├── config.js
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── pip/
│ │ │ │ │ ├── config.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── proxy/
│ │ │ │ │ └── index.js
│ │ │ │ └── server/
│ │ │ │ └── index.js
│ │ │ ├── shell/
│ │ │ │ ├── index.js
│ │ │ │ ├── scripts/
│ │ │ │ │ ├── enable-loopback.js
│ │ │ │ │ ├── extra-path/
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── get-npm-env.js
│ │ │ │ │ ├── get-system-env.js
│ │ │ │ │ ├── kill-by-port.js
│ │ │ │ │ ├── set-npm-env.js
│ │ │ │ │ ├── set-system-env.js
│ │ │ │ │ ├── set-system-proxy/
│ │ │ │ │ │ ├── index.js
│ │ │ │ │ │ └── refresh-internet.js
│ │ │ │ │ └── setup-ca.js
│ │ │ │ └── shell.js
│ │ │ ├── status.js
│ │ │ └── utils/
│ │ │ ├── util.date.js
│ │ │ ├── util.log-or-console.js
│ │ │ ├── util.log.core.js
│ │ │ ├── util.logger.js
│ │ │ └── util.version.js
│ │ └── test/
│ │ ├── configTest.js
│ │ ├── httpsVerifyTest.js
│ │ ├── macProxyTest.js
│ │ ├── mergeTest.js
│ │ ├── regex.test.js
│ │ ├── requestTest.js
│ │ └── versionTest.js
│ ├── gui/
│ │ ├── .editorconfig
│ │ ├── .gitignore
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── babel.config.js
│ │ ├── build/
│ │ │ ├── icons/
│ │ │ │ └── icon.icns
│ │ │ └── mac/
│ │ │ └── icon.icns
│ │ ├── extra/
│ │ │ ├── icons/
│ │ │ │ └── icon.icns
│ │ │ ├── pac/
│ │ │ │ └── pac.txt
│ │ │ ├── proxy/
│ │ │ │ └── domestic-domain-allowlist.txt
│ │ │ └── scripts/
│ │ │ ├── github.script
│ │ │ ├── google.js
│ │ │ └── tampermonkey.script
│ │ ├── package.json
│ │ ├── pkg/
│ │ │ ├── after-all-artifact-build.js
│ │ │ └── after-pack.js
│ │ ├── public/
│ │ │ └── index.html
│ │ ├── src/
│ │ │ ├── background/
│ │ │ │ └── powerMonitor.js
│ │ │ ├── background.js
│ │ │ ├── bridge/
│ │ │ │ ├── api/
│ │ │ │ │ ├── backend.js
│ │ │ │ │ └── open-enable-loopback.js
│ │ │ │ ├── auto-start/
│ │ │ │ │ ├── backend.js
│ │ │ │ │ └── front.js
│ │ │ │ ├── backend.js
│ │ │ │ ├── error/
│ │ │ │ │ └── front.js
│ │ │ │ ├── file-selector/
│ │ │ │ │ ├── backend.js
│ │ │ │ │ └── front.js
│ │ │ │ ├── front.js
│ │ │ │ ├── mitmproxy.js
│ │ │ │ ├── on-close/
│ │ │ │ │ └── front.js
│ │ │ │ ├── tongji/
│ │ │ │ │ ├── backend.js
│ │ │ │ │ └── front.js
│ │ │ │ └── update/
│ │ │ │ ├── backend.js
│ │ │ │ └── front.js
│ │ │ ├── main.js
│ │ │ ├── utils/
│ │ │ │ ├── util.apppath.js
│ │ │ │ └── util.log.gui.js
│ │ │ └── view/
│ │ │ ├── App.vue
│ │ │ ├── api.js
│ │ │ ├── components/
│ │ │ │ ├── container.vue
│ │ │ │ ├── mock-input.vue
│ │ │ │ ├── setup-ca.vue
│ │ │ │ └── tree-node.vue
│ │ │ ├── composables/
│ │ │ │ └── theme.js
│ │ │ ├── index.js
│ │ │ ├── mixins/
│ │ │ │ └── plugin.js
│ │ │ ├── pages/
│ │ │ │ ├── help.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── plugin/
│ │ │ │ │ ├── git.vue
│ │ │ │ │ ├── node.vue
│ │ │ │ │ ├── overwall.vue
│ │ │ │ │ └── pip.vue
│ │ │ │ ├── proxy.vue
│ │ │ │ ├── server.vue
│ │ │ │ └── setting.vue
│ │ │ ├── router/
│ │ │ │ ├── index.js
│ │ │ │ └── menu.js
│ │ │ ├── status.js
│ │ │ └── style/
│ │ │ ├── index.scss
│ │ │ └── theme/
│ │ │ └── dark.scss
│ │ └── vue.config.js
│ └── mitmproxy/
│ ├── LICENSE
│ ├── index.js
│ ├── package.json
│ ├── src/
│ │ ├── index.js
│ │ ├── json.js
│ │ ├── lib/
│ │ │ ├── choice/
│ │ │ │ ├── RequestCounter.js
│ │ │ │ └── index.js
│ │ │ ├── dns/
│ │ │ │ ├── base.js
│ │ │ │ ├── https.js
│ │ │ │ ├── index.js
│ │ │ │ ├── preset.js
│ │ │ │ ├── tcp.js
│ │ │ │ ├── tls.js
│ │ │ │ ├── udp.js
│ │ │ │ └── util/
│ │ │ │ └── dns-over-tls.js
│ │ │ ├── interceptor/
│ │ │ │ ├── impl/
│ │ │ │ │ ├── req/
│ │ │ │ │ │ ├── OPTIONS.js
│ │ │ │ │ │ ├── abort.js
│ │ │ │ │ │ ├── baiduOcr.js
│ │ │ │ │ │ ├── cacheRequest.js
│ │ │ │ │ │ ├── proxy.js
│ │ │ │ │ │ ├── redirect.js
│ │ │ │ │ │ ├── requestReplace.js
│ │ │ │ │ │ ├── sni.js
│ │ │ │ │ │ ├── success.js
│ │ │ │ │ │ └── unVerifySsl.js
│ │ │ │ │ └── res/
│ │ │ │ │ ├── AfterOPTIONSHeaders.js
│ │ │ │ │ ├── cacheResponse.js
│ │ │ │ │ ├── responseReplace.js
│ │ │ │ │ └── script.js
│ │ │ │ └── index.js
│ │ │ ├── monkey/
│ │ │ │ └── index.js
│ │ │ ├── proxy/
│ │ │ │ ├── common/
│ │ │ │ │ ├── ProxyHttpAgent.js
│ │ │ │ │ ├── ProxyHttpsAgent.js
│ │ │ │ │ ├── config.js
│ │ │ │ │ └── util.js
│ │ │ │ ├── compatible/
│ │ │ │ │ └── compatible.js
│ │ │ │ ├── index.js
│ │ │ │ ├── middleware/
│ │ │ │ │ ├── InsertScriptMiddleware.js
│ │ │ │ │ ├── overwall.js
│ │ │ │ │ └── source/
│ │ │ │ │ └── pac.js
│ │ │ │ ├── mitmproxy/
│ │ │ │ │ ├── createConnectHandler.js
│ │ │ │ │ ├── createFakeServerCenter.js
│ │ │ │ │ ├── createRequestHandler.js
│ │ │ │ │ ├── createUpgradeHandler.js
│ │ │ │ │ ├── dnsLookup.js
│ │ │ │ │ └── index.js
│ │ │ │ └── tls/
│ │ │ │ ├── CertAndKeyContainer.js
│ │ │ │ ├── FakeServersCenter.js
│ │ │ │ ├── sniUtil.js
│ │ │ │ └── tlsUtils.js
│ │ │ └── speed/
│ │ │ ├── SpeedTester.js
│ │ │ ├── config.js
│ │ │ └── index.js
│ │ ├── options.js
│ │ └── utils/
│ │ ├── util.js
│ │ ├── util.log.server.js
│ │ ├── util.match.js
│ │ └── util.process.js
│ └── test/
│ ├── baiduOcrTest.js
│ ├── dnsSpeedTest.js
│ ├── dnsTest-abroad-doh-sni.mjs
│ ├── dnsTest-abroad-dot-sni.mjs
│ ├── dnsTest-abroad.mjs
│ ├── dnsTest.mjs
│ ├── lodashTest.js
│ ├── matchTest.js
│ ├── matchUtilTest.js
│ ├── monkeyTest.js
│ ├── pacTest.js
│ ├── proxyTest.js
│ ├── responseReplaceTest.js
│ ├── sha256Test.js
│ └── utilTest.js
├── pnpm-workspace.yaml
└── test/
├── test.js
└── testDns.js
SYMBOL INDEX (452 symbols across 107 files)
FILE: packages/cli/src/index.js
function startup (line 7) | async function startup () {
function onClose (line 29) | async function onClose () {
FILE: packages/core/src/config-api.js
function get (line 13) | function get () {
method startAutoDownloadRemoteConfig (line 19) | async startAutoDownloadRemoteConfig () {
method downloadRemoteConfig (line 34) | async downloadRemoteConfig () {
method doDownloadRemoteConfig (line 46) | doDownloadRemoteConfig (remoteConfigUrl, suffix = '') {
method deleteRemoteConfigFile (line 116) | deleteRemoteConfigFile (suffix = '') {
method readRemoteConfigStr (line 123) | readRemoteConfigStr (suffix = '') {
method save (line 143) | save (newConfig) {
method reload (line 183) | reload () {
method update (line 187) | update (partConfig) {
method set (line 192) | set (newConfig) {
method load (line 199) | load (newConfig) {
method cloneDefault (line 204) | cloneDefault () {
method addDefault (line 207) | addDefault (key, defValue) {
method removeUserConfig (line 211) | async removeUserConfig () {
method resetDefault (line 253) | resetDefault (key) {
method getVariables (line 263) | async getVariables (type) {
method setVariables (line 278) | async setVariables (type) {
FILE: packages/core/src/config/index.js
function getRootCaCertPath (line 4) | function getRootCaCertPath () {
function getRootCaKeyPath (line 8) | function getRootCaKeyPath () {
FILE: packages/core/src/config/local-config-loader.js
function getUserBasePath (line 8) | function getUserBasePath (autoCreate = true) {
function loadConfigFromFile (line 20) | function loadConfigFromFile (configFilePath) {
function getUserConfigPath (line 51) | function getUserConfigPath () {
function getUserConfig (line 64) | function getUserConfig () {
function getRemoteConfigPath (line 69) | function getRemoteConfigPath (suffix = '') {
function getRemoteConfig (line 74) | function getRemoteConfig (suffix = '') {
function getAutomaticCompatibleConfigPath (line 79) | function getAutomaticCompatibleConfigPath () {
function getConfigFromFiles (line 90) | function getConfigFromFiles (userConfig, defaultConfig) {
FILE: packages/core/src/event.js
function register (line 3) | function register (channel, handle, order = 10) {
function fire (line 14) | function fire (channel, event) {
function unregister (line 24) | function unregister (id) {
FILE: packages/core/src/expose.js
function setupPlugin (line 17) | function setupPlugin (key, plugin, context, config) {
function newServerStart (line 40) | function newServerStart ({ mitmproxyPath }) {
function startup (line 44) | async function startup ({ mitmproxyPath }) {
function shutdown (line 83) | async function shutdown () {
method get (line 128) | get () {
FILE: packages/core/src/merge.js
function doDiff (line 10) | function doDiff (oldObj, newObj) {
function deleteNullItems (line 66) | function deleteNullItems (target) {
method doMerge (line 78) | doMerge (oldObj, newObj) {
FILE: packages/core/src/modules/plugin/git/index.js
method start (line 6) | async start () {
method close (line 13) | async close () {
method restart (line 17) | async restart () {
method isEnabled (line 22) | isEnabled () {
method save (line 26) | async save (newConfig) {
method setProxy (line 30) | async setProxy (ip, port) {
method unsetProxy (line 54) | async unsetProxy () {
FILE: packages/core/src/modules/plugin/node/index.js
method start (line 7) | async start () {
method close (line 20) | async close () {
method restart (line 24) | async restart () {
method save (line 29) | async save (newConfig) {
method getNpmEnv (line 32) | async getNpmEnv () {
method setNpmEnv (line 43) | async setNpmEnv (list) {
method unsetNpmEnv (line 57) | async unsetNpmEnv (list) {
method setYarnEnv (line 67) | async setYarnEnv (list) {
method unsetYarnEnv (line 80) | async unsetYarnEnv (list) {
method getVariables (line 88) | async getVariables () {
method setVariables (line 105) | async setVariables () {
method setRegistry (line 115) | async setRegistry ({ registry, type }) {
method setProxy (line 124) | async setProxy (ip, port) {
method unsetProxy (line 169) | async unsetProxy () {
FILE: packages/core/src/modules/plugin/overwall/index.js
method start (line 6) | async start () {
method close (line 10) | async close () {
method restart (line 14) | async restart () {
method overrideRunningConfig_bak (line 19) | async overrideRunningConfig_bak (serverConfig) {
FILE: packages/core/src/modules/plugin/pip/index.js
method start (line 6) | async start () {
method close (line 11) | async close () {
method restart (line 14) | async restart () {
method save (line 19) | async save (newConfig) {
method getPipEnv (line 22) | async getPipEnv () {
method setPipEnv (line 45) | async setPipEnv (list) {
method unsetPipEnv (line 58) | async unsetPipEnv (list) {
method setRegistry (line 67) | async setRegistry ({ registry }) {
method setTrustedHost (line 72) | async setTrustedHost (host) {
method setProxy (line 77) | async setProxy (ip, port) {
method unsetProxy (line 81) | async unsetProxy () {
FILE: packages/core/src/modules/proxy/index.js
method start (line 4) | async start () {
method close (line 8) | async close () {
method restart (line 12) | async restart () {
method setProxy (line 17) | async setProxy () {
method unsetProxy (line 27) | async unsetProxy (setEnv) {
method setEnableLoopback (line 42) | async setEnableLoopback () {
FILE: packages/core/src/modules/server/index.js
function fireStatus (line 12) | function fireStatus (status) {
function sleep (line 15) | function sleep (time) {
method startup (line 23) | async startup () {
method shutdown (line 28) | async shutdown () {
method start (line 33) | async start ({ mitmproxyPath, plugins }) {
method kill (line 123) | async kill () {
method close (line 130) | async close () {
method close1 (line 133) | async close1 () {
method restart (line 158) | async restart ({ mitmproxyPath }) {
method getServer (line 162) | getServer () {
method getSpeedTestList (line 165) | getSpeedTestList () {
method reSpeedTest (line 170) | reSpeedTest () {
FILE: packages/core/src/shell/index.js
method exec (line 22) | async exec (cmds, args) {
FILE: packages/core/src/shell/scripts/enable-loopback.js
method windows (line 10) | windows (exec) {
method linux (line 35) | async linux (exec, { port }) {
method mac (line 38) | async mac (exec, { port }) {
FILE: packages/core/src/shell/scripts/extra-path/index.js
function getExtraPath (line 4) | function getExtraPath () {
function getProxyExePath (line 13) | function getProxyExePath () {
function getEnableLoopbackPath (line 18) | function getEnableLoopbackPath () {
FILE: packages/core/src/shell/scripts/get-npm-env.js
method windows (line 10) | async windows (exec) {
method linux (line 18) | async linux (exec, { port }) {
method mac (line 21) | async mac (exec, { port }) {
FILE: packages/core/src/shell/scripts/get-system-env.js
method windows (line 9) | async windows (exec) {
method linux (line 23) | async linux (exec, { port }) {
method mac (line 26) | async mac (exec, { port }) {
FILE: packages/core/src/shell/scripts/kill-by-port.js
method windows (line 6) | async windows (exec, { port }) {
method linux (line 11) | async linux (exec, { port }) {
method mac (line 15) | async mac (exec, { port }) {
FILE: packages/core/src/shell/scripts/set-npm-env.js
method windows (line 9) | async windows (exec, { list }) {
method linux (line 16) | async linux (exec, { port }) {
method mac (line 19) | async mac (exec, { port }) {
FILE: packages/core/src/shell/scripts/set-system-env.js
method windows (line 9) | async windows (exec, { list }) {
method linux (line 25) | async linux (exec, { port }) {
method mac (line 28) | async mac (exec, { port }) {
FILE: packages/core/src/shell/scripts/set-system-proxy/index.js
function loadConfig (line 17) | function loadConfig () {
function getDomesticDomainAllowListTmpFilePath (line 23) | function getDomesticDomainAllowListTmpFilePath () {
function downloadDomesticDomainAllowListAsync (line 27) | async function downloadDomesticDomainAllowListAsync () {
function loadLastModifiedTimeFromTxt (line 66) | function loadLastModifiedTimeFromTxt (fileTxt) {
function saveDomesticDomainAllowListFile (line 78) | function saveDomesticDomainAllowListFile (fileTxt) {
function getDomesticDomainAllowList (line 109) | function getDomesticDomainAllowList () {
function getProxyExcludeIpStr (line 148) | function getProxyExcludeIpStr (split) {
method windows (line 187) | async windows (exec, params = {}) {
method linux (line 288) | async linux (exec, params = {}) {
method mac (line 321) | async mac (exec, params = {}) {
FILE: packages/core/src/shell/scripts/setup-ca.js
method windows (line 6) | async windows (exec, { certPath }) {
method linux (line 11) | async linux (exec, { certPath }) {
method mac (line 16) | async mac (exec, { certPath }) {
FILE: packages/core/src/shell/shell.js
class SystemShell (line 9) | class SystemShell {
method exec (line 10) | static async exec (cmds, args) {
class LinuxSystemShell (line 15) | class LinuxSystemShell extends SystemShell {
method exec (line 16) | static async exec (cmds) {
class DarwinSystemShell (line 26) | class DarwinSystemShell extends SystemShell {
method exec (line 27) | static async exec (cmds) {
class WindowsSystemShell (line 39) | class WindowsSystemShell extends SystemShell {
method exec (line 40) | static async exec (cmds, args = { }) {
function childExec (line 72) | function childExec (composeCmds, options = {}) {
function getSystemShell (line 91) | function getSystemShell () {
function getSystemPlatform (line 104) | function getSystemPlatform (throwIfUnknown = false) {
function execute (line 124) | async function execute (executor, args) {
function execFile (line 128) | async function execFile (file, args, options) {
FILE: packages/core/src/utils/util.date.js
method format (line 3) | format (date, needMill = true) {
method now (line 19) | now (needMill = true) {
FILE: packages/core/src/utils/util.log-or-console.js
function backup (line 8) | function backup (fun, args) {
function printBackups (line 28) | function printBackups () {
function _doLog (line 44) | function _doLog (fun, args) {
method setLogger (line 54) | setLogger (logger) {
method debug (line 77) | debug (...args) {
method info (line 80) | info (...args) {
method warn (line 83) | warn (...args) {
method error (line 86) | error (...args) {
FILE: packages/core/src/utils/util.logger.js
function getDefaultConfigBasePath (line 10) | function getDefaultConfigBasePath () {
function log4jsConfigure (line 39) | function log4jsConfigure (categories) {
method getLogger (line 69) | getLogger (category) {
FILE: packages/core/src/utils/util.version.js
function parseVersion (line 1) | function parseVersion (version) {
function isNewVersion (line 17) | function isNewVersion (onlineVersion, currentVersion, log = null) {
FILE: packages/core/test/versionTest.js
function testIsNewVersion (line 4) | function testIsNewVersion (onlineVersion, currentVersion, expected) {
FILE: packages/gui/pkg/after-all-artifact-build.js
function appendIntro (line 5) | function appendIntro (context, systemType, latest) {
FILE: packages/gui/pkg/after-pack.js
function writeAppUpdateYmlForLinux (line 6) | function writeAppUpdateYmlForLinux () {
FILE: packages/gui/src/background.js
function openDevTools (line 50) | function openDevTools () {
function closeDevTools (line 60) | function closeDevTools () {
function switchDevTools (line 70) | function switchDevTools () {
function setTray (line 82) | function setTray () {
function checkHideWin (line 151) | function checkHideWin () {
function hideWin (line 173) | function hideWin (reason = '', needCheck = false) {
function showWin (line 189) | function showWin () {
function changeAppConfig (line 201) | function changeAppConfig (config) {
function createWindow (line 207) | function createWindow (startHideWindow, autoQuitIfError = true) {
function beforeQuit (line 364) | async function beforeQuit () {
function quit (line 368) | async function quit (reason) {
function hasShortcut (line 379) | function hasShortcut (showHideShortcut) {
function registerShowHideShortcut (line 383) | function registerShowHideShortcut (showHideShortcut) {
function initApp (line 410) | function initApp () {
FILE: packages/gui/src/background/powerMonitor.js
class PowerMonitor (line 4) | class PowerMonitor {
method constructor (line 5) | constructor () {
method setupMainWindow (line 14) | setupMainWindow (window) {
method addListener (line 21) | addListener (event, listener) {
method removeListener (line 25) | removeListener (event, listener) {
method removeAllListeners (line 29) | removeAllListeners (event) {
method on (line 42) | on (event, listener) {
method off (line 58) | off (event, listener) {
method once (line 66) | once (event, listener) {
method emit (line 74) | emit (event, ...args) {
method eventNames (line 78) | eventNames () {
method getMaxListeners (line 82) | getMaxListeners () {
method listeners (line 86) | listeners (event) {
method rawListeners (line 90) | rawListeners (event) {
method listenerCount (line 94) | listenerCount (event, listener) {
method onBatteryPower (line 101) | get onBatteryPower () {
method getSystemIdleState (line 109) | getSystemIdleState (idleThreshold) {
method getSystemIdleTime (line 116) | getSystemIdleTime () {
method getCurrentThermalState (line 123) | getCurrentThermalState () {
method isOnBatteryPower (line 130) | isOnBatteryPower () {
FILE: packages/gui/src/bridge/api/backend.js
method getApiList (line 25) | getApiList () {
method get (line 35) | get () {
method getConfigDir (line 40) | getConfigDir () {
method getLogDir (line 43) | getLogDir () {
method getSystemPlatform (line 46) | getSystemPlatform (throwIfUnknown = false) {
method load (line 54) | load () {
method save (line 90) | save (setting = {}) {
method startup (line 104) | startup () {
method start (line 112) | start () {
method restart (line 119) | restart () {
function _deepFindFunction (line 125) | function _deepFindFunction (list, parent, parentKey) {
function _getSettingsPath (line 136) | function _getSettingsPath () {
function invoke (line 152) | function invoke (api, param) {
function doStart (line 165) | async function doStart () {
method install (line 173) | install ({ win }) {
FILE: packages/gui/src/bridge/api/open-enable-loopback.js
method open (line 8) | open () {
FILE: packages/gui/src/bridge/auto-start/backend.js
function setAutoStartForLinux (line 3) | async function setAutoStartForLinux (app, enable = true) {
method install (line 28) | install (context) {
FILE: packages/gui/src/bridge/auto-start/front.js
function install (line 1) | function install (app, api) {
FILE: packages/gui/src/bridge/backend.js
method install (line 16) | install (context) {
FILE: packages/gui/src/bridge/error/front.js
function install (line 3) | function install (app, api) {
function handleServerStartError (line 16) | function handleServerStartError (message, err, app, api) {
FILE: packages/gui/src/bridge/file-selector/backend.js
method install (line 2) | install (context) {
FILE: packages/gui/src/bridge/file-selector/front.js
function install (line 1) | function install (app, api) {
FILE: packages/gui/src/bridge/front.js
method install (line 19) | install (app, api, router) {
FILE: packages/gui/src/bridge/on-close/front.js
function install (line 4) | function install (app, api) {
FILE: packages/gui/src/bridge/tongji/backend.js
function ebtMain (line 5) | function ebtMain (ipcMain) {
method install (line 50) | install (context) {
FILE: packages/gui/src/bridge/tongji/front.js
function ebtRenderer (line 7) | function ebtRenderer (ipcRenderer, siteId, router) {
method install (line 56) | install (app, api, router) {
FILE: packages/gui/src/bridge/update/backend.js
function downloadFile (line 20) | function downloadFile (uri, filePath, onProgress, onSuccess, onError) {
function updateHandle (line 46) | function updateHandle (app, api, win, beforeQuit, quit, log) {
method install (line 317) | install (context) {
FILE: packages/gui/src/bridge/update/front.js
function install (line 1) | function install (app, api) {
FILE: packages/gui/src/utils/util.apppath.js
function getSystemPlatform (line 5) | function getSystemPlatform (throwIfUnknown = false) {
method getAppRootPath (line 26) | getAppRootPath (app) {
FILE: packages/gui/src/view/api.js
function apiInit (line 7) | function apiInit (app) {
function useApi (line 64) | function useApi () {
FILE: packages/gui/src/view/index.js
method initPre (line 7) | async initPre (Vue, api) {
method initModules (line 16) | initModules (app, router) {
FILE: packages/gui/src/view/mixins/plugin.js
method data (line 8) | data () {
method created (line 20) | created () {
method mounted (line 23) | mounted () {
method getKey (line 26) | getKey () {
method init (line 32) | async init () {
method apply (line 42) | async apply () {
method applyBefore (line 55) | async applyBefore () {
method applyAfter (line 58) | async applyAfter () {
method resetDefault (line 61) | resetDefault () {
method saveConfig (line 83) | saveConfig () {
method getConfig (line 91) | getConfig (key) {
method setConfig (line 98) | setConfig (newConfig) {
method printConfig (line 101) | printConfig (prefix = '') {
method getStatus (line 104) | getStatus (key) {
method reloadConfig (line 111) | async reloadConfig () {
method reloadConfigAndRestart (line 115) | async reloadConfigAndRestart () {
method isWindows (line 132) | isWindows () {
method isMac (line 135) | isMac () {
method isLinux (line 138) | isLinux () {
method openLog (line 141) | async openLog () {
method focusFirst (line 145) | async focusFirst (ref) {
method handleHostname (line 158) | handleHostname (hostname) {
method isNotHostname (line 166) | isNotHostname (hostname) {
FILE: packages/gui/src/view/router/menu.js
function createMenus (line 1) | function createMenus (app) {
FILE: packages/gui/src/view/status.js
function install (line 15) | async function install (api) {
FILE: packages/gui/vue.config.js
method chainWebpackMainProcess (line 127) | chainWebpackMainProcess (config) {
FILE: packages/mitmproxy/src/index.js
method start (line 11) | async start (config) {
method close (line 50) | async close () {
function registerProcessListener (line 80) | function registerProcessListener () {
FILE: packages/mitmproxy/src/json.js
constant JSON5 (line 2) | let JSON5 = require('json5')
method parse (line 8) | parse (str, defaultValue) {
method stringify (line 26) | stringify (obj) {
method stringify2 (line 31) | stringify2 (obj) {
FILE: packages/mitmproxy/src/lib/choice/index.js
class ChoiceCache (line 6) | class ChoiceCache {
method constructor (line 7) | constructor () {
method get (line 16) | get (key) {
method getOrCreate (line 20) | getOrCreate (key, backupList) {
class DynamicChoice (line 32) | class DynamicChoice {
method constructor (line 33) | constructor (key) {
method doRank (line 41) | doRank () {
method setBackupList (line 63) | setBackupList (newBackupList) {
method countStart (line 76) | countStart (value) {
method changeNext (line 84) | changeNext (count) {
method doCount (line 105) | doCount (ip, isError) {
FILE: packages/mitmproxy/src/lib/dns/base.js
function mapToList (line 6) | function mapToList (ipMap) {
class IpCache (line 19) | class IpCache extends DynamicChoice {
method constructor (line 20) | constructor (hostname) {
method setBackupList (line 30) | setBackupList (newBackupList) {
method constructor (line 37) | constructor (dnsName, dnsType, cacheSize, preSetIpList) {
method count (line 49) | count (hostname, ip, isError = true) {
method lookup (line 56) | async lookup (hostname, ipChecker) {
method _lookupWithPreSetIpList (line 106) | async _lookupWithPreSetIpList (hostname) {
method _lookup (line 128) | async _lookup (hostname) {
method _doDnsQuery (line 164) | _doDnsQuery (hostname, type = 'A', start) {
FILE: packages/mitmproxy/src/lib/dns/https.js
function createAgent (line 9) | function createAgent (dnsServer) {
method constructor (line 17) | constructor (dnsName, cacheSize, preSetIpList, dnsServer, dnsServerName) {
method _dnsQueryPromise (line 23) | _dnsQueryPromise (hostname, type = 'A') {
FILE: packages/mitmproxy/src/lib/dns/index.js
method initDNS (line 10) | initDNS (dnsProviders, preSetIpList) {
method hasDnsLookup (line 92) | hasDnsLookup (dnsConfig, hostname) {
FILE: packages/mitmproxy/src/lib/dns/preset.js
method constructor (line 4) | constructor (preSetIpList) {
method _lookup (line 8) | async _lookup (_hostname) {
FILE: packages/mitmproxy/src/lib/dns/tcp.js
method constructor (line 10) | constructor (dnsName, cacheSize, preSetIpList, dnsServer, dnsServerPort) {
method _dnsQueryPromise (line 16) | _dnsQueryPromise (hostname, type = 'A') {
FILE: packages/mitmproxy/src/lib/dns/tls.js
method constructor (line 7) | constructor (dnsName, cacheSize, preSetIpList, dnsServer, dnsServerPort,...
method _dnsQueryPromise (line 14) | _dnsQueryPromise (hostname, type = 'A') {
FILE: packages/mitmproxy/src/lib/dns/udp.js
method constructor (line 9) | constructor (dnsName, cacheSize, preSetIpList, dnsServer, dnsServerPort) {
method _dnsQueryPromise (line 18) | _dnsQueryPromise (hostname, type = 'A') {
FILE: packages/mitmproxy/src/lib/dns/util/dns-over-tls.js
constant TWO_BYTES (line 8) | const TWO_BYTES = 2
function getDnsQuery (line 10) | function getDnsQuery ({ type, name, klass, id }) {
function query (line 19) | function query ({ host, servername, type, name, klass, port, rejectUnaut...
FILE: packages/mitmproxy/src/lib/interceptor/impl/req/OPTIONS.js
function readConfig (line 4) | function readConfig (config, defaultConfig) {
method requestIntercept (line 18) | requestIntercept (context, interceptOpt, req, res, ssl, next) {
method is (line 51) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/req/abort.js
method requestIntercept (line 4) | requestIntercept (context, interceptOpt, req, res, ssl, next) {
method is (line 85) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/req/baiduOcr.js
function getTomorrow (line 1) | function getTomorrow () {
function createBaiduOcrClient (line 34) | function createBaiduOcrClient (config) {
function getConfig (line 46) | function getConfig (interceptOpt, tryCount, log) {
function limitConfig (line 99) | function limitConfig (id, api) {
function checkIsLimitConfig (line 105) | function checkIsLimitConfig (id, api) {
method requestIntercept (line 114) | requestIntercept (context, interceptOpt, req, res, ssl, next) {
method is (line 191) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/req/cacheRequest.js
function getMaxAge (line 1) | function getMaxAge (interceptOpt) {
function getLastModifiedTimeFromIfModifiedSince (line 35) | function getLastModifiedTimeFromIfModifiedSince (rOptions, log) {
method requestIntercept (line 60) | requestIntercept (context, interceptOpt, req, res, ssl, next) {
method is (line 102) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/req/proxy.js
function replacePlaceholder0 (line 4) | function replacePlaceholder0 (url, matched, pre) {
function replacePlaceholder (line 19) | function replacePlaceholder (url, rOptions, pathMatched, hostnameMatched) {
function buildTargetUrl (line 38) | function buildTargetUrl (rOptions, urlConf, interceptOpt, matched, hostn...
function doProxy (line 64) | function doProxy (proxyConf, rOptions, req, interceptOpt, matched, hostn...
method requestIntercept (line 92) | requestIntercept (context, interceptOpt, req, res, ssl, next, matched, h...
method is (line 158) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/req/redirect.js
method requestIntercept (line 6) | requestIntercept (context, interceptOpt, req, res, ssl, next, matched, h...
method is (line 30) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/req/requestReplace.js
constant REMOVE (line 1) | const REMOVE = '[remove]'
function replaceRequestHeaders (line 3) | function replaceRequestHeaders (rOptions, headers, log) {
method requestIntercept (line 25) | requestIntercept (context, interceptOpt, req, res, ssl, next) {
method is (line 51) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/req/sni.js
method requestIntercept (line 4) | requestIntercept (context, interceptOpt, req, res, ssl, next) {
method is (line 22) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/req/success.js
method requestIntercept (line 4) | requestIntercept (context, interceptOpt, req, res, ssl, next) {
method is (line 85) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/req/unVerifySsl.js
method requestIntercept (line 4) | requestIntercept (context, interceptOpt, req, res, ssl, next) {
method is (line 18) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/res/AfterOPTIONSHeaders.js
method responseIntercept (line 7) | responseIntercept (context, interceptOpt, req, res, proxyReq, proxyRes, ...
method is (line 28) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/res/cacheResponse.js
method responseIntercept (line 6) | responseIntercept (context, interceptOpt, req, res, proxyReq, proxyRes, ...
method is (line 108) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/res/responseReplace.js
constant REMOVE (line 4) | const REMOVE = '[remove]'
function replaceResponseHeaders (line 7) | function replaceResponseHeaders (newHeaders, res, proxyRes) {
method responseIntercept (line 70) | responseIntercept (context, interceptOpt, req, res, proxyReq, proxyRes, ...
method is (line 113) | is (interceptOpt) {
FILE: packages/mitmproxy/src/lib/interceptor/impl/res/script.js
constant SCRIPT_URL_PRE (line 6) | const SCRIPT_URL_PRE = '/____ds_script____/' // 内置脚本的请求地址前缀
constant SCRIPT_PROXY_URL_PRE (line 7) | const SCRIPT_PROXY_URL_PRE = '/____ds_script_proxy____/' // 绝对地址脚本的伪脚本地址前缀
constant REMOVE (line 8) | const REMOVE = '[remove]' // 标记需要移除的头信息
function getScript (line 10) | function getScript (key, script) {
function getScriptByUrlOrPath (line 16) | function getScriptByUrlOrPath (scriptUrlOrPath) {
method responseIntercept (line 23) | responseIntercept (context, interceptOpt, req, res, proxyReq, proxyRes, ...
method is (line 92) | is (interceptOpt) {
method handleScriptInterceptConfig (line 96) | handleScriptInterceptConfig (intercepts) {
FILE: packages/mitmproxy/src/lib/interceptor/index.js
constant OPTIONS (line 2) | const OPTIONS = require('./impl/req/OPTIONS.js')
FILE: packages/mitmproxy/src/lib/monkey/index.js
function buildScript (line 7) | function buildScript (sc, content, scriptName) {
function loadScript (line 66) | function loadScript (content, scriptName) {
function readFile (line 105) | function readFile (rootDir, script) {
method get (line 113) | get (rootDir) {
method load (line 119) | load (rootDir) {
FILE: packages/mitmproxy/src/lib/proxy/common/ProxyHttpAgent.js
method getName (line 5) | getName (option) {
FILE: packages/mitmproxy/src/lib/proxy/common/ProxyHttpsAgent.js
method getName (line 5) | getName (option) {
FILE: packages/mitmproxy/src/lib/proxy/common/config.js
function buildDefaultCABasePath (line 20) | function buildDefaultCABasePath () {
FILE: packages/mitmproxy/src/lib/proxy/common/util.js
function getTimeoutConfig (line 17) | function getTimeoutConfig (hostname, serverSetting) {
function createHttpsAgent (line 28) | function createHttpsAgent (timeoutConfig, verifySsl) {
function createHttpAgent (line 60) | function createHttpAgent (timeoutConfig) {
function createAgent (line 73) | function createAgent (protocol, timeoutConfig, verifySsl) {
FILE: packages/mitmproxy/src/lib/proxy/compatible/compatible.js
function _getConnectConfig (line 33) | function _getConnectConfig (hostname, port) {
function _getRequestConfig (line 38) | function _getRequestConfig (hostname, port) {
function _loadFromFile (line 46) | function _loadFromFile (defaultConfig) {
function _saveConfigToFile (line 73) | function _saveConfigToFile () {
method getConnectCompatibleConfig (line 94) | getConnectCompatibleConfig (hostname, port, manualCompatibleConfig = nul...
method setConnectSsl (line 102) | setConnectSsl (hostname, port, ssl, autoSave = true) {
method getRequestCompatibleConfig (line 126) | getRequestCompatibleConfig (rOptions, manualCompatibleConfig = null) {
method setRequestRejectUnauthorized (line 134) | setRequestRejectUnauthorized (rOptions, rejectUnauthorized, autoSave = t...
FILE: packages/mitmproxy/src/lib/proxy/middleware/InsertScriptMiddleware.js
method getContentEncoding (line 25) | getContentEncoding (res) {
method getCodec (line 33) | getCodec (encoding) {
method supportedEncodingsStr (line 37) | supportedEncodingsStr () {
method isHtml (line 41) | isHtml (res) {
constant HEAD (line 46) | const HEAD = Buffer.from('</head>')
constant HEAD_UP (line 47) | const HEAD_UP = Buffer.from('</HEAD>')
constant BODY (line 48) | const BODY = Buffer.from('</body>')
constant BODY_UP (line 49) | const BODY_UP = Buffer.from('</BODY>')
function chunkByteReplace (line 51) | function chunkByteReplace (_this, chunk, enc, callback, append) {
function injectScriptIntoHtml (line 70) | function injectScriptIntoHtml (tags, chunk, script) {
function handleResponseHeaders (line 86) | function handleResponseHeaders (res, proxyRes) {
method requestIntercept (line 122) | requestIntercept (context, req, res, ssl, next) {
method responseInterceptor (line 152) | responseInterceptor (req, res, proxyReq, proxyRes, ssl, next, append) {
FILE: packages/mitmproxy/src/lib/proxy/middleware/overwall.js
function matched (line 14) | function matched (hostname, overWallTargetMap) {
function getUserBasePath (line 38) | function getUserBasePath () {
function getTmpPacFilePath (line 44) | function getTmpPacFilePath () {
function loadPacLastModifiedTime (line 48) | function loadPacLastModifiedTime (pacTxt) {
function savePacFile (line 60) | function savePacFile (pacTxt) {
function downloadPacAsync (line 92) | async function downloadPacAsync (pacConfig) {
function createOverwallMiddleware (line 128) | function createOverwallMiddleware (overWallConfig) {
FILE: packages/mitmproxy/src/lib/proxy/middleware/source/pac.js
function createPacClient (line 5) | function createPacClient (pacFilePath) {
FILE: packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js
function isSslConnect (line 10) | function isSslConnect (sslConnectInterceptors, req, cltSocket, head) {
function connect (line 55) | function connect (req, cltSocket, head, hostname, port, dnsConfig = null...
FILE: packages/mitmproxy/src/lib/proxy/mitmproxy/createRequestHandler.js
constant MAX_SLOW_TIME (line 13) | const MAX_SLOW_TIME = 8000 // 超过此时间 则认为太慢了
function countSlow (line 83) | function countSlow (isDnsIntercept, reason) {
function onFree (line 110) | function onFree () {
FILE: packages/mitmproxy/src/lib/proxy/mitmproxy/dnsLookup.js
function createIpChecker (line 5) | function createIpChecker (tester) {
method createLookupFunc (line 29) | createLookupFunc (res, dns, action, target, port, isDnsIntercept) {
FILE: packages/mitmproxy/src/lib/proxy/mitmproxy/index.js
method createProxy (line 12) | createProxy ({
method createCA (line 160) | createCA (caPaths) {
FILE: packages/mitmproxy/src/lib/proxy/tls/CertAndKeyContainer.js
method constructor (line 6) | constructor ({
method addCertPromise (line 19) | addCertPromise (certPromiseObj) {
method getCertPromise (line 28) | getCertPromise (hostname, port, dnsName, mappingHostNames) {
method reRankCert (line 59) | reRankCert (index) {
FILE: packages/mitmproxy/src/lib/proxy/tls/FakeServersCenter.js
function getDnsName (line 13) | function getDnsName (hostname) {
method constructor (line 33) | constructor ({ maxLength = 256, requestHandler, upgradeHandler, caCert, ...
method addServerPromise (line 45) | addServerPromise (serverPromiseObj) {
method getServerPromise (line 59) | getServerPromise (hostname, port, ssl, manualCompatibleConfig) {
method reRankServer (line 236) | reRankServer (index) {
FILE: packages/mitmproxy/src/lib/speed/SpeedTester.js
constant DISABLE_TIMEOUT (line 9) | const DISABLE_TIMEOUT = 60 * 60 * 1000
class SpeedTester (line 11) | class SpeedTester {
method constructor (line 12) | constructor ({ hostname, port }) {
method pickFastAliveIpObj (line 31) | pickFastAliveIpObj () {
method touch (line 47) | touch () {
method startChecker (line 54) | startChecker () {
method getIpListFromDns (line 73) | async getIpListFromDns (dnsMap) {
method getFromOneDns (line 96) | async getFromOneDns (dns) {
method test (line 100) | async test () {
method testBackups (line 118) | async testBackups () {
method doTest (line 133) | async doTest (item, aliveList) {
method testByTCP (line 164) | testByTCP (item) {
method testOne (line 258) | testOne (item) {
FILE: packages/mitmproxy/src/lib/speed/config.js
method getConfig (line 5) | getConfig () {
FILE: packages/mitmproxy/src/lib/speed/index.js
function addSpeedTest (line 9) | function addSpeedTest (hostname, port) {
function initSpeedTest (line 31) | function initSpeedTest (runtimeConfig) {
function getAllSpeedTester (line 44) | function getAllSpeedTester () {
function getSpeedTester (line 61) | function getSpeedTester (hostname, port) {
function reSpeedTest (line 72) | function reSpeedTest () {
function action (line 79) | function action (event) {
FILE: packages/mitmproxy/src/options.js
function buildIntercepts (line 12) | function buildIntercepts (intercepts) {
function getExclusionArray (line 20) | function getExclusionArray (exclusions) {
FILE: packages/mitmproxy/src/utils/util.js
method getNodeVersion (line 5) | getNodeVersion () {
FILE: packages/mitmproxy/src/utils/util.match.js
function isMatched (line 5) | function isMatched (url, regexp) {
function domainRegexply (line 22) | function domainRegexply (target) {
function domainMapRegexply (line 29) | function domainMapRegexply (hostMap) {
function matchHostname (line 63) | function matchHostname (hostMap, hostname, action) {
function merge (line 110) | function merge (oldObj, newObj) {
function matchHostnameAll (line 118) | function matchHostnameAll (hostMap, hostname, action) {
FILE: packages/mitmproxy/src/utils/util.process.js
method fireError (line 2) | fireError (e) {
method fireStatus (line 7) | fireStatus (status) {
FILE: packages/mitmproxy/test/baiduOcrTest.js
constant APP_ID (line 4) | const APP_ID = '101474620'
constant API_KEY (line 5) | const API_KEY = 'fqCvIHGisGwpsglzV2wdxZJ5'
constant SECRET_KEY (line 6) | const SECRET_KEY = 'RhTOXUA4V6CrGuCTJJvUQ7z6Nl4m0Lij'
FILE: packages/mitmproxy/test/dnsTest-abroad-doh-sni.mjs
function count (line 48) | function count (isSuccess, hostname, idx, dns, result, cost) {
FILE: packages/mitmproxy/test/dnsTest-abroad-dot-sni.mjs
function count (line 65) | function count (isSuccess, hostname, idx, dns, result, cost) {
FILE: packages/mitmproxy/test/lodashTest.js
function isEmpty (line 13) | function isEmpty (obj) {
FILE: test/test.js
function testRequest (line 53) | function testRequest () {
Condensed preview — 222 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (938K chars).
[
{
"path": ".github/ISSUE_TEMPLATE/1_BUG_REPORT.md",
"chars": 627,
"preview": "---\nname: 问题上报\nabout: 如果你在使用过程中发现问题,请使用此模板。\nlabels: Bug\n---\n\n<!-- 如果搜索过但未找到,请将 `[ ]` 替换为 `[x]` -->\n\n- [ ] 你是否在现有 [Issue列"
},
{
"path": ".github/ISSUE_TEMPLATE/2_STYLE_ISSUE.md",
"chars": 282,
"preview": "---\nname: 样式问题\nabout: 如果你发现了一些页面样式问题,请使用此模板。\nlabels: Style Issue\n---\n\n<!-- 如果搜索过但未找到,请将 `[ ]` 替换为 `[x]` -->\n\n- [ ] 你是否在现"
},
{
"path": ".github/ISSUE_TEMPLATE/3_CONFIG_ISSUES.md",
"chars": 631,
"preview": "---\nname: 配置问题\nabout: 如果你不知道如何配置DS来访问某个网站,请使用这个模板。\nlabels: Config Issue\n---\n\n### Ⅰ. 你对哪个功能的配置不了解?\n\n<!-- 请选择一个或多个选项,将前面的 "
},
{
"path": ".github/ISSUE_TEMPLATE/4_FEATURE_REQUEST.md",
"chars": 297,
"preview": "---\nname: 提新需求\nabout: 如果你想提出一个新需求,请使用此模板。\nlabels: Feature Request\n---\n\n### Ⅰ. 请描述你想要的新功能:\n\n<!-- 请简单描述你希望的新功能,例如:\"在某某页面,添"
},
{
"path": ".github/ISSUE_TEMPLATE/5_OTHERS.md",
"chars": 65,
"preview": "---\nname: 其他问题\nabout: 如果不是以上问题,请使用此模板。\n---\n\n### 请详细描述你的问题、需求或建议:\n"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 135,
"preview": "### Ⅰ. 描述此PR的作用:\n\n### Ⅱ. 此PR修复了哪个issue吗?\n\n<!-- 如果是的话,请在下一行写上 \"fixes #xxx\",比如:fixes #97 -->\n\n### Ⅲ. 界面变化截屏\n\n<!-- 如果存在界面上的"
},
{
"path": ".github/workflows/build-and-release.yml",
"chars": 20075,
"preview": "name: Build And Release\n\non:\n push:\n branches:\n - release*\n\njobs:\n # job 1\n build-and-upload:\n runs-on: ${"
},
{
"path": ".github/workflows/npm-run-electron.yml",
"chars": 3400,
"preview": "name: npm run electron\n\non:\n push:\n branches:\n - run*\n - test*\n - release*\n paths-ignore:\n - "
},
{
"path": ".github/workflows/test-and-upload.yml",
"chars": 15034,
"preview": "name: Test And Upload\n\non:\n push:\n branches:\n - master\n - 1.x\n - develop\n - test*\n paths-igno"
},
{
"path": ".gitignore",
"chars": 175,
"preview": "# IntelliJ project files\n.idea\n*.iml\n\n# vscode settings files\n.vscode\n\n# Mac\n.DS_Store\n\n# Node files\nnode_modules/\n*.loc"
},
{
"path": ".npmrc",
"chars": 22,
"preview": "shamefully-hoist=true\n"
},
{
"path": "LICENSE",
"chars": 16725,
"preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
},
{
"path": "README.md",
"chars": 11258,
"preview": "# dev-sidecar\n\n开发者边车,命名取自service-mesh的service-sidecar,意为为开发者打辅助的边车工具(以下简称ds)\n通过本地代理的方式将https请求代理到一些国内的加速通道上\n\n<a href='ht"
},
{
"path": "_script/0、updateDependencies.bat",
"chars": 148,
"preview": "node -v\n\n# 安装ncu\n# npm install -g npm-check-updates\n\ncd ../packages/core\nncu -u\n\n# cd ../packages/gui\n# ncu -u\n\n# cd ../"
},
{
"path": "_script/1、setupEnv.bat",
"chars": 78,
"preview": "node -v\n\ncd ../\nnpm install -g pnpm --registry=https://registry.npmmirror.com\n"
},
{
"path": "_script/2、installProject.bat",
"chars": 40,
"preview": "node -v\n\ncd ../\nchcp 65001\npnpm install\n"
},
{
"path": "_script/3、buildAndRun.bat",
"chars": 56,
"preview": "node -v\n\ncd ../packages/gui\nchcp 65001\nnpm run electron\n"
},
{
"path": "_script/4.1、runTestCore.bat",
"chars": 43,
"preview": "node -v\n\ncd ../packages/core\npnpm run test\n"
},
{
"path": "_script/4.2、runTestMitmproxy.bat",
"chars": 48,
"preview": "node -v\n\ncd ../packages/mitmproxy\npnpm run test\n"
},
{
"path": "_script/5、generateSetupFile.bat",
"chars": 124,
"preview": "node -v\n\ncd ../packages/gui\n\nif not exist \"dist_electron\" mkdir \"dist_electron\"\nstart dist_electron\n\nnpm run electron:bu"
},
{
"path": "doc/caroot.md",
"chars": 1402,
"preview": "# 关于信任根证书的说明\n\n## 一、为什么要信任根证书。\n\n要回答这个问题需要先掌握下面两个知识点\n\n### 知识点1:什么是根证书\n\n[百度百科-什么是根证书](https://baike.baidu.com/item/%E6%A0%B"
},
{
"path": "doc/linux.md",
"chars": 1392,
"preview": "# Linux 支持\n\n`Linux`使用说明,目前仅官方支持`Ubuntu x86_64 GNOME桌面版(原版)`,其他`Linux`未测试\n\n> 注意:需要开启 [sudo 免密支持](https://www.jianshu.com/"
},
{
"path": "doc/other.md",
"chars": 648,
"preview": "# 其他程序使用\n\n## Java程序使用\n\n> 由 [Enaium](https://github.com/Enaium) 提供,未做验证,可供参考\n\n1. 先通过keytool安装证书:\n\n ```shell\n keytool "
},
{
"path": "doc/recover.md",
"chars": 477,
"preview": "# 卸载与恢复网络\n\n由于应用启动后会自动设置系统代理,正常退出时会关闭系统代理。\n当应用意外关闭,或者未正常退出后被卸载,此时会因为系统代理没有恢复从而导致完全上不了网。\n目前electron在windows系统上无法监听系统重启事件。更"
},
{
"path": "doc/wiki/Home.md",
"chars": 2638,
"preview": "> **给作者打个广告:**<br>\n> [https://github.com/certd/certd](https://github.com/certd/certd) 我的开源证书管理工具项目,全自动申请和部署证书,有需求的可以去试试,"
},
{
"path": "doc/wiki/加速服务使用说明.md",
"chars": 4804,
"preview": "# 1. 加速服务:\n\n1. 什么是 `加速服务`?\n\n - `加速服务` 即 `代理服务`,它通过中间人攻击的方式,将网络请求拦截下来,并经过DNS加速、修改、重定向、代理等一系列的功能,达到加速访问、或访问原本无法访问的站点等目的。"
},
{
"path": "doc/wiki/各平台安装说明.md",
"chars": 350,
"preview": "|平台|安装说明 |\n|---|---|\n| 【Windows】 | 下载后提示无法验证发行者时,选择保留即可 <br/>注意:开着ds重启电脑会导致无法上网,你可以再次打开ds,然后右键小图标退出ds即可。[更多说明](https://g"
},
{
"path": "doc/wiki/解决Github访问不了或速度很慢的问题.md",
"chars": 427,
"preview": "> 注:请使用 `v2.0.0-RC2` 及以上版本,下载地址:https://github.com/docmirror/dev-sidecar/releases\n\n目前,Github通过预设置的IP来访问的,选取测速排在前的IP。\n\n可是"
},
{
"path": "eslint.config.js",
"chars": 628,
"preview": "import antfu from '@antfu/eslint-config'\n\nexport default antfu(\n {\n vue: {\n vueVersion: 2,\n },\n rules: {\n"
},
{
"path": "package.json",
"chars": 479,
"preview": "{\n \"name\": \"dev-sidecar-parent\",\n \"type\": \"module\",\n \"private\": false,\n \"packageManager\": \"pnpm@9.13.2\",\n \"author\":"
},
{
"path": "packages/cli/LICENSE",
"chars": 16725,
"preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
},
{
"path": "packages/cli/cli.js",
"chars": 38,
"preview": "#!/usr/bin/env node\n\nrequire('./src')\n"
},
{
"path": "packages/cli/package.json",
"chars": 455,
"preview": "{\n \"name\": \"@docmirror/dev-sidecar-cli\",\n \"version\": \"2.0.1\",\n \"private\": false,\n \"description\": \"给开发者的加速代理工具\",\n \"a"
},
{
"path": "packages/cli/src/banner.txt",
"chars": 321,
"preview": " ____ _____ _ __\n / __ \\___ _ __ / ___/(_)___/ /__ _________ ______\n / / / / _ \\ | / /_"
},
{
"path": "packages/cli/src/index.js",
"chars": 995,
"preview": "const fs = require('node:fs')\nconst DevSidecar = require('@docmirror/dev-sidecar')\nconst jsonApi = require('@docmirror/m"
},
{
"path": "packages/cli/src/mitmproxy.js",
"chars": 1228,
"preview": "const fs = require('node:fs')\nconst path = require('node:path')\nconst server = require('@docmirror/mitmproxy')\nconst jso"
},
{
"path": "packages/cli/src/user_config.json5",
"chars": 748,
"preview": "{\n \"app\": {\n \"autoStart\": {\n \"enabled\": true\n },\n \"mode\": \"default\"\n },\n \"plugin\": {\n \"node\": {\n "
},
{
"path": "packages/core/LICENSE",
"chars": 16725,
"preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
},
{
"path": "packages/core/index.js",
"chars": 639,
"preview": "module.exports = require('./src')\n\n// TODO 这是一个解谜游戏 ↓ ↓ ↓ ↓ ↓ ↓ ,如果你破解了它,请不要公开,好好用它来学习和查资料吧(特别注意:为了你的人身安全,请不要用它来查看和发表不当"
},
{
"path": "packages/core/package.json",
"chars": 669,
"preview": "{\n \"name\": \"@docmirror/dev-sidecar\",\n \"version\": \"2.0.1\",\n \"private\": false,\n \"description\": \"给开发者的加速代理工具\",\n \"autho"
},
{
"path": "packages/core/src/config/index.js",
"chars": 13196,
"preview": "const path = require('node:path')\nconst configLoader = require('./local-config-loader')\n\nfunction getRootCaCertPath () {"
},
{
"path": "packages/core/src/config/local-config-loader.js",
"chars": 3200,
"preview": "const fs = require('node:fs')\nconst path = require('node:path')\nconst lodash = require('lodash')\nconst jsonApi = require"
},
{
"path": "packages/core/src/config/remote_config.json5",
"chars": 5739,
"preview": "{\n \"server\": {\n \"compatible\": {\n \"connect\": {\n \"218.18.106.132:443\": {\n \"ssl\": true\n }\n "
},
{
"path": "packages/core/src/config-api.js",
"chars": 8584,
"preview": "const fs = require('node:fs')\nconst jsonApi = require('@docmirror/mitmproxy/src/json')\nconst lodash = require('lodash')\n"
},
{
"path": "packages/core/src/event.js",
"chars": 828,
"preview": "const listener = {}\nlet index = 1\nfunction register (channel, handle, order = 10) {\n let handles = listener[channel]\n "
},
{
"path": "packages/core/src/expose.js",
"chars": 3045,
"preview": "const lodash = require('lodash')\nconst config = require('./config-api')\nconst event = require('./event')\nconst modules ="
},
{
"path": "packages/core/src/index.js",
"chars": 471,
"preview": "const expose = require('./expose.js')\nconst log = require('./utils/util.log.core')\n// process.env.NODE_TLS_REJECT_UNAUTH"
},
{
"path": "packages/core/src/merge.js",
"chars": 1710,
"preview": "const lodash = require('lodash')\n\n/**\n * 找出 newObj 相对于 oldObj 有差异的部分\n *\n * @param oldObj\n * @param newObj\n * @returns {{"
},
{
"path": "packages/core/src/modules/index.js",
"chars": 112,
"preview": "module.exports = {\n server: require('./server'),\n proxy: require('./proxy'),\n plugin: require('./plugin'),\n}\n"
},
{
"path": "packages/core/src/modules/plugin/git/config.js",
"chars": 348,
"preview": "module.exports = {\n name: 'Git.exe代理',\n enabled: false,\n tip: '如果你没有安装git命令行则不需要启动它',\n setting: {\n sslVerify: tru"
},
{
"path": "packages/core/src/modules/plugin/git/index.js",
"chars": 2439,
"preview": "const pluginConfig = require('./config')\n\nconst Plugin = function (context) {\n const { config, shell, event, log } = co"
},
{
"path": "packages/core/src/modules/plugin/index.js",
"chars": 133,
"preview": "module.exports = {\n node: require('./node'),\n git: require('./git'),\n pip: require('./pip'),\n overwall: require('./o"
},
{
"path": "packages/core/src/modules/plugin/node/config.js",
"chars": 1023,
"preview": "module.exports = {\n name: 'NPM加速',\n enabled: false,\n tip: '如果你没有安装nodejs则不需要启动它',\n startup: {\n variables: true,\n "
},
{
"path": "packages/core/src/modules/plugin/node/index.js",
"chars": 5602,
"preview": "const jsonApi = require('@docmirror/mitmproxy/src/json')\nconst nodeConfig = require('./config')\n\nconst NodePlugin = func"
},
{
"path": "packages/core/src/modules/plugin/overwall/config.js",
"chars": 1276,
"preview": "module.exports = {\n name: '梯子',\n enabled: false, // 默认关闭梯子\n server: {},\n serverDefault: {\n 'ow-prod.docmirror.top"
},
{
"path": "packages/core/src/modules/plugin/overwall/index.js",
"chars": 1154,
"preview": "const pluginConfig = require('./config')\n\nconst Plugin = function (context) {\n const { config, shell, event, log } = co"
},
{
"path": "packages/core/src/modules/plugin/pip/config.js",
"chars": 255,
"preview": "module.exports = {\n name: 'PIP加速',\n statusOff: true,\n enabled: null, // 没有开关\n tip: '如果你没有安装pip则不需要启动它',\n startup: {"
},
{
"path": "packages/core/src/modules/plugin/pip/index.js",
"chars": 2383,
"preview": "const pipConfig = require('./config')\n\nconst PipPlugin = function (context) {\n const { config, shell, event, log } = co"
},
{
"path": "packages/core/src/modules/proxy/index.js",
"chars": 5672,
"preview": "const ProxyPlugin = function (context) {\n const { config, event, shell, log } = context\n const api = {\n async start"
},
{
"path": "packages/core/src/modules/server/index.js",
"chars": 4885,
"preview": "const fork = require('node:child_process').fork\nconst fs = require('node:fs')\nconst path = require('node:path')\nconst lo"
},
{
"path": "packages/core/src/shell/index.js",
"chars": 803,
"preview": "const enableLoopback = require('./scripts/enable-loopback')\nconst extraPath = require('./scripts/extra-path')\nconst getN"
},
{
"path": "packages/core/src/shell/scripts/enable-loopback.js",
"chars": 1012,
"preview": "/**\n */\nconst Shell = require('../shell')\nconst extraPath = require('./extra-path')\nconst sudoPrompt = require('@vscode/"
},
{
"path": "packages/core/src/shell/scripts/extra-path/index.js",
"chars": 571,
"preview": "const path = require('node:path')\nconst log = require('../../../utils/util.log.core')\n\nfunction getExtraPath () {\n let "
},
{
"path": "packages/core/src/shell/scripts/get-npm-env.js",
"chars": 604,
"preview": "/**\n * 获取环境变量\n */\nconst jsonApi = require('@docmirror/mitmproxy/src/json')\nconst Shell = require('../shell')\n\nconst exec"
},
{
"path": "packages/core/src/shell/scripts/get-system-env.js",
"chars": 661,
"preview": "/**\n * 获取环境变量\n */\nconst Shell = require('../shell')\n\nconst execute = Shell.execute\n\nconst executor = {\n async windows ("
},
{
"path": "packages/core/src/shell/scripts/kill-by-port.js",
"chars": 691,
"preview": "const Shell = require('../shell')\n\nconst execute = Shell.execute\n\nconst executor = {\n async windows (exec, { port }) {\n"
},
{
"path": "packages/core/src/shell/scripts/set-npm-env.js",
"chars": 521,
"preview": "/**\n * 设置环境变量\n */\nconst Shell = require('../shell')\n\nconst execute = Shell.execute\n\nconst executor = {\n async windows ("
},
{
"path": "packages/core/src/shell/scripts/set-system-env.js",
"chars": 860,
"preview": "/**\n * 设置环境变量\n */\nconst Shell = require('../shell')\n\nconst execute = Shell.execute\n\nconst executor = {\n async windows ("
},
{
"path": "packages/core/src/shell/scripts/set-system-proxy/index.js",
"chars": 12193,
"preview": "/**\n * 获取环境变量\n */\nconst fs = require('node:fs')\nconst path = require('node:path')\nconst request = require('request')\ncon"
},
{
"path": "packages/core/src/shell/scripts/set-system-proxy/refresh-internet.js",
"chars": 568,
"preview": "const script = `\n$signature = @'\n[DllImport(\"wininet.dll\", SetLastError = true, CharSet=CharSet.Auto)]\npublic static ext"
},
{
"path": "packages/core/src/shell/scripts/setup-ca.js",
"chars": 625,
"preview": "const Shell = require('../shell')\n\nconst execute = Shell.execute\n\nconst executor = {\n async windows (exec, { certPath }"
},
{
"path": "packages/core/src/shell/shell.js",
"chars": 3512,
"preview": "const childProcess = require('node:child_process')\nconst os = require('node:os')\nconst fixPath = require('fix-path')\ncon"
},
{
"path": "packages/core/src/status.js",
"chars": 343,
"preview": "const lodash = require('lodash')\nconst event = require('./event')\nconst log = require('./utils/util.log.core')\n\nconst st"
},
{
"path": "packages/core/src/utils/util.date.js",
"chars": 800,
"preview": "module.exports = {\n\n format (date, needMill = true) {\n if (date == null) {\n return 'null'\n }\n\n const year"
},
{
"path": "packages/core/src/utils/util.log-or-console.js",
"chars": 1527,
"preview": "const dateUtil = require('./util.date')\n\nlet log = console\n\n// 将console中的日志缓存起来,当setLogger时,将控制台的日志写入日志文件\nlet backupLogs"
},
{
"path": "packages/core/src/utils/util.log.core.js",
"chars": 120,
"preview": "const loggerFactory = require('./util.logger')\n\nconst logger = loggerFactory.getLogger('core')\n\nmodule.exports = logger\n"
},
{
"path": "packages/core/src/utils/util.logger.js",
"chars": 2817,
"preview": "const path = require('node:path')\nconst log4js = require('log4js')\nconst logOrConsole = require('./util.log-or-console')"
},
{
"path": "packages/core/src/utils/util.version.js",
"chars": 2049,
"preview": "function parseVersion (version) {\n const matched = version.match(/^v?(\\d{1,2}(?:\\.\\d{1,2})*)(.*)$/)\n return {\n vers"
},
{
"path": "packages/core/test/configTest.js",
"chars": 450,
"preview": "// const config = require('../src/config-api')\n//\n// config.set({\n// server: {\n// intercepts: {\n// 'github1."
},
{
"path": "packages/core/test/httpsVerifyTest.js",
"chars": 1076,
"preview": "// const https = require('node:https')\n//\n// process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1'\n//\n// function request () {\n"
},
{
"path": "packages/core/test/macProxyTest.js",
"chars": 798,
"preview": "const assert = require('node:assert')\n\n// const childProcess = require('child_process')\n// const util = require('util')\n"
},
{
"path": "packages/core/test/mergeTest.js",
"chars": 1519,
"preview": "const assert = require('node:assert')\nconst lodash = require('lodash')\nconst mergeApi = require('../src/merge.js')\n\n// 默"
},
{
"path": "packages/core/test/regex.test.js",
"chars": 440,
"preview": "const assert = require('node:assert')\nconst expect = require('chai').expect\n// eslint-disable-next-line no-undef\ndescrib"
},
{
"path": "packages/core/test/requestTest.js",
"chars": 994,
"preview": "const HttpsAgent = require('@docmirror/mitmproxy/src/lib/proxy/common/ProxyHttpsAgent')\nconst request = require('request"
},
{
"path": "packages/core/test/versionTest.js",
"chars": 1025,
"preview": "const assert = require('node:assert')\nconst { isNewVersion } = require('../src/utils/util.version.js')\n\nfunction testIsN"
},
{
"path": "packages/gui/.editorconfig",
"chars": 121,
"preview": "[*.{js,jsx,ts,tsx,vue}]\nindent_style = space\nindent_size = 2\ntrim_trailing_whitespace = true\ninsert_final_newline = true"
},
{
"path": "packages/gui/.gitignore",
"chars": 292,
"preview": ".DS_Store\nnode_modules\n/dist\n\n\n# local env files\n.env.local\n.env.*.local\n\n# Log files\nnpm-debug.log*\nyarn-debug.log*\nyar"
},
{
"path": "packages/gui/LICENSE",
"chars": 16725,
"preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
},
{
"path": "packages/gui/README.md",
"chars": 324,
"preview": "# dev-sidecar-gui\n\n## Project setup\n\n```\nyarn install\n```\n\n### Compiles and hot-reloads for development\n\n```\nyarn serve\n"
},
{
"path": "packages/gui/babel.config.js",
"chars": 68,
"preview": "module.exports = {\n presets: [\n '@vue/babel-preset-jsx',\n ],\n}\n"
},
{
"path": "packages/gui/extra/pac/pac.txt",
"chars": 148279,
"preview": "[AutoProxy 0.2.9]\n! Checksum: BZUefB22itmhAjqqdpvRkA\n! Expires: 6h\n! Title: GFWList4LL\n! GFWList with EVERYTHING include"
},
{
"path": "packages/gui/extra/proxy/domestic-domain-allowlist.txt",
"chars": 16692,
"preview": "[SwitchyOmega Conditions]\n; Require: SwitchyOmega >= 2.3.2\n; Update Date: 2024/12/01\n; Author: Pluwen\n; Usage: https://g"
},
{
"path": "packages/gui/extra/scripts/github.script",
"chars": 28802,
"preview": "// ==UserScript==\n// @name Github 增强 - 高速下载\n// @name:zh-CN Github 增强 - 高速下载\n// @name:zh-TW Github 增強 - 高速下載\n"
},
{
"path": "packages/gui/extra/scripts/google.js",
"chars": 529,
"preview": "// ==UserScript==\n// @name google增强\n// @version 1.2.4\n// @author Greper\n// @description 去除ping链接\n// "
},
{
"path": "packages/gui/extra/scripts/tampermonkey.script",
"chars": 20274,
"preview": "/**\n * 篡改猴(Tampermonkey)| 油猴(Greasemonkey)浏览器脚本扩展\n *\n * @version 0.1.4\n * @since 2024-04-24 17:06\n * @au"
},
{
"path": "packages/gui/package.json",
"chars": 2004,
"preview": "{\n \"name\": \"@docmirror/dev-sidecar-gui\",\n \"version\": \"2.0.1\",\n \"private\": false,\n \"author\": {\n \"email\": \"xiaojunn"
},
{
"path": "packages/gui/pkg/after-all-artifact-build.js",
"chars": 914,
"preview": "const fs = require('node:fs')\nconst path = require('node:path')\nconst pkg = require('../package.json')\n\nfunction appendI"
},
{
"path": "packages/gui/pkg/after-pack.js",
"chars": 1511,
"preview": "const fs = require('node:fs')\nconst path = require('node:path')\nconst AdmZip = require('adm-zip')\nconst pkg = require('."
},
{
"path": "packages/gui/public/index.html",
"chars": 741,
"preview": "<!DOCTYPE html>\n<html lang=\"en\" style=\"height: 100%\">\n <head>\n <meta charset=\"utf-8\" />\n <meta http-equiv=\"X-UA-C"
},
{
"path": "packages/gui/src/background/powerMonitor.js",
"chars": 3156,
"preview": "import { acquireShutdownBlock, insertWndProcHook, releaseShutdownBlock, removeWndProcHook, setMainWindowHandle } from '@"
},
{
"path": "packages/gui/src/background.js",
"chars": 15497,
"preview": "'use strict'\n/* global __static */\nimport path from 'node:path'\nimport DevSidecar from '@docmirror/dev-sidecar'\nimport {"
},
{
"path": "packages/gui/src/bridge/api/backend.js",
"chars": 5295,
"preview": "import fs from 'node:fs'\nimport path from 'node:path'\nimport DevSidecar from '@docmirror/dev-sidecar'\nimport { ipcMain }"
},
{
"path": "packages/gui/src/bridge/api/open-enable-loopback.js",
"chars": 897,
"preview": "/* global __static */\nimport DevSidecar from '@docmirror/dev-sidecar'\nimport sudoPrompt from '@vscode/sudo-prompt'\nimpor"
},
{
"path": "packages/gui/src/bridge/auto-start/backend.js",
"chars": 1658,
"preview": "import DevSidecar from '@docmirror/dev-sidecar'\n\nasync function setAutoStartForLinux (app, enable = true) {\n const path"
},
{
"path": "packages/gui/src/bridge/auto-start/front.js",
"chars": 359,
"preview": "function install (app, api) {\n api.ipc.on('auto-start', (event, message) => {\n if (message.value === true) {\n a"
},
{
"path": "packages/gui/src/bridge/backend.js",
"chars": 540,
"preview": "import api from './api/backend'\nimport autoStart from './auto-start/backend'\nimport fileSelector from './file-selector/b"
},
{
"path": "packages/gui/src/bridge/error/front.js",
"chars": 1175,
"preview": "let latestConfirmTime = null\n\nfunction install (app, api) {\n api.ipc.on('error.core', (event, message) => {\n console"
},
{
"path": "packages/gui/src/bridge/file-selector/backend.js",
"chars": 877,
"preview": "export default {\n install (context) {\n const { ipcMain, dialog, log } = context\n ipcMain.on('file-selector', (eve"
},
{
"path": "packages/gui/src/bridge/file-selector/front.js",
"chars": 1781,
"preview": "function install (app, api) {\n api.fileSelector = {\n\n /**\n * 打开文件选择框\n *\n * 支持传参方式:\n * 1. open(String"
},
{
"path": "packages/gui/src/bridge/front.js",
"chars": 565,
"preview": "// import api from './api/front'\nimport autoStart from './auto-start/front'\nimport error from './error/front'\nimport fil"
},
{
"path": "packages/gui/src/bridge/mitmproxy.js",
"chars": 1006,
"preview": "const fs = require('node:fs')\nconst path = require('node:path')\nconst server = require('@docmirror/mitmproxy')\nconst jso"
},
{
"path": "packages/gui/src/bridge/on-close/front.js",
"chars": 1462,
"preview": "let closeType = 2\nlet doSave = false\n\nfunction install (app, api) {\n api.ipc.on('close.showTip', (event, message) => {\n"
},
{
"path": "packages/gui/src/bridge/tongji/backend.js",
"chars": 1565,
"preview": "/**\n * first step\n * @param {*} ipcMain\n */\nfunction ebtMain (ipcMain) {\n const isDevelopment = process.env.NODE_ENV !="
},
{
"path": "packages/gui/src/bridge/tongji/front.js",
"chars": 1581,
"preview": "/**\n * second step\n * @param {*} ipcRenderer\n * @param {*} siteId\n * @param {*} router\n */\nfunction ebtRenderer (ipcRend"
},
{
"path": "packages/gui/src/bridge/update/backend.js",
"chars": 11362,
"preview": "import fs from 'node:fs'\nimport path from 'node:path'\nimport DevSidecar from '@docmirror/dev-sidecar'\nimport AdmZip from"
},
{
"path": "packages/gui/src/bridge/update/front.js",
"chars": 7060,
"preview": "function install (app, api) {\n const updateParams = app.$global.update = { fromUser: false, autoDownload: false, progre"
},
{
"path": "packages/gui/src/main.js",
"chars": 1934,
"preview": "import antd from 'ant-design-vue'\nimport Vue from 'vue'\nimport VueRouter from 'vue-router'\nimport SearchBar from 'search"
},
{
"path": "packages/gui/src/utils/util.apppath.js",
"chars": 754,
"preview": "import os from 'node:os'\nimport path from 'node:path'\nimport log from './util.log.gui'\n\nfunction getSystemPlatform (thro"
},
{
"path": "packages/gui/src/utils/util.log.gui.js",
"chars": 150,
"preview": "const loggerFactory = require('@docmirror/dev-sidecar/src/utils/util.logger')\n\nconst logger = loggerFactory.getLogger('g"
},
{
"path": "packages/gui/src/view/App.vue",
"chars": 7027,
"preview": "<script>\nimport { ipcRenderer } from 'electron'\nimport createMenus from '@/view/router/menu'\nimport zhCN from 'ant-desig"
},
{
"path": "packages/gui/src/view/api.js",
"chars": 1526,
"preview": "import { ipcRenderer, shell } from 'electron'\nimport lodash from 'lodash'\nimport path from 'node:path'\n\nlet inited = fal"
},
{
"path": "packages/gui/src/view/components/container.vue",
"chars": 1116,
"preview": "<script>\nexport default {\n name: 'DsContainer',\n}\n</script>\n\n<template>\n <div class=\"ds-container\">\n <div class=\"bo"
},
{
"path": "packages/gui/src/view/components/mock-input.vue",
"chars": 775,
"preview": "<!--\n 组件:模拟输入框(当前为简易版本,只添加了value属性)\n 作用:全文检索(SearchBar)组件,无法检索 `<a-input/>` 的内容,所以使用 `<span contenteditable=\"true\"></s"
},
{
"path": "packages/gui/src/view/components/setup-ca.vue",
"chars": 2445,
"preview": "<script>\nexport default {\n name: 'SetupCa',\n components: {\n\n },\n props: {\n title: {\n type: String,\n def"
},
{
"path": "packages/gui/src/view/components/tree-node.vue",
"chars": 915,
"preview": "<script>\nexport default {\n name: 'TreeNode',\n props: {\n treeData: Array,\n },\n methods: {\n async openExternal ("
},
{
"path": "packages/gui/src/view/composables/theme.js",
"chars": 65,
"preview": "import { ref } from 'vue'\n\nexport const colorTheme = ref('dark')\n"
},
{
"path": "packages/gui/src/view/index.js",
"chars": 473,
"preview": "import modules from '../bridge/front'\nimport { apiInit, useApi } from './api'\nimport status from './status'\n\nexport defa"
},
{
"path": "packages/gui/src/view/mixins/plugin.js",
"chars": 4188,
"preview": "import lodash from 'lodash'\nimport DsContainer from '../components/container'\n\nexport default {\n components: {\n DsCo"
},
{
"path": "packages/gui/src/view/pages/help.vue",
"chars": 831,
"preview": "<script>\nimport Plugin from '../mixins/plugin'\nimport TreeNode from '../components/tree-node'\n\nexport default {\n name: "
},
{
"path": "packages/gui/src/view/pages/index.vue",
"chars": 12838,
"preview": "<script>\nimport lodash from 'lodash'\nimport DsContainer from '../components/container'\nimport SetupCa from '../component"
},
{
"path": "packages/gui/src/view/pages/plugin/git.vue",
"chars": 3846,
"preview": "<script>\nimport Plugin from '../../mixins/plugin'\nimport MockInput from '@/view/components/mock-input.vue'\n\nexport defau"
},
{
"path": "packages/gui/src/view/pages/plugin/node.vue",
"chars": 5219,
"preview": "<script>\nimport Plugin from '../../mixins/plugin'\n\nexport default {\n name: 'Node',\n mixins: [Plugin],\n data () {\n "
},
{
"path": "packages/gui/src/view/pages/plugin/overwall.vue",
"chars": 8018,
"preview": "<script>\nimport Plugin from '../../mixins/plugin'\nimport MockInput from '@/view/components/mock-input.vue'\n\nexport defau"
},
{
"path": "packages/gui/src/view/pages/plugin/pip.vue",
"chars": 5228,
"preview": "<script>\nimport Plugin from '../../mixins/plugin'\n\nexport default {\n name: 'Pip',\n mixins: [Plugin],\n data () {\n r"
},
{
"path": "packages/gui/src/view/pages/proxy.vue",
"chars": 7247,
"preview": "<script>\nimport Plugin from '../mixins/plugin'\nimport MockInput from '@/view/components/mock-input.vue'\n\nexport default "
},
{
"path": "packages/gui/src/view/pages/server.vue",
"chars": 18894,
"preview": "<script>\nimport _ from 'lodash'\nimport VueJsonEditor from 'vue-json-editor-fix-cn'\nimport Plugin from '../mixins/plugin'"
},
{
"path": "packages/gui/src/view/pages/setting.vue",
"chars": 18106,
"preview": "<script>\nimport { ipcRenderer } from 'electron'\nimport Plugin from '../mixins/plugin'\nimport { colorTheme } from '../com"
},
{
"path": "packages/gui/src/view/router/index.js",
"chars": 811,
"preview": "import Index from '../pages/index'\nimport Git from '../pages/plugin/git'\nimport Node from '../pages/plugin/node'\nimport "
},
{
"path": "packages/gui/src/view/router/menu.js",
"chars": 832,
"preview": "export default function createMenus (app) {\n const plugins = [\n { title: 'NPM加速', path: '/plugin/node', icon: 'like'"
},
{
"path": "packages/gui/src/view/status.js",
"chars": 572,
"preview": "import lodash from 'lodash'\nimport Vue from 'vue'\n\nconst status = {\n server: {\n enabled: false,\n },\n proxy: {\n "
},
{
"path": "packages/gui/src/view/style/index.scss",
"chars": 2446,
"preview": ".footer-bar {\n padding: 10px;\n text-align: right;\n border-top: #eee 1px solid;\n}\n\n.flex-l-r {\n align-content: center"
},
{
"path": "packages/gui/src/view/style/theme/dark.scss",
"chars": 5211,
"preview": "/* 暗色主题 */\n$dark-logo: url('../../../../public/logo/logo-lang-light.svg');\n$dark-bg: #1e1f22; //背景\n$dark-bg-highlight: #"
},
{
"path": "packages/gui/vue.config.js",
"chars": 4166,
"preview": "const path = require('node:path')\nconst { defineConfig } = require('@vue/cli-service')\nconst webpack = require('webpack'"
},
{
"path": "packages/mitmproxy/LICENSE",
"chars": 16725,
"preview": "Mozilla Public License Version 2.0\n==================================\n\n1. Definitions\n--------------\n\n1.1. \"Contributor\""
},
{
"path": "packages/mitmproxy/index.js",
"chars": 34,
"preview": "module.exports = require('./src')\n"
},
{
"path": "packages/mitmproxy/package.json",
"chars": 667,
"preview": "{\n \"name\": \"@docmirror/mitmproxy\",\n \"version\": \"2.0.1\",\n \"private\": false,\n \"description\": \"\",\n \"author\": \"docmirro"
},
{
"path": "packages/mitmproxy/src/index.js",
"chars": 3608,
"preview": "const mitmproxy = require('./lib/proxy')\nconst proxyConfig = require('./lib/proxy/common/config')\nconst speedTest = requ"
},
{
"path": "packages/mitmproxy/src/json.js",
"chars": 841,
"preview": "const logOrConsole = require('@docmirror/dev-sidecar/src/utils/util.log-or-console')\nlet JSON5 = require('json5')\nif (JS"
},
{
"path": "packages/mitmproxy/src/lib/choice/RequestCounter.js",
"chars": 79,
"preview": "const { ChoiceCache } = require('./index')\n\nmodule.exports = new ChoiceCache()\n"
},
{
"path": "packages/mitmproxy/src/lib/choice/index.js",
"chars": 3160,
"preview": "const LRUCache = require('lru-cache')\nconst log = require('../../utils/util.log.server')\n\nconst cacheSize = 1024\n\nclass "
},
{
"path": "packages/mitmproxy/src/lib/dns/base.js",
"chars": 6862,
"preview": "const LRUCache = require('lru-cache')\nconst log = require('../../utils/util.log.server')\nconst matchUtil = require('../."
},
{
"path": "packages/mitmproxy/src/lib/dns/https.js",
"chars": 1151,
"preview": "const { promisify } = require('node:util')\nconst doh = require('dns-over-http')\nconst BaseDNS = require('./base')\nconst "
},
{
"path": "packages/mitmproxy/src/lib/dns/index.js",
"chars": 3525,
"preview": "const matchUtil = require('../../utils/util.match')\nconst log = require('../../utils/util.log.server')\nconst DNSOverPreS"
},
{
"path": "packages/mitmproxy/src/lib/dns/preset.js",
"chars": 232,
"preview": "const BaseDNS = require('./base')\n\nmodule.exports = class DNSOverPreSetIpList extends BaseDNS {\n constructor (preSetIpL"
},
{
"path": "packages/mitmproxy/src/lib/dns/tcp.js",
"chars": 1549,
"preview": "const net = require('node:net')\nconst { Buffer } = require('node:buffer')\nconst dnsPacket = require('dns-packet')\nconst "
},
{
"path": "packages/mitmproxy/src/lib/dns/tls.js",
"chars": 817,
"preview": "const dnstls = require('./util/dns-over-tls')\nconst BaseDNS = require('./base')\n\nconst defaultPort = 853\n\nmodule.exports"
},
{
"path": "packages/mitmproxy/src/lib/dns/udp.js",
"chars": 1772,
"preview": "const dgram = require('node:dgram')\nconst dnsPacket = require('dns-packet')\nconst randi = require('random-int')\nconst Ba"
},
{
"path": "packages/mitmproxy/src/lib/dns/util/dns-over-tls.js",
"chars": 2206,
"preview": "/**\n * 由于组件 `dns-over-tls@0.0.9` 不支持 `rejectUnauthorized` 和 `timeout` 两个参数,所以将源码复制过来,并简化了代码。\n */\nconst dnsPacket = requi"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/req/OPTIONS.js",
"chars": 1772,
"preview": "const defaultAllowHeaders = '*'\nconst defaultAllowMethods = 'GET,POST,PUT,DELETE,HEAD,OPTIONS,PATCH' // CONNECT、TRACE被认为"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/req/abort.js",
"chars": 3103,
"preview": "module.exports = {\n name: 'abort',\n priority: 103,\n requestIntercept (context, interceptOpt, req, res, ssl, next) {\n "
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/req/baiduOcr.js",
"chars": 5370,
"preview": "function getTomorrow () {\n const now = new Date()\n const tomorrow = new Date(now)\n\n // 设置日期为明天\n tomorrow.setDate(now"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/req/cacheRequest.js",
"chars": 2986,
"preview": "function getMaxAge (interceptOpt) {\n // 秒\n if (interceptOpt.cacheSeconds > 0 || interceptOpt.cacheMaxAge > 0 || interc"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/req/proxy.js",
"chars": 5395,
"preview": "const url = require('node:url')\nconst lodash = require('lodash')\n\nfunction replacePlaceholder0 (url, matched, pre) {\n i"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/req/redirect.js",
"chars": 1019,
"preview": "const proxyApi = require('./proxy')\n\nmodule.exports = {\n name: 'redirect',\n priority: 105,\n requestIntercept (context"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/req/requestReplace.js",
"chars": 1803,
"preview": "const REMOVE = '[remove]'\n\nfunction replaceRequestHeaders (rOptions, headers, log) {\n for (const key in headers) {\n "
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/req/sni.js",
"chars": 977,
"preview": "module.exports = {\n name: 'sni',\n priority: 123,\n requestIntercept (context, interceptOpt, req, res, ssl, next) {\n "
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/req/success.js",
"chars": 3129,
"preview": "module.exports = {\n name: 'success',\n priority: 102,\n requestIntercept (context, interceptOpt, req, res, ssl, next) {"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/req/unVerifySsl.js",
"chars": 724,
"preview": "module.exports = {\n name: 'unVerifySsl',\n priority: 124,\n requestIntercept (context, interceptOpt, req, res, ssl, nex"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/res/AfterOPTIONSHeaders.js",
"chars": 983,
"preview": "const responseReplaceApi = require('./responseReplace')\n\nmodule.exports = {\n name: 'AfterOPTIONSHeaders',\n desc: '开启了o"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/res/cacheResponse.js",
"chars": 4408,
"preview": "const cacheReq = require('../req/cacheRequest')\n\nmodule.exports = {\n name: 'cacheResponse',\n priority: 202,\n response"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/res/responseReplace.js",
"chars": 3210,
"preview": "const lodash = require('lodash')\nconst cacheReq = require('../req/cacheRequest')\n\nconst REMOVE = '[remove]'\n\n// 替换响应头\nfu"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/impl/res/script.js",
"chars": 7151,
"preview": "const monkey = require('../../../monkey')\n// const CryptoJs = require('crypto-js')\nconst lodash = require('lodash')\ncons"
},
{
"path": "packages/mitmproxy/src/lib/interceptor/index.js",
"chars": 1040,
"preview": "// request interceptor impls\nconst OPTIONS = require('./impl/req/OPTIONS.js')\nconst success = require('./impl/req/succes"
},
{
"path": "packages/mitmproxy/src/lib/monkey/index.js",
"chars": 3424,
"preview": "const fs = require('node:fs')\nconst path = require('node:path')\nconst log = require('../../utils/util.log.server')\n\nlet "
},
{
"path": "packages/mitmproxy/src/lib/proxy/common/ProxyHttpAgent.js",
"chars": 307,
"preview": "const AgentOrigin = require('agentkeepalive')\n\nmodule.exports = class Agent extends AgentOrigin {\n // Hacky\n getName ("
},
{
"path": "packages/mitmproxy/src/lib/proxy/common/ProxyHttpsAgent.js",
"chars": 338,
"preview": "const HttpsAgentOrigin = require('agentkeepalive').HttpsAgent\n\nmodule.exports = class HttpsAgent extends HttpsAgentOrigi"
},
{
"path": "packages/mitmproxy/src/lib/proxy/common/config.js",
"chars": 911,
"preview": "const path = require('node:path')\n\nconst config = exports\n\nconfig.defaultHost = '127.0.0.1'\nconfig.defaultPort = 31181\nc"
},
{
"path": "packages/mitmproxy/src/lib/proxy/common/util.js",
"chars": 6675,
"preview": "const url = require('node:url')\nconst tunnelAgent = require('tunnel-agent')\nconst log = require('../../../utils/util.log"
},
{
"path": "packages/mitmproxy/src/lib/proxy/compatible/compatible.js",
"chars": 4711,
"preview": "/**\n * 自动兼容程序自适应生成配置\n * 此脚本会针对各种兼容性问题,为对应域名生成相应的兼容性配置,并将自适应配置写入到 `~/.dev-sidecar/automaticCompatibleConfig.json` 文件中。\n *"
},
{
"path": "packages/mitmproxy/src/lib/proxy/index.js",
"chars": 69,
"preview": "// require('babel-polyfill')\nmodule.exports = require('./mitmproxy')\n"
},
{
"path": "packages/mitmproxy/src/lib/proxy/middleware/InsertScriptMiddleware.js",
"chars": 5571,
"preview": "const zlib = require('node:zlib')\nconst through = require('through2')\nconst log = require('../../../utils/util.log.serve"
},
{
"path": "packages/mitmproxy/src/lib/proxy/middleware/overwall.js",
"chars": 7017,
"preview": "const { Buffer } = require('node:buffer')\nconst fs = require('node:fs')\nconst path = require('node:path')\nconst url = re"
},
{
"path": "packages/mitmproxy/src/lib/proxy/middleware/source/pac.js",
"chars": 21154,
"preview": "const fs = require('node:fs')\nconst path = require('node:path')\nconst log = require('../../../../utils/util.log.server')"
},
{
"path": "packages/mitmproxy/src/lib/proxy/mitmproxy/createConnectHandler.js",
"chars": 7394,
"preview": "const net = require('node:net')\nconst url = require('node:url')\nconst jsonApi = require('../../../json')\nconst log = req"
},
{
"path": "packages/mitmproxy/src/lib/proxy/mitmproxy/createFakeServerCenter.js",
"chars": 899,
"preview": "const fs = require('node:fs')\nconst forge = require('node-forge')\nconst log = require('../../../utils/util.log.server')\n"
},
{
"path": "packages/mitmproxy/src/lib/proxy/mitmproxy/createRequestHandler.js",
"chars": 13454,
"preview": "const http = require('node:http')\nconst https = require('node:https')\nconst jsonApi = require('../../../json')\nconst log"
},
{
"path": "packages/mitmproxy/src/lib/proxy/mitmproxy/createUpgradeHandler.js",
"chars": 1802,
"preview": "const http = require('node:http')\nconst https = require('node:https')\nconst log = require('../../../utils/util.log.serve"
},
{
"path": "packages/mitmproxy/src/lib/proxy/mitmproxy/dnsLookup.js",
"chars": 2357,
"preview": "const defaultDns = require('node:dns')\nconst log = require('../../../utils/util.log.server')\nconst speedTest = require('"
},
{
"path": "packages/mitmproxy/src/lib/proxy/mitmproxy/index.js",
"chars": 5728,
"preview": "const http = require('node:http')\nconst log = require('../../../utils/util.log.server')\nconst speedTest = require('../.."
},
{
"path": "packages/mitmproxy/src/lib/proxy/tls/CertAndKeyContainer.js",
"chars": 1959,
"preview": "const tlsUtils = require('./tlsUtils')\n// const https = require('https')\nconst log = require('../../../utils/util.log.se"
},
{
"path": "packages/mitmproxy/src/lib/proxy/tls/FakeServersCenter.js",
"chars": 9777,
"preview": "const http = require('node:http')\nconst https = require('node:https')\nconst tls = require('node:tls')\nconst forge = requ"
},
{
"path": "packages/mitmproxy/src/lib/proxy/tls/sniUtil.js",
"chars": 4858,
"preview": "module.exports = function extractSNI (data) {\n /*\n From https://tools.ietf.org/html/rfc5246:\n enum {\n hell"
},
{
"path": "packages/mitmproxy/src/lib/proxy/tls/tlsUtils.js",
"chars": 6970,
"preview": "const fs = require('node:fs')\nconst path = require('node:path')\nconst _ = require('lodash')\nconst forge = require('node-"
},
{
"path": "packages/mitmproxy/src/lib/speed/SpeedTester.js",
"chars": 8086,
"preview": "// const { exec } = require('node:child_process')\nconst net = require('node:net')\nconst _ = require('lodash')\nconst log "
},
{
"path": "packages/mitmproxy/src/lib/speed/config.js",
"chars": 110,
"preview": "const config = {\n dnsMap: {},\n}\nmodule.exports = {\n getConfig () {\n return config\n },\n notify: null,\n}\n"
},
{
"path": "packages/mitmproxy/src/lib/speed/index.js",
"chars": 2039,
"preview": "const _ = require('lodash')\nconst log = require('../../utils/util.log.server')\nconst config = require('./config')\nconst "
},
{
"path": "packages/mitmproxy/src/options.js",
"chars": 8115,
"preview": "const fs = require('node:fs')\nconst path = require('node:path')\nconst lodash = require('lodash')\nconst dnsUtil = require"
},
{
"path": "packages/mitmproxy/src/utils/util.js",
"chars": 216,
"preview": "// const os = require('os')\nconst log = require('./util.log.server')\n\nconst util = {\n getNodeVersion () {\n const ver"
},
{
"path": "packages/mitmproxy/src/utils/util.log.server.js",
"chars": 153,
"preview": "const loggerFactory = require('@docmirror/dev-sidecar/src/utils/util.logger')\n\nconst logger = loggerFactory.getLogger('s"
},
{
"path": "packages/mitmproxy/src/utils/util.match.js",
"chars": 5704,
"preview": "const lodash = require('lodash')\nconst log = require('./util.log.server')\nconst mergeApi = require('@docmirror/dev-sidec"
}
]
// ... and 22 more files (download for full content)
About this extraction
This page contains the full source code of the docmirror/dev-sidecar GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 222 files (863.1 KB), approximately 274.0k tokens, and a symbol index with 452 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.