diff options
Diffstat (limited to 'server/helpers/requests.ts')
-rw-r--r-- | server/helpers/requests.ts | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/server/helpers/requests.ts b/server/helpers/requests.ts index 3fc776f1a..2e30c94a1 100644 --- a/server/helpers/requests.ts +++ b/server/helpers/requests.ts | |||
@@ -1,13 +1,16 @@ | |||
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 } from '../initializers/constants' |
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' | ||
8 | import { CONFIG } from '../initializers/config' | ||
7 | 9 | ||
8 | function doRequest <T> ( | 10 | function doRequest <T> ( |
9 | requestOptions: request.CoreOptions & request.UriOptions & { activityPub?: boolean } | 11 | requestOptions: request.CoreOptions & request.UriOptions & { activityPub?: boolean }, |
10 | ): Bluebird<{ response: request.RequestResponse, body: any }> { | 12 | bodyKBLimit = 1000 // 1MB |
13 | ): Bluebird<{ response: request.RequestResponse, body: T }> { | ||
11 | if (requestOptions.activityPub === true) { | 14 | if (requestOptions.activityPub === true) { |
12 | if (!Array.isArray(requestOptions.headers)) requestOptions.headers = {} | 15 | if (!Array.isArray(requestOptions.headers)) requestOptions.headers = {} |
13 | requestOptions.headers['accept'] = ACTIVITY_PUB.ACCEPT_HEADER | 16 | requestOptions.headers['accept'] = ACTIVITY_PUB.ACCEPT_HEADER |
@@ -15,16 +18,29 @@ function doRequest <T> ( | |||
15 | 18 | ||
16 | return new Bluebird<{ response: request.RequestResponse, body: T }>((res, rej) => { | 19 | return new Bluebird<{ response: request.RequestResponse, body: T }>((res, rej) => { |
17 | request(requestOptions, (err, response, body) => err ? rej(err) : res({ response, body })) | 20 | request(requestOptions, (err, response, body) => err ? rej(err) : res({ response, body })) |
21 | .on('data', onRequestDataLengthCheck(bodyKBLimit)) | ||
18 | }) | 22 | }) |
19 | } | 23 | } |
20 | 24 | ||
21 | function doRequestAndSaveToFile (requestOptions: request.CoreOptions & request.UriOptions, destPath: string) { | 25 | function doRequestAndSaveToFile ( |
26 | requestOptions: request.CoreOptions & request.UriOptions, | ||
27 | destPath: string, | ||
28 | bodyKBLimit = 10000 // 10MB | ||
29 | ) { | ||
22 | return new Bluebird<void>((res, rej) => { | 30 | return new Bluebird<void>((res, rej) => { |
23 | const file = createWriteStream(destPath) | 31 | const file = createWriteStream(destPath) |
24 | file.on('finish', () => res()) | 32 | file.on('finish', () => res()) |
25 | 33 | ||
26 | request(requestOptions) | 34 | request(requestOptions) |
27 | .on('error', err => rej(err)) | 35 | .on('data', onRequestDataLengthCheck(bodyKBLimit)) |
36 | .on('error', err => { | ||
37 | file.close() | ||
38 | |||
39 | remove(destPath) | ||
40 | .catch(err => logger.error('Cannot remove %s after request failure.', destPath, { err })) | ||
41 | |||
42 | return rej(err) | ||
43 | }) | ||
28 | .pipe(file) | 44 | .pipe(file) |
29 | }) | 45 | }) |
30 | } | 46 | } |
@@ -34,7 +50,14 @@ async function downloadImage (url: string, destDir: string, destName: string, si | |||
34 | await doRequestAndSaveToFile({ method: 'GET', uri: url }, tmpPath) | 50 | await doRequestAndSaveToFile({ method: 'GET', uri: url }, tmpPath) |
35 | 51 | ||
36 | const destPath = join(destDir, destName) | 52 | const destPath = join(destDir, destName) |
37 | await processImage({ path: tmpPath }, destPath, size) | 53 | |
54 | try { | ||
55 | await processImage(tmpPath, destPath, size) | ||
56 | } catch (err) { | ||
57 | await remove(tmpPath) | ||
58 | |||
59 | throw err | ||
60 | } | ||
38 | } | 61 | } |
39 | 62 | ||
40 | // --------------------------------------------------------------------------- | 63 | // --------------------------------------------------------------------------- |
@@ -44,3 +67,21 @@ export { | |||
44 | doRequestAndSaveToFile, | 67 | doRequestAndSaveToFile, |
45 | downloadImage | 68 | downloadImage |
46 | } | 69 | } |
70 | |||
71 | // --------------------------------------------------------------------------- | ||
72 | |||
73 | // Thanks to https://github.com/request/request/issues/2470#issuecomment-268929907 <3 | ||
74 | function onRequestDataLengthCheck (bodyKBLimit: number) { | ||
75 | let bufferLength = 0 | ||
76 | const bytesLimit = bodyKBLimit * 1000 | ||
77 | |||
78 | return function (chunk) { | ||
79 | bufferLength += chunk.length | ||
80 | if (bufferLength > bytesLimit) { | ||
81 | this.abort() | ||
82 | |||
83 | const error = new Error(`Response was too large - aborted after ${bytesLimit} bytes.`) | ||
84 | this.emit('error', error) | ||
85 | } | ||
86 | } | ||
87 | } | ||