diff options
Diffstat (limited to 'server/helpers')
-rw-r--r-- | server/helpers/requests.ts | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/server/helpers/requests.ts b/server/helpers/requests.ts index 5c6dc5e19..3762e4d3c 100644 --- a/server/helpers/requests.ts +++ b/server/helpers/requests.ts | |||
@@ -1,12 +1,14 @@ | |||
1 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import { createWriteStream } from 'fs-extra' | 2 | import { createWriteStream, remove } from 'fs-extra' |
3 | import * as request from 'request' | 3 | import * as request from 'request' |
4 | import { ACTIVITY_PUB, CONFIG } from '../initializers' | 4 | import { ACTIVITY_PUB, CONFIG } from '../initializers' |
5 | import { processImage } from './image-utils' | 5 | import { processImage } from './image-utils' |
6 | import { join } from 'path' | 6 | import { join } from 'path' |
7 | import { logger } from './logger' | ||
7 | 8 | ||
8 | function doRequest <T> ( | 9 | function doRequest <T> ( |
9 | requestOptions: request.CoreOptions & request.UriOptions & { activityPub?: boolean } | 10 | requestOptions: request.CoreOptions & request.UriOptions & { activityPub?: boolean }, |
11 | bodyKBLimit = 1000 // 1MB | ||
10 | ): Bluebird<{ response: request.RequestResponse, body: T }> { | 12 | ): Bluebird<{ response: request.RequestResponse, body: T }> { |
11 | if (requestOptions.activityPub === true) { | 13 | if (requestOptions.activityPub === true) { |
12 | if (!Array.isArray(requestOptions.headers)) requestOptions.headers = {} | 14 | if (!Array.isArray(requestOptions.headers)) requestOptions.headers = {} |
@@ -15,16 +17,29 @@ function doRequest <T> ( | |||
15 | 17 | ||
16 | return new Bluebird<{ response: request.RequestResponse, body: T }>((res, rej) => { | 18 | return new Bluebird<{ response: request.RequestResponse, body: T }>((res, rej) => { |
17 | request(requestOptions, (err, response, body) => err ? rej(err) : res({ response, body })) | 19 | request(requestOptions, (err, response, body) => err ? rej(err) : res({ response, body })) |
20 | .on('data', onRequestDataLengthCheck(bodyKBLimit)) | ||
18 | }) | 21 | }) |
19 | } | 22 | } |
20 | 23 | ||
21 | function doRequestAndSaveToFile (requestOptions: request.CoreOptions & request.UriOptions, destPath: string) { | 24 | function doRequestAndSaveToFile ( |
25 | requestOptions: request.CoreOptions & request.UriOptions, | ||
26 | destPath: string, | ||
27 | bodyKBLimit = 10000 // 10MB | ||
28 | ) { | ||
22 | return new Bluebird<void>((res, rej) => { | 29 | return new Bluebird<void>((res, rej) => { |
23 | const file = createWriteStream(destPath) | 30 | const file = createWriteStream(destPath) |
24 | file.on('finish', () => res()) | 31 | file.on('finish', () => res()) |
25 | 32 | ||
26 | request(requestOptions) | 33 | request(requestOptions) |
27 | .on('error', err => rej(err)) | 34 | .on('data', onRequestDataLengthCheck(bodyKBLimit)) |
35 | .on('error', err => { | ||
36 | file.close() | ||
37 | |||
38 | remove(destPath) | ||
39 | .catch(err => logger.error('Cannot remove %s after request failure.', destPath, { err })) | ||
40 | |||
41 | return rej(err) | ||
42 | }) | ||
28 | .pipe(file) | 43 | .pipe(file) |
29 | }) | 44 | }) |
30 | } | 45 | } |
@@ -44,3 +59,21 @@ export { | |||
44 | doRequestAndSaveToFile, | 59 | doRequestAndSaveToFile, |
45 | downloadImage | 60 | downloadImage |
46 | } | 61 | } |
62 | |||
63 | // --------------------------------------------------------------------------- | ||
64 | |||
65 | // Thanks to https://github.com/request/request/issues/2470#issuecomment-268929907 <3 | ||
66 | function onRequestDataLengthCheck (bodyKBLimit: number) { | ||
67 | let bufferLength = 0 | ||
68 | const bytesLimit = bodyKBLimit * 1000 | ||
69 | |||
70 | return function (chunk) { | ||
71 | bufferLength += chunk.length | ||
72 | if (bufferLength > bytesLimit) { | ||
73 | this.abort() | ||
74 | |||
75 | const error = new Error(`Response was too large - aborted after ${bytesLimit} bytes.`) | ||
76 | this.emit('error', error) | ||
77 | } | ||
78 | } | ||
79 | } | ||