From 9261abd2b16e6582045cd7a1eef535bbeb58d5ff Mon Sep 17 00:00:00 2001
From: AkiraFukushima
Date: Mon, 21 Oct 2019 22:24:59 +0900
Subject: [PATCH] refs #69 Add support to using socks proxy for REST, streaming
and websocket
---
example/typescript/yarn.lock | 33 +++++++++++++++++++++++++++++++++
package.json | 1 +
src/mastodon.ts | 16 ++++++++--------
src/proxy_config.ts | 24 ++++++++++++++++++++----
yarn.lock | 32 ++++++++++++++++++++++++++++++++
5 files changed, 94 insertions(+), 12 deletions(-)
diff --git a/example/typescript/yarn.lock b/example/typescript/yarn.lock
index 6bd7cf5..11a7a32 100644
--- a/example/typescript/yarn.lock
+++ b/example/typescript/yarn.lock
@@ -55,6 +55,13 @@ agent-base@^4.3.0:
dependencies:
es6-promisify "^5.0.0"
+agent-base@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
+ integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
+ dependencies:
+ es6-promisify "^5.0.0"
+
ajv@^5.3.0:
version "5.5.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
@@ -301,6 +308,11 @@ https-proxy-agent@^3.0.0:
agent-base "^4.3.0"
debug "^3.1.0"
+ip@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
+ integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
+
is-buffer@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
@@ -375,6 +387,7 @@ log4js@^5.2.2:
moment "^2.24.0"
oauth "^0.9.15"
request "^2.87.0"
+ socks-proxy-agent h3poteto/node-socks-proxy-agent#master
typescript "^3.4.5"
ws "^7.0.1"
@@ -476,6 +489,26 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+smart-buffer@4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d"
+ integrity sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==
+
+socks-proxy-agent@h3poteto/node-socks-proxy-agent#master:
+ version "4.0.2"
+ resolved "https://codeload.github.com/h3poteto/node-socks-proxy-agent/tar.gz/5be42d4a3f98c5a156d713ea88a54b825f26d1f3"
+ dependencies:
+ agent-base "~4.2.1"
+ socks "~2.3.2"
+
+socks@~2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.2.tgz#ade388e9e6d87fdb11649c15746c578922a5883e"
+ integrity sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==
+ dependencies:
+ ip "^1.1.5"
+ smart-buffer "4.0.2"
+
sshpk@^1.7.0:
version "1.14.2"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98"
diff --git a/package.json b/package.json
index 0a83c55..442cfd7 100644
--- a/package.json
+++ b/package.json
@@ -58,6 +58,7 @@
"moment": "^2.24.0",
"oauth": "^0.9.15",
"request": "^2.87.0",
+ "socks-proxy-agent": "h3poteto/node-socks-proxy-agent#master",
"typescript": "^3.4.5",
"ws": "^7.0.1"
},
diff --git a/src/mastodon.ts b/src/mastodon.ts
index c7b6ba9..748181f 100644
--- a/src/mastodon.ts
+++ b/src/mastodon.ts
@@ -1,5 +1,5 @@
import { OAuth2 } from 'oauth'
-import axios, { AxiosResponse, CancelTokenSource } from 'axios'
+import axios, { AxiosResponse, CancelTokenSource, AxiosRequestConfig } from 'axios'
import StreamListener from './stream_listener'
import WebSocket from './web_socket'
@@ -239,7 +239,7 @@ export default class Mastodon implements MegalodonInstance {
proxyConfig: ProxyConfig | false = false
): Promise> {
const apiUrl = baseUrl
- let options = {
+ let options: AxiosRequestConfig = {
params: params
}
if (proxyConfig) {
@@ -264,7 +264,7 @@ export default class Mastodon implements MegalodonInstance {
baseUrl = DEFAULT_URL,
proxyConfig: ProxyConfig | false = false
): Promise> {
- let options = {}
+ let options: AxiosRequestConfig = {}
if (proxyConfig) {
options = Object.assign(options, {
httpsAgent: proxyAgent(proxyConfig)
@@ -288,7 +288,7 @@ export default class Mastodon implements MegalodonInstance {
* @param params Query parameters
*/
public async get(path: string, params = {}): Promise> {
- let options = {
+ let options: AxiosRequestConfig = {
cancelToken: this.cancelTokenSource.token,
headers: {
Authorization: `Bearer ${this.accessToken}`
@@ -326,7 +326,7 @@ export default class Mastodon implements MegalodonInstance {
* @param params Form data. If you want to post file, please use FormData()
*/
public async put(path: string, params = {}): Promise> {
- let options = {
+ let options: AxiosRequestConfig = {
cancelToken: this.cancelTokenSource.token,
headers: {
Authorization: `Bearer ${this.accessToken}`
@@ -363,7 +363,7 @@ export default class Mastodon implements MegalodonInstance {
* @param params Form data. If you want to post file, please use FormData()
*/
public async patch(path: string, params = {}): Promise> {
- let options = {
+ let options: AxiosRequestConfig = {
cancelToken: this.cancelTokenSource.token,
headers: {
Authorization: `Bearer ${this.accessToken}`
@@ -400,7 +400,7 @@ export default class Mastodon implements MegalodonInstance {
* @param params Form data
*/
public async post(path: string, params = {}): Promise> {
- let options = {
+ let options: AxiosRequestConfig = {
cancelToken: this.cancelTokenSource.token,
headers: {
Authorization: `Bearer ${this.accessToken}`
@@ -428,7 +428,7 @@ export default class Mastodon implements MegalodonInstance {
* @param params Form data
*/
public async del(path: string, params = {}): Promise> {
- let options = {
+ let options: AxiosRequestConfig = {
cancelToken: this.cancelTokenSource.token,
data: params,
headers: {
diff --git a/src/proxy_config.ts b/src/proxy_config.ts
index c80a524..cda4e7d 100644
--- a/src/proxy_config.ts
+++ b/src/proxy_config.ts
@@ -1,4 +1,5 @@
import HttpsProxyAgent from 'https-proxy-agent'
+import SocksProxyAgent from 'socks-proxy-agent'
export type ProxyConfig = {
host: string
@@ -7,15 +8,30 @@ export type ProxyConfig = {
username: string
password: string
}
- protocol: string
+ protocol: 'http' | 'https' | 'socks4' | 'socks4a' | 'socks5' | 'socks5h' | 'socks'
}
-const proxyAgent = (proxyConfig: ProxyConfig): HttpsProxyAgent => {
+class ProxyProtocolError extends Error {}
+
+const proxyAgent = (proxyConfig: ProxyConfig): HttpsProxyAgent | SocksProxyAgent => {
let auth = ''
if (proxyConfig.auth) {
auth = `${proxyConfig.auth.username}:${proxyConfig.auth.password}@`
}
- const agent = new HttpsProxyAgent(`${proxyConfig.protocol}://${auth}${proxyConfig.host}:${proxyConfig.port}`)
- return agent
+ switch (proxyConfig.protocol) {
+ case 'http':
+ case 'https':
+ const httpsAgent = new HttpsProxyAgent(`${proxyConfig.protocol}://${auth}${proxyConfig.host}:${proxyConfig.port}`)
+ return httpsAgent
+ case 'socks4':
+ case 'socks4a':
+ case 'socks5':
+ case 'socks5h':
+ case 'socks':
+ const socksAgent = new SocksProxyAgent(`${proxyConfig.protocol}://${auth}${proxyConfig.host}:${proxyConfig.port}`)
+ return socksAgent
+ default:
+ throw new ProxyProtocolError('protocol is not accepted')
+ }
}
export default proxyAgent
diff --git a/yarn.lock b/yarn.lock
index d2b9226..35bbd93 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -503,6 +503,13 @@ agent-base@^4.3.0:
dependencies:
es6-promisify "^5.0.0"
+agent-base@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
+ integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
+ dependencies:
+ es6-promisify "^5.0.0"
+
ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5:
version "6.10.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52"
@@ -1938,6 +1945,11 @@ invert-kv@^2.0.0:
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
+ip@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
+ integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
+
is-accessor-descriptor@^0.1.6:
version "0.1.6"
resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
@@ -3794,6 +3806,11 @@ slice-ansi@^2.1.0:
astral-regex "^1.0.0"
is-fullwidth-code-point "^2.0.0"
+smart-buffer@4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d"
+ integrity sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==
+
snapdragon-node@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
@@ -3824,6 +3841,21 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
+socks-proxy-agent@h3poteto/node-socks-proxy-agent#master:
+ version "4.0.2"
+ resolved "https://codeload.github.com/h3poteto/node-socks-proxy-agent/tar.gz/5be42d4a3f98c5a156d713ea88a54b825f26d1f3"
+ dependencies:
+ agent-base "~4.2.1"
+ socks "~2.3.2"
+
+socks@~2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.2.tgz#ade388e9e6d87fdb11649c15746c578922a5883e"
+ integrity sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==
+ dependencies:
+ ip "^1.1.5"
+ smart-buffer "4.0.2"
+
source-map-resolve@^0.5.0:
version "0.5.2"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259"