Skip to content

Commit 011f952

Browse files
authored
Merge pull request #12 from tekliner/master
Add proxy_server arg support
2 parents 45d050d + 9c6d794 commit 011f952

3 files changed

Lines changed: 85 additions & 52 deletions

File tree

API/WS/Screenshot.js

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,14 @@ exports.message = async (event, context, callback) => {
3838
return;
3939
}
4040

41-
41+
4242
var resp = null;
4343

4444
if ( obj.cmd == "screenshot" ){
4545

4646
var sharedmem = context.sharedmem;
4747
var beginPipeline = process.hrtime();
48+
var proxy_server = process.env.PROXY_SERVER
4849

4950
while ( sharedmem.getInteger("nbPuppeteerProcess") >= maxConcurrency ){
5051
await tools.sleep(20);
@@ -63,12 +64,20 @@ exports.message = async (event, context, callback) => {
6364
//var screenshotResult = await tools.screnshotForUrl(url, true);
6465
var screenshotResult = null;
6566
try{
66-
screenshotResult = await tools.screnshotForUrlTab(url, obj.isFullPage, obj.resX, obj.resY, obj.outFormat, obj.waitTime);
67+
screenshotResult = await tools.screnshotForUrlTab(
68+
url,
69+
obj.isFullPage,
70+
obj.resX,
71+
obj.resY,
72+
obj.outFormat,
73+
obj.waitTime,
74+
proxy_server,
75+
);
6776
}
6877
catch(ex){
6978
//do nothing
7079
}
71-
80+
7281

7382
sharedmem.incInteger("nbPuppeteerProcess", -1);
7483
sharedmem.incInteger("nbScreenshots", 1);
@@ -79,7 +88,7 @@ exports.message = async (event, context, callback) => {
7988
/*
8089
callback(null, {
8190
status: 200,
82-
content: screenshotResult.data,
91+
content: screenshotResult.data,
8392
headers:{
8493
"execTime": durationMS.toFixed(2) + "ms",
8594
"nbPuppeteerProcess": sharedmem.getInteger("nbPuppeteerProcess"),
@@ -101,20 +110,20 @@ exports.message = async (event, context, callback) => {
101110

102111
if ( screenshotResult == null ){
103112
resp = {
104-
"cmd": "responseScreenshot",
105-
"data": "",
113+
"cmd": "responseScreenshot",
114+
"data": "",
106115
"isEmptyResult": true,
107116
"execTime": durationMS.toFixed(2) + "ms",
108117
"totalScreenshots": sharedmem.getInteger("nbScreenshots"),
109118
"originalTS": obj.originalTS,
110119
"outFormat": obj.outFormat,
111120
"Content-Type": "application/json"
112121
};
113-
}
122+
}
114123
else{
115124
resp = {
116-
"cmd": "responseScreenshot",
117-
"data": b64Data,
125+
"cmd": "responseScreenshot",
126+
"data": b64Data,
118127
"details": screenshotResult.details,
119128
"isEmptyResult": false,
120129
"execTime": durationMS.toFixed(2) + "ms",
@@ -124,36 +133,36 @@ exports.message = async (event, context, callback) => {
124133
"Content-Type": screenshotResult.mimeType
125134
};
126135
}
127-
128-
136+
137+
129138
}
130139
else if ( obj.cmd == "CleanMemory" ){
131140
await tools.CleanMemory();
132141
resp = {
133-
"cmd": "responseCleanMemory",
142+
"cmd": "responseCleanMemory",
134143
"originalTS": obj.originalTS,
135144
"status": "OK"
136145
};
137146
}
138-
147+
139148
}
140149
catch(ex){
141150
console.log(ex);
142151
console.log("Crash in Message handling");
143152
}
144153

145-
154+
146155

147156
//return the response to the websocket client (caller)
148157
if ( resp != null ){
149158
callback(null, JSON.stringify(resp));
150159
}
151-
160+
152161
};
153162

154163
exports.close = async (event, context, callback) => {
155-
156-
//here your response will be discarded because the websocket
164+
165+
//here your response will be discarded because the websocket
157166
//is already closed at clientside when we receive this event
158167
callback(null, null);
159168
};

API/shared.js

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const puppeteer = require('puppeteer');
22

33
var browser = null;
4-
module.exports.screnshotForUrlTab = async function (url, isfullPage, resX, resY, outFormat, waitTime) {
4+
module.exports.screnshotForUrlTab = async function (url, isfullPage, resX, resY, outFormat, waitTime, proxy_server) {
55
return new Promise(async function (resolve, reject) {
66

77
try{
@@ -18,10 +18,25 @@ module.exports.screnshotForUrlTab = async function (url, isfullPage, resX, resY,
1818
var buffer = null;
1919
try{
2020

21+
var args = [
22+
'--no-sandbox',
23+
'--font-render-hinting=none',
24+
'--force-color-profile=srgb'
25+
]
26+
27+
if (proxy_server != null){
28+
args.push(`--proxy-server=${proxy_server}`)
29+
args.push('--host-resolver-rules="MAP * ~NOTFOUND , EXCLUDE proxyhost"',)
30+
}
2131
if ( browser == null){
22-
browser = await puppeteer.launch({headless: true, args: ['--no-sandbox', '--font-render-hinting=none', '--force-color-profile=srgb']});
32+
browser = await puppeteer.launch(
33+
{
34+
headless: true,
35+
args: args
36+
}
37+
);
2338
}
24-
39+
2540
//const browser = await puppeteer.launch({args: ['--no-sandbox']});
2641
const page = await browser.newPage();
2742
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36");
@@ -38,13 +53,13 @@ module.exports.screnshotForUrlTab = async function (url, isfullPage, resX, resY,
3853
if (isfullPage){
3954
await autoScroll(page);
4055
}
41-
56+
4257
//wait for the page to be fully loaded - max 1000ms wait
4358
try{
4459
await page.waitForNavigation({waitUntil: 'networkidle2', timeout: waitTime});
4560
} catch(ex){
4661
}
47-
62+
4863
var finalType = "jpg";
4964
var finalMime = "image/jpeg";
5065

@@ -61,8 +76,8 @@ module.exports.screnshotForUrlTab = async function (url, isfullPage, resX, resY,
6176
finalMime = "application/pdf";
6277
}
6378

64-
var optionsPup = {
65-
type: finalType,
79+
var optionsPup = {
80+
type: finalType,
6681
encoding: 'binary',
6782
fullPage: isfullPage
6883
};
@@ -77,18 +92,18 @@ module.exports.screnshotForUrlTab = async function (url, isfullPage, resX, resY,
7792
else{
7893
buffer = await page.pdf({printBackground: true, scale: 1, format: 'A4'});
7994
}
80-
95+
8196
//await browser.close();
8297
await page.close();
8398

84-
let mimeType = finalMime;
99+
let mimeType = finalMime;
85100
var resp = {
86101
mimeType: mimeType,
87102
data: buffer
88103
};
89104

90105
resolve(resp);
91-
106+
92107
}
93108
catch(ex){
94109
console.log("Error while taking screenshot: " + ex.message);
@@ -144,11 +159,11 @@ module.exports.screnshotForUrl = async function (url, isfullPage, resX, resY, ou
144159

145160
var errorContent = "";
146161
await page.goto(url).catch(e => errorContent = e);
147-
162+
148163
//display error in the image
149164
if ( errorContent != "" ){
150165
page.setContent("<pre>" + errorContent.stack + "</pre>");
151-
}
166+
}
152167

153168
await page.setViewport({
154169
width: parseInt(resX),
@@ -166,7 +181,7 @@ module.exports.screnshotForUrl = async function (url, isfullPage, resX, resY, ou
166181
} catch(ex){
167182

168183
}
169-
184+
170185
var finalType = "jpg";
171186
var finalMime = "image/jpeg";
172187

@@ -183,22 +198,22 @@ module.exports.screnshotForUrl = async function (url, isfullPage, resX, resY, ou
183198
finalMime = "application/pdf";
184199
}
185200

186-
buffer = await page.screenshot({
187-
type: finalType,
188-
quality: 84,
201+
buffer = await page.screenshot({
202+
type: finalType,
203+
quality: 84,
189204
encoding: 'binary',
190205
fullPage: isfullPage
191206
});
192207
await browser.close();
193208

194-
let mimeType = finalMime;
209+
let mimeType = finalMime;
195210
var resp = {
196211
mimeType: mimeType,
197212
data: buffer
198213
};
199214

200215
resolve(resp);
201-
216+
202217
}
203218
catch(ex){
204219
console.log("Error while taking screenshot: " + ex.message);
@@ -243,4 +258,4 @@ module.exports.sleep = function (ms) {
243258
return new Promise((resolve) => {
244259
setTimeout(resolve, ms);
245260
});
246-
}
261+
}

README.md

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ DEMO: https://backup15.terasp.net/
99

1010
# Quickstart with Docker
1111

12-
Run once:
12+
Run once:
1313

1414
docker pull elestio/ws-screenshot.slim
1515
docker run -p 3000:3000 -it elestio/ws-screenshot.slim
@@ -39,7 +39,7 @@ Clone this repo then install NPM dependencies for ws-screenshot:
3939
npm install
4040

4141
## Install required dependencies for chrome:
42-
42+
4343
./installPuppeteerNativeDeps.sh
4444

4545

@@ -50,7 +50,7 @@ Clone this repo then install NPM dependencies for ws-screenshot:
5050
## Run directly
5151

5252
Finally we can start WS-SCREENSHOT Server one-time:
53-
53+
5454
./run.sh
5555

5656
or run as a service with pm2
@@ -74,26 +74,35 @@ Run with helm
7474

7575
helm upgrade --install ws-screenshot --namespace ws-screenshot helm/
7676

77+
## Run with proxy
78+
Add `PROXY_SERVER` env variable:
79+
80+
docker run --rm -p 3000:3000 --env PROXY_SERVER=socks5://host:port -it ws-screenshot
81+
82+
> NOTE: Chromium ignores username and password in `--proxy-server` arg
83+
>
84+
> https://bugs.chromium.org/p/chromium/issues/detail?id=615947
85+
7786
&nbsp;
7887
# Usage
7988

8089
## REST API
8190

8291
Make a GET request (or open the url in your browser):
83-
92+
8493
/api/screenshot?resX=1280&resY=900&outFormat=jpg&isFullPage=false&url=https://vms2.terasp.net
8594

8695
## Websocket API
8796

8897
```js
89-
var event = {
90-
cmd: "screenshot",
91-
url: url,
92-
originalTS: (+new Date()),
93-
resX: resX,
94-
resY: resY,
95-
outFormat: outFormat,
96-
isFullPage: isFullPage
98+
var event = {
99+
cmd: "screenshot",
100+
url: url,
101+
originalTS: (+new Date()),
102+
resX: resX,
103+
resY: resY,
104+
outFormat: outFormat,
105+
isFullPage: isFullPage
97106
};
98107
```
99108

@@ -122,10 +131,10 @@ To call the REST API with an ApiKey:
122131
To call the Websocket API with an ApiKey:
123132

124133
```js
125-
var event = {
126-
cmd: "screenshot",
127-
url: url,
128-
originalTS: (+new Date()),
134+
var event = {
135+
cmd: "screenshot",
136+
url: url,
137+
originalTS: (+new Date()),
129138
apiKey: "XXXXXXXXXXXXX"
130139
};
131140
```

0 commit comments

Comments
 (0)