Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": [
"@apify/ts"
],
"parserOptions": {
"project": "tsconfig.eslint.json"
},
"overrides": [
{
"files": [
"test/**/*.js"
],
"env": {
"jest": true
}
}
]
}
4 changes: 2 additions & 2 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ jobs:

strategy:
matrix:
os: [ubuntu-22.04] # add windows-latest later
node-version: [14, 16, 18]
os: [ubuntu-latest] # add windows-latest later
node-version: [10, 12, 14, 16]

steps:
-
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ jobs:

strategy:
matrix:
<<<<<<< HEAD:.github/workflows/release.yaml
os: [ubuntu-22.04] # add windows-latest later
node-version: [14, 16, 18]
=======
os: [ubuntu-latest] # add windows-latest later
node-version: [14, 16]
>>>>>>> f1bbe42 (release: 2.0.0 (#162)):.github/workflows/release.yml

steps:
-
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,7 @@ docs
package-lock.json
.nyc_output
dist
<<<<<<< HEAD
.vscode
=======
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
<<<<<<< HEAD
2.0.1 / 2022-05-02
=======
2.0.0 / 2021-10-12
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
==================
- Simplify code, fix tests, move to TypeScript [#162](https://github.com/apify/proxy-chain/pull/162)
- Bugfix: Memory leak in createTunnel [#160](https://github.com/apify/proxy-chain/issues/160)
- Bugfix: Proxy fails to handle non-standard HTTP response in HTTP forwarding mode, on certain websites [#107](https://github.com/apify/proxy-chain/issues/107)
<<<<<<< HEAD
- Pass proxyChainId to tunnelConnectResponded [#173](https://github.com/apify/proxy-chain/pull/173)
- feat: accept custom port for proxy anonymization [#214](https://github.com/apify/proxy-chain/pull/214)
- fix: socket close race condition
- feat: closeConnection by id [#176](https://github.com/apify/proxy-chain/pull/176)
- feat: custom dns lookup [#175](https://github.com/apify/proxy-chain/pull/175)
=======
>>>>>>> f1bbe42 (release: 2.0.0 (#162))

1.0.3 / 2021-08-17
==================
Expand Down
3 changes: 3 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { Config } from '@jest/types';

<<<<<<< HEAD
// eslint-disable-next-line import/no-default-export
=======
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
export default (): Config.InitialOptions => ({
verbose: true,
preset: 'ts-jest',
Expand Down
44 changes: 42 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"name": "proxy-chain",
<<<<<<< HEAD
"version": "2.5.9",
=======
"version": "2.0.0",
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
"description": "Node.js implementation of a proxy server (think Squid) with support for SSL, authentication, upstream proxy chaining, and protocol tunneling.",
"main": "dist/index.js",
"keywords": [
Expand Down Expand Up @@ -37,41 +41,74 @@
"prepublishOnly": "npm run build",
"local-proxy": "node ./dist/run_locally.js",
"test": "nyc cross-env NODE_OPTIONS=--insecure-http-parser mocha --bail",
<<<<<<< HEAD
"lint": "eslint .",
"lint:fix": "eslint . --fix"
=======
"lint": "eslint src",
"lint-fix": "eslint src --fix"
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
},
"engines": {
"node": ">=14"
},
"devDependencies": {
<<<<<<< HEAD
"@apify/eslint-config": "^1.0.0",
"@apify/tsconfig": "^0.1.0",
"@types/jest": "^28.1.2",
"@types/node": "^18.8.3",
"basic-auth": "^2.0.1",
"basic-auth-parser": "^0.0.2",
"body-parser": "^1.19.0",
"chai": "^4.3.4",
"chai": "^4.5.0",
"cross-env": "^7.0.3",
"eslint": "^9.18.0",
=======
"@apify/eslint-config-ts": "^0.1.4",
"@apify/tsconfig": "^0.1.0",
"@types/jest": "^27.0.2",
"@types/node": "^16.10.1",
"@typescript-eslint/eslint-plugin": "^4.31.2",
"basic-auth": "^2.0.1",
"basic-auth-parser": "^0.0.2",
"body-parser": "^1.19.0",
"chai": "^4.3.4",
"cross-env": "^7.0.3",
"eslint": "^7.32.0",
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
"express": "^4.17.1",
"faye-websocket": "^0.11.4",
"got-scraping": "^3.2.4-beta.0",
"isparta": "^4.1.1",
"mocha": "^10.0.0",
<<<<<<< HEAD
"mocha": "^10.8.2",
"nyc": "^15.1.0",
"portastic": "^1.0.1",
"proxy": "^1.0.2",
"puppeteer": "^19.6.3",
"request": "^2.88.2",
"rimraf": "^4.1.2",
"sinon": "^13.0.2",
=======
"mocha": "^9.1.2",
"nyc": "^15.1.0",
"phantomjs-prebuilt": "^2.1.16",
"portastic": "^1.0.1",
"proxy": "^1.0.2",
"request": "^2.88.2",
"rimraf": "^3.0.2",
"sinon": "^11.1.2",
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
"sinon-stub-promise": "^4.0.0",
"socksv5": "^0.0.6",
"through": "^2.3.8",
"ts-node": "^10.2.1",
"typescript": "^4.4.3",
<<<<<<< HEAD
"typescript-eslint": "^8.20.0",
=======
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
"underscore": "^1.13.1",
"ws": "^8.2.2"
},
Expand All @@ -84,10 +121,13 @@
"exclude": [
"**/test/**"
]
<<<<<<< HEAD
},
"dependencies": {
"socks": "^2.8.3",
"socks-proxy-agent": "^8.0.3",
"tslib": "^2.3.1"
=======
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
}
}
65 changes: 65 additions & 0 deletions src/anonymize_proxy.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
<<<<<<< HEAD
import type { Buffer } from 'node:buffer';
import type http from 'node:http';
import type net from 'node:net';
import { URL } from 'node:url';

import { Server, SOCKS_PROTOCOLS } from './server';
=======
import net from 'net';
import http from 'http';
import { Buffer } from 'buffer';
import { URL } from 'url';
import { Server } from './server';
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
import { nodeify } from './utils/nodeify';

// Dictionary, key is value returned from anonymizeProxy(), value is Server instance.
const anonymizedProxyUrlToServer: Record<string, Server> = {};

<<<<<<< HEAD
export interface AnonymizeProxyOptions {
url: string;
port: number;
Expand Down Expand Up @@ -52,11 +61,26 @@ export const anonymizeProxy = async (

// If upstream proxy requires no password or if there is no need to ignore HTTPS proxy cert errors, return it directly
if (!parsedProxyUrl.username && !parsedProxyUrl.password && (!ignoreProxyCertificate || parsedProxyUrl.protocol !== 'https:')) {
=======
/**
* Parses and validates a HTTP proxy URL. If the proxy requires authentication, then the function
* starts an open local proxy server that forwards to the upstream proxy.
*/
export const anonymizeProxy = (proxyUrl: string, callback?: (error: Error | null) => void): Promise<string> => {
const parsedProxyUrl = new URL(proxyUrl);
if (parsedProxyUrl.protocol !== 'http:') {
throw new Error('Invalid "proxyUrl" option: only HTTP proxies are currently supported.');
}

// If upstream proxy requires no password, return it directly
if (!parsedProxyUrl.username && !parsedProxyUrl.password) {
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
return nodeify(Promise.resolve(proxyUrl), callback);
}

let server: Server & { port: number };

<<<<<<< HEAD
const startServer = async () => {
return Promise.resolve().then(async () => {
server = new Server({
Expand All @@ -81,6 +105,32 @@ export const anonymizeProxy = async (
anonymizedProxyUrlToServer[url] = server;
return url;
});
=======
const startServer = () => {
return Promise.resolve()
.then(() => {
server = new Server({
// verbose: true,
port: 0,
prepareRequestFunction: () => {
return {
requestAuthentication: false,
upstreamProxyUrl: proxyUrl,
};
},
}) as Server & { port: number };

return server.listen();
});
};

const promise = startServer()
.then(() => {
const url = `http://127.0.0.1:${server.port}`;
anonymizedProxyUrlToServer[url] = server;
return url;
});
>>>>>>> f1bbe42 (release: 2.0.0 (#162))

return nodeify(promise, callback);
};
Expand All @@ -91,7 +141,11 @@ export const anonymizeProxy = async (
* and its result if `false`. Otherwise the result is `true`.
* @param closeConnections If true, pending proxy connections are forcibly closed.
*/
<<<<<<< HEAD
export const closeAnonymizedProxy = async (
=======
export const closeAnonymizedProxy = (
>>>>>>> f1bbe42 (release: 2.0.0 (#162))
anonymizedProxyUrl: string,
closeConnections: boolean,
callback?: (error: Error | null, result?: boolean) => void,
Expand All @@ -107,6 +161,7 @@ export const closeAnonymizedProxy = async (

delete anonymizedProxyUrlToServer[anonymizedProxyUrl];

<<<<<<< HEAD
const promise = server.close(closeConnections).then(() => {
return true;
});
Expand All @@ -122,6 +177,16 @@ type Callback = ({
socket: net.Socket;
head: Buffer;
}) => void;
=======
const promise = server.close(closeConnections)
.then(() => {
return true;
});
return nodeify(promise, callback);
};

type Callback = ({ response, socket, head }: { response: http.IncomingMessage; socket: net.Socket; head: Buffer; }) => void;
>>>>>>> f1bbe42 (release: 2.0.0 (#162))

/**
* Add a callback on 'tunnelConnectResponded' Event in order to get headers from CONNECT tunnel to proxy
Expand Down
Loading