releasebird-javascript-sdk 1.0.58 ā 1.0.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +9 -1
- package/NGINX_CONFIG_GUIDE.md +204 -0
- package/backend-image-service/image-service/.ebextensions/04_nginx.config +12 -0
- package/backend-image-service/image-service/.platform/nginx/conf.d/client_max_body_size.conf +1 -0
- package/backend-image-service/image-service/Dockerfile +3 -0
- package/backend-image-service/image-service/server.js +41 -7
- package/backend-image-service/test-compression.js +120 -0
- package/backend-image-service/test-deployed-service.js +126 -0
- package/backend-image-service/test-full-flow.js +226 -0
- package/backend-image-service/test-java-backend.js +72 -0
- package/backend-image-service/test-svg-debug.html +28 -0
- package/build/index.js +1 -1
- package/package.json +1 -1
- package/published/1.0./index.js +1 -0
- package/published/1.0.59/index.js +1 -0
- package/published/1.0.60/index.js +1 -0
- package/published/1.0.61/index.js +1 -0
- package/published/latest/index.js +1 -1
- package/src/RbirdScreenshotManager.js +99 -172
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const zlib = require('zlib');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
|
|
6
|
+
const JAVA_BACKEND_URL = 'https://api.releasebird.com/papi/images/screenshot/render';
|
|
7
|
+
|
|
8
|
+
// Larger, more realistic HTML
|
|
9
|
+
const testHtml = `
|
|
10
|
+
<!DOCTYPE html>
|
|
11
|
+
<html>
|
|
12
|
+
<head>
|
|
13
|
+
<meta charset="UTF-8">
|
|
14
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
15
|
+
<style>
|
|
16
|
+
* {
|
|
17
|
+
margin: 0;
|
|
18
|
+
padding: 0;
|
|
19
|
+
box-sizing: border-box;
|
|
20
|
+
}
|
|
21
|
+
body {
|
|
22
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
23
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
24
|
+
min-height: 100vh;
|
|
25
|
+
padding: 40px;
|
|
26
|
+
}
|
|
27
|
+
.container {
|
|
28
|
+
max-width: 1200px;
|
|
29
|
+
margin: 0 auto;
|
|
30
|
+
background: white;
|
|
31
|
+
border-radius: 20px;
|
|
32
|
+
padding: 40px;
|
|
33
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
|
34
|
+
}
|
|
35
|
+
h1 {
|
|
36
|
+
color: #667eea;
|
|
37
|
+
font-size: 48px;
|
|
38
|
+
margin-bottom: 20px;
|
|
39
|
+
text-align: center;
|
|
40
|
+
}
|
|
41
|
+
.success-badge {
|
|
42
|
+
background: #10b981;
|
|
43
|
+
color: white;
|
|
44
|
+
padding: 10px 20px;
|
|
45
|
+
border-radius: 50px;
|
|
46
|
+
display: inline-block;
|
|
47
|
+
margin: 20px 0;
|
|
48
|
+
font-weight: 600;
|
|
49
|
+
}
|
|
50
|
+
.info-grid {
|
|
51
|
+
display: grid;
|
|
52
|
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
53
|
+
gap: 20px;
|
|
54
|
+
margin: 30px 0;
|
|
55
|
+
}
|
|
56
|
+
.info-card {
|
|
57
|
+
background: #f3f4f6;
|
|
58
|
+
padding: 20px;
|
|
59
|
+
border-radius: 10px;
|
|
60
|
+
border-left: 4px solid #667eea;
|
|
61
|
+
}
|
|
62
|
+
.info-card h3 {
|
|
63
|
+
color: #374151;
|
|
64
|
+
margin-bottom: 10px;
|
|
65
|
+
}
|
|
66
|
+
.info-card p {
|
|
67
|
+
color: #6b7280;
|
|
68
|
+
line-height: 1.6;
|
|
69
|
+
}
|
|
70
|
+
.stats {
|
|
71
|
+
display: flex;
|
|
72
|
+
justify-content: space-around;
|
|
73
|
+
margin: 40px 0;
|
|
74
|
+
}
|
|
75
|
+
.stat {
|
|
76
|
+
text-align: center;
|
|
77
|
+
}
|
|
78
|
+
.stat-value {
|
|
79
|
+
font-size: 36px;
|
|
80
|
+
font-weight: bold;
|
|
81
|
+
color: #667eea;
|
|
82
|
+
}
|
|
83
|
+
.stat-label {
|
|
84
|
+
color: #6b7280;
|
|
85
|
+
margin-top: 5px;
|
|
86
|
+
}
|
|
87
|
+
</style>
|
|
88
|
+
</head>
|
|
89
|
+
<body>
|
|
90
|
+
<div class="container">
|
|
91
|
+
<h1>š Full Compression Test Successful!</h1>
|
|
92
|
+
|
|
93
|
+
<div style="text-align: center;">
|
|
94
|
+
<span class="success-badge">ā
Gzip Compression Working</span>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<div class="stats">
|
|
98
|
+
<div class="stat">
|
|
99
|
+
<div class="stat-value">57%</div>
|
|
100
|
+
<div class="stat-label">Compression Ratio</div>
|
|
101
|
+
</div>
|
|
102
|
+
<div class="stat">
|
|
103
|
+
<div class="stat-value">50MB</div>
|
|
104
|
+
<div class="stat-label">Max Payload Size</div>
|
|
105
|
+
</div>
|
|
106
|
+
<div class="stat">
|
|
107
|
+
<div class="stat-value">3</div>
|
|
108
|
+
<div class="stat-label">Services Updated</div>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div class="info-grid">
|
|
113
|
+
<div class="info-card">
|
|
114
|
+
<h3>šØ JavaScript SDK</h3>
|
|
115
|
+
<p>Automatically compresses HTML payloads using gzip before sending to backend.</p>
|
|
116
|
+
</div>
|
|
117
|
+
<div class="info-card">
|
|
118
|
+
<h3>ā Java Backend</h3>
|
|
119
|
+
<p>Decompresses gzip data and forwards to image service for rendering.</p>
|
|
120
|
+
</div>
|
|
121
|
+
<div class="info-card">
|
|
122
|
+
<h3>š Image Service</h3>
|
|
123
|
+
<p>Renders HTML to high-quality images using Puppeteer in Docker.</p>
|
|
124
|
+
</div>
|
|
125
|
+
<div class="info-card">
|
|
126
|
+
<h3>š§ Configuration</h3>
|
|
127
|
+
<p>Nginx configured with 50MB client_max_body_size for large payloads.</p>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<div style="margin-top: 40px; padding: 20px; background: #fef3c7; border-radius: 10px; border-left: 4px solid #f59e0b;">
|
|
132
|
+
<h3 style="color: #92400e; margin-bottom: 10px;">⨠Benefits</h3>
|
|
133
|
+
<ul style="color: #78350f; line-height: 2;">
|
|
134
|
+
<li>70-90% reduction in payload size</li>
|
|
135
|
+
<li>Faster network transmission</li>
|
|
136
|
+
<li>Reduced bandwidth costs</li>
|
|
137
|
+
<li>Better performance for large HTML documents</li>
|
|
138
|
+
<li>Backward compatible with uncompressed requests</li>
|
|
139
|
+
</ul>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
</body>
|
|
143
|
+
</html>
|
|
144
|
+
`;
|
|
145
|
+
|
|
146
|
+
console.log('=== Full Flow Compression Test ===\n');
|
|
147
|
+
console.log(`Backend URL: ${JAVA_BACKEND_URL}`);
|
|
148
|
+
console.log(`Original HTML: ${testHtml.length} bytes`);
|
|
149
|
+
console.log(`HTML contains: ${testHtml.split('\n').length} lines\n`);
|
|
150
|
+
|
|
151
|
+
// Compress HTML
|
|
152
|
+
const compressed = zlib.gzipSync(Buffer.from(testHtml, 'utf-8'));
|
|
153
|
+
const base64Compressed = compressed.toString('base64');
|
|
154
|
+
|
|
155
|
+
console.log(`Compressed: ${compressed.length} bytes`);
|
|
156
|
+
console.log(`Base64: ${base64Compressed.length} bytes`);
|
|
157
|
+
console.log(`Compression ratio: ${Math.round(compressed.length / testHtml.length * 100)}%`);
|
|
158
|
+
console.log(`Savings: ${testHtml.length - compressed.length} bytes (${Math.round((1 - compressed.length / testHtml.length) * 100)}%)\n`);
|
|
159
|
+
|
|
160
|
+
const requestData = {
|
|
161
|
+
htmlCompressed: base64Compressed,
|
|
162
|
+
compressed: true,
|
|
163
|
+
width: 1280,
|
|
164
|
+
height: 900,
|
|
165
|
+
url: 'http://test.compression.local'
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
const requestBody = JSON.stringify(requestData);
|
|
169
|
+
console.log(`Final request payload: ${requestBody.length} bytes\n`);
|
|
170
|
+
|
|
171
|
+
const url = new URL(JAVA_BACKEND_URL);
|
|
172
|
+
const options = {
|
|
173
|
+
hostname: url.hostname,
|
|
174
|
+
port: url.port || 443,
|
|
175
|
+
path: url.pathname,
|
|
176
|
+
method: 'POST',
|
|
177
|
+
headers: {
|
|
178
|
+
'Content-Type': 'application/json',
|
|
179
|
+
'Content-Length': Buffer.byteLength(requestBody)
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
console.log('Sending request through full pipeline:');
|
|
184
|
+
console.log(' 1. JavaScript SDK ā Java Backend (compressed)');
|
|
185
|
+
console.log(' 2. Java Backend ā Image Service (decompressed)');
|
|
186
|
+
console.log(' 3. Image Service ā Screenshot (rendered)\n');
|
|
187
|
+
|
|
188
|
+
const startTime = Date.now();
|
|
189
|
+
|
|
190
|
+
const req = https.request(options, (res) => {
|
|
191
|
+
const duration = Date.now() - startTime;
|
|
192
|
+
|
|
193
|
+
console.log(`Status: ${res.statusCode} ${res.statusMessage}`);
|
|
194
|
+
console.log(`Duration: ${duration}ms\n`);
|
|
195
|
+
|
|
196
|
+
let data = '';
|
|
197
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
198
|
+
res.on('end', () => {
|
|
199
|
+
try {
|
|
200
|
+
const response = JSON.parse(data);
|
|
201
|
+
if (response.screenshot) {
|
|
202
|
+
console.log('ā
SUCCESS - Full pipeline working!');
|
|
203
|
+
console.log(`Screenshot data URL: ${response.screenshot.length} characters`);
|
|
204
|
+
console.log(`\n=== Summary ===`);
|
|
205
|
+
console.log(`ā Compression: ${Math.round((1 - compressed.length / testHtml.length) * 100)}% size reduction`);
|
|
206
|
+
console.log(`ā Transfer: ${requestBody.length} bytes sent`);
|
|
207
|
+
console.log(`ā Response: ${response.screenshot.length} chars received`);
|
|
208
|
+
console.log(`ā Duration: ${duration}ms`);
|
|
209
|
+
console.log(`\nš All systems operational!`);
|
|
210
|
+
} else {
|
|
211
|
+
console.error('ā No screenshot in response');
|
|
212
|
+
console.error(JSON.stringify(response, null, 2).substring(0, 500));
|
|
213
|
+
}
|
|
214
|
+
} catch (e) {
|
|
215
|
+
console.error('ā Parse error:', e.message);
|
|
216
|
+
console.error('Response:', data.substring(0, 500));
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
req.on('error', (error) => {
|
|
222
|
+
console.error('ā Request failed:', error.message);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
req.write(requestBody);
|
|
226
|
+
req.end();
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const zlib = require('zlib');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
|
|
6
|
+
const JAVA_BACKEND_URL = 'https://api.releasebird.com/papi/images/screenshot/render';
|
|
7
|
+
|
|
8
|
+
const testHtml = `<!DOCTYPE html><html><body><h1>Test Java Backend</h1></body></html>`;
|
|
9
|
+
|
|
10
|
+
console.log('=== Testing Java Backend ===\n');
|
|
11
|
+
console.log(`Backend URL: ${JAVA_BACKEND_URL}`);
|
|
12
|
+
console.log(`Original HTML: ${testHtml.length} bytes\n`);
|
|
13
|
+
|
|
14
|
+
// Compress HTML
|
|
15
|
+
const compressed = zlib.gzipSync(Buffer.from(testHtml, 'utf-8'));
|
|
16
|
+
const base64Compressed = compressed.toString('base64');
|
|
17
|
+
|
|
18
|
+
console.log(`Compressed: ${compressed.length} bytes`);
|
|
19
|
+
console.log(`Base64: ${base64Compressed.length} bytes\n`);
|
|
20
|
+
|
|
21
|
+
const requestData = {
|
|
22
|
+
htmlCompressed: base64Compressed,
|
|
23
|
+
compressed: true,
|
|
24
|
+
width: 800,
|
|
25
|
+
height: 600,
|
|
26
|
+
url: 'http://test.local'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const requestBody = JSON.stringify(requestData);
|
|
30
|
+
console.log(`Request payload: ${requestBody.length} bytes\n`);
|
|
31
|
+
|
|
32
|
+
const url = new URL(JAVA_BACKEND_URL);
|
|
33
|
+
const options = {
|
|
34
|
+
hostname: url.hostname,
|
|
35
|
+
port: url.port || 443,
|
|
36
|
+
path: url.pathname,
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
'Content-Length': Buffer.byteLength(requestBody)
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
console.log('Sending compressed request to Java backend...\n');
|
|
45
|
+
|
|
46
|
+
const req = https.request(options, (res) => {
|
|
47
|
+
console.log(`Status: ${res.statusCode} ${res.statusMessage}\n`);
|
|
48
|
+
|
|
49
|
+
let data = '';
|
|
50
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
51
|
+
res.on('end', () => {
|
|
52
|
+
try {
|
|
53
|
+
const response = JSON.parse(data);
|
|
54
|
+
if (response.screenshot) {
|
|
55
|
+
console.log('ā
Screenshot generated!');
|
|
56
|
+
console.log(`Screenshot length: ${response.screenshot.length} chars`);
|
|
57
|
+
} else {
|
|
58
|
+
console.error('ā Response:', JSON.stringify(response, null, 2).substring(0, 500));
|
|
59
|
+
}
|
|
60
|
+
} catch (e) {
|
|
61
|
+
console.error('ā Parse error:', e.message);
|
|
62
|
+
console.error('Response:', data.substring(0, 500));
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
req.on('error', (error) => {
|
|
68
|
+
console.error('ā Request failed:', error.message);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
req.write(requestBody);
|
|
72
|
+
req.end();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<style>
|
|
6
|
+
body { padding: 20px; font-family: Arial; }
|
|
7
|
+
.test-img { border: 2px solid red; margin: 10px; }
|
|
8
|
+
svg { border: 2px solid blue; margin: 10px; }
|
|
9
|
+
</style>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<h1>SVG and Image Test</h1>
|
|
13
|
+
|
|
14
|
+
<!-- Inline SVG -->
|
|
15
|
+
<svg width="200" height="200" style="background: #f0f0f0;">
|
|
16
|
+
<circle cx="100" cy="100" r="50" fill="red"/>
|
|
17
|
+
<rect x="50" y="50" width="100" height="100" fill="none" stroke="blue" stroke-width="2"/>
|
|
18
|
+
<line x1="0" y1="0" x2="200" y2="200" stroke="green" stroke-width="2"/>
|
|
19
|
+
</svg>
|
|
20
|
+
|
|
21
|
+
<!-- Data URL Image -->
|
|
22
|
+
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100'%3E%3Ccircle cx='50' cy='50' r='40' fill='purple'/%3E%3C/svg%3E"
|
|
23
|
+
alt="Data URL SVG" class="test-img">
|
|
24
|
+
|
|
25
|
+
<!-- External Image -->
|
|
26
|
+
<img src="https://via.placeholder.com/150" alt="External Image" class="test-img">
|
|
27
|
+
</body>
|
|
28
|
+
</html>
|