diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/helpers/proxy.ts | 14 | ||||
-rw-r--r-- | server/helpers/requests.ts | 32 | ||||
-rw-r--r-- | server/tests/api/server/index.ts | 1 | ||||
-rw-r--r-- | server/tests/api/server/proxy.ts | 72 |
4 files changed, 117 insertions, 2 deletions
diff --git a/server/helpers/proxy.ts b/server/helpers/proxy.ts new file mode 100644 index 000000000..8b82ccae0 --- /dev/null +++ b/server/helpers/proxy.ts | |||
@@ -0,0 +1,14 @@ | |||
1 | function getProxy () { | ||
2 | return process.env.HTTPS_PROXY || | ||
3 | process.env.HTTP_PROXY || | ||
4 | undefined | ||
5 | } | ||
6 | |||
7 | function isProxyEnabled () { | ||
8 | return !!getProxy() | ||
9 | } | ||
10 | |||
11 | export { | ||
12 | getProxy, | ||
13 | isProxyEnabled | ||
14 | } | ||
diff --git a/server/helpers/requests.ts b/server/helpers/requests.ts index 36e69458e..e09e23086 100644 --- a/server/helpers/requests.ts +++ b/server/helpers/requests.ts | |||
@@ -1,19 +1,21 @@ | |||
1 | import { createWriteStream, remove } from 'fs-extra' | 1 | import { createWriteStream, remove } from 'fs-extra' |
2 | import got, { CancelableRequest, Options as GotOptions, RequestError } from 'got' | 2 | import got, { CancelableRequest, Options as GotOptions, RequestError } from 'got' |
3 | import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent' | ||
3 | import { join } from 'path' | 4 | import { join } from 'path' |
4 | import { CONFIG } from '../initializers/config' | 5 | import { CONFIG } from '../initializers/config' |
5 | import { ACTIVITY_PUB, PEERTUBE_VERSION, REQUEST_TIMEOUT, WEBSERVER } from '../initializers/constants' | 6 | import { ACTIVITY_PUB, PEERTUBE_VERSION, REQUEST_TIMEOUT, WEBSERVER } from '../initializers/constants' |
6 | import { pipelinePromise } from './core-utils' | 7 | import { pipelinePromise } from './core-utils' |
7 | import { processImage } from './image-utils' | 8 | import { processImage } from './image-utils' |
8 | import { logger } from './logger' | 9 | import { logger } from './logger' |
10 | import { getProxy, isProxyEnabled } from './proxy' | ||
11 | |||
12 | const httpSignature = require('http-signature') | ||
9 | 13 | ||
10 | export interface PeerTubeRequestError extends Error { | 14 | export interface PeerTubeRequestError extends Error { |
11 | statusCode?: number | 15 | statusCode?: number |
12 | responseBody?: any | 16 | responseBody?: any |
13 | } | 17 | } |
14 | 18 | ||
15 | const httpSignature = require('http-signature') | ||
16 | |||
17 | type PeerTubeRequestOptions = { | 19 | type PeerTubeRequestOptions = { |
18 | activityPub?: boolean | 20 | activityPub?: boolean |
19 | bodyKBLimit?: number // 1MB | 21 | bodyKBLimit?: number // 1MB |
@@ -29,6 +31,8 @@ type PeerTubeRequestOptions = { | |||
29 | } & Pick<GotOptions, 'headers' | 'json' | 'method' | 'searchParams'> | 31 | } & Pick<GotOptions, 'headers' | 'json' | 'method' | 'searchParams'> |
30 | 32 | ||
31 | const peertubeGot = got.extend({ | 33 | const peertubeGot = got.extend({ |
34 | ...getAgent(), | ||
35 | |||
32 | headers: { | 36 | headers: { |
33 | 'user-agent': getUserAgent() | 37 | 'user-agent': getUserAgent() |
34 | }, | 38 | }, |
@@ -153,6 +157,30 @@ async function downloadImage (url: string, destDir: string, destName: string, si | |||
153 | } | 157 | } |
154 | } | 158 | } |
155 | 159 | ||
160 | function getAgent () { | ||
161 | if (!isProxyEnabled()) return {} | ||
162 | |||
163 | const proxy = getProxy() | ||
164 | |||
165 | logger.info('Using proxy %s.', proxy) | ||
166 | |||
167 | const proxyAgentOptions = { | ||
168 | keepAlive: true, | ||
169 | keepAliveMsecs: 1000, | ||
170 | maxSockets: 256, | ||
171 | maxFreeSockets: 256, | ||
172 | scheduling: 'lifo' as 'lifo', | ||
173 | proxy | ||
174 | } | ||
175 | |||
176 | return { | ||
177 | agent: { | ||
178 | http: new HttpProxyAgent(proxyAgentOptions), | ||
179 | https: new HttpsProxyAgent(proxyAgentOptions) | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
156 | function getUserAgent () { | 184 | function getUserAgent () { |
157 | return `PeerTube/${PEERTUBE_VERSION} (+${WEBSERVER.URL})` | 185 | return `PeerTube/${PEERTUBE_VERSION} (+${WEBSERVER.URL})` |
158 | } | 186 | } |
diff --git a/server/tests/api/server/index.ts b/server/tests/api/server/index.ts index 56e6eb5da..b16a22ee7 100644 --- a/server/tests/api/server/index.ts +++ b/server/tests/api/server/index.ts | |||
@@ -15,3 +15,4 @@ import './stats' | |||
15 | import './tracker' | 15 | import './tracker' |
16 | import './no-client' | 16 | import './no-client' |
17 | import './plugins' | 17 | import './plugins' |
18 | import './proxy' | ||
diff --git a/server/tests/api/server/proxy.ts b/server/tests/api/server/proxy.ts new file mode 100644 index 000000000..d5042ef27 --- /dev/null +++ b/server/tests/api/server/proxy.ts | |||
@@ -0,0 +1,72 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import * as chai from 'chai' | ||
5 | import { cleanupTests, createMultipleServers, doubleFollow, PeerTubeServer, setAccessTokensToServers, waitJobs } from '@shared/extra-utils' | ||
6 | import { MockProxy } from '@shared/extra-utils/mock-servers/mock-proxy' | ||
7 | |||
8 | const expect = chai.expect | ||
9 | |||
10 | describe('Test proxy', function () { | ||
11 | let servers: PeerTubeServer[] = [] | ||
12 | let proxy: MockProxy | ||
13 | |||
14 | const goodEnv = { HTTP_PROXY: '' } | ||
15 | const badEnv = { HTTP_PROXY: 'http://localhost:9000' } | ||
16 | |||
17 | before(async function () { | ||
18 | this.timeout(120000) | ||
19 | |||
20 | proxy = new MockProxy() | ||
21 | |||
22 | const proxyPort = await proxy.initialize() | ||
23 | servers = await createMultipleServers(2) | ||
24 | |||
25 | goodEnv.HTTP_PROXY = 'http://localhost:' + proxyPort | ||
26 | |||
27 | await setAccessTokensToServers(servers) | ||
28 | await doubleFollow(servers[0], servers[1]) | ||
29 | }) | ||
30 | |||
31 | it('Should succeed federation with the appropriate proxy config', async function () { | ||
32 | await servers[0].kill() | ||
33 | await servers[0].run({}, { env: goodEnv }) | ||
34 | |||
35 | await servers[0].videos.quickUpload({ name: 'video 1' }) | ||
36 | |||
37 | await waitJobs(servers) | ||
38 | |||
39 | for (const server of servers) { | ||
40 | const { total, data } = await server.videos.list() | ||
41 | expect(total).to.equal(1) | ||
42 | expect(data).to.have.lengthOf(1) | ||
43 | } | ||
44 | }) | ||
45 | |||
46 | it('Should fail federation with a wrong proxy config', async function () { | ||
47 | await servers[0].kill() | ||
48 | await servers[0].run({}, { env: badEnv }) | ||
49 | |||
50 | await servers[0].videos.quickUpload({ name: 'video 2' }) | ||
51 | |||
52 | await waitJobs(servers) | ||
53 | |||
54 | { | ||
55 | const { total, data } = await servers[0].videos.list() | ||
56 | expect(total).to.equal(2) | ||
57 | expect(data).to.have.lengthOf(2) | ||
58 | } | ||
59 | |||
60 | { | ||
61 | const { total, data } = await servers[1].videos.list() | ||
62 | expect(total).to.equal(1) | ||
63 | expect(data).to.have.lengthOf(1) | ||
64 | } | ||
65 | }) | ||
66 | |||
67 | after(async function () { | ||
68 | proxy.terminate() | ||
69 | |||
70 | await cleanupTests(servers) | ||
71 | }) | ||
72 | }) | ||