Skip to content

Commit 681af5d

Browse files
feat: added image endpoint (#1)
Co-authored-by: CodiumAI-Agent <137281646+CodiumAI-Agent@users.noreply.github.com>
1 parent 077666d commit 681af5d

File tree

2 files changed

+54
-15
lines changed

2 files changed

+54
-15
lines changed

src/app.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import compression from 'compression';
22
import express from 'express';
33
import morgan from 'morgan';
44
import { getBrowser } from './browser.js';
5-
import render from './render.js';
5+
import { renderPdf, renderImage } from './render.js';
66

77
const app = express();
88

@@ -41,23 +41,21 @@ app.get('/.live', async (req, res, next) => {
4141
}
4242
});
4343

44-
// render page
45-
app.post('/', async (req, res, next) => {
44+
// render pdf
45+
const handleRender = (renderFunc, contentType) => async (req, res, next) => {
4646
try {
47-
// get inputs from the json payload
4847
const { html = '', options = null } = req.body;
49-
50-
// render the PDF
51-
const pdf = await render(html, options);
52-
53-
// reply with express
54-
res.set('content-type', 'application/pdf');
55-
res.send(pdf);
48+
const result = await renderFunc(html, options);
49+
res.set('content-type', contentType);
50+
res.send(result);
5651
} catch (error) {
57-
// continue with the error
5852
next(error);
5953
}
60-
});
54+
};
55+
56+
app.post('/image', handleRender(renderImage, 'image/jpeg'));
57+
app.post('/pdf', handleRender(renderPdf, 'application/pdf'));
58+
app.post('/', handleRender(renderPdf, 'application/pdf'));
6159

6260
// error handler
6361
app.use((error, req, res, next) => {

src/render.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@ export type RenderOptions = {
77
viewport: puppeteer.Viewport;
88
waitUntil: puppeteer.WaitForOptions['waitUntil'];
99
pdf: puppeteer.PDFOptions;
10+
image: puppeteer.ScreenshotOptions;
1011
};
1112

1213
const defaultOptions: RenderOptions = {
1314
emulateScreenMedia: true,
1415
viewport: { width: 1600, height: 1200 },
1516
waitUntil: 'networkidle2',
1617
pdf: { format: 'a4', printBackground: true },
18+
image: {},
1719
};
1820

19-
const render = async (html: string, customOptions?: Partial<RenderOptions> | null) => {
21+
export const renderPdf = async (html: string, customOptions?: Partial<RenderOptions> | null) => {
2022
const options = merge(defaultOptions, customOptions);
2123

2224
// start browser
@@ -57,4 +59,43 @@ const render = async (html: string, customOptions?: Partial<RenderOptions> | nul
5759
return pdf;
5860
};
5961

60-
export default render;
62+
export const renderImage = async (html: string, customOptions?: Partial<RenderOptions> | null) => {
63+
const options = merge(defaultOptions, customOptions);
64+
65+
// start browser
66+
const browser = await getBrowser();
67+
// start page
68+
const page = await browser.newPage();
69+
70+
// print on console
71+
page.on('console', (...messages) => console.info('Console logs:', ...messages));
72+
73+
// print on error
74+
page.on('error', err => {
75+
console.error(`Error event emitted: ${err}`);
76+
console.error(err.stack);
77+
browser.close();
78+
});
79+
80+
let image: Buffer;
81+
82+
try {
83+
// set view port
84+
await page.setViewport(options.viewport);
85+
86+
if (options.emulateScreenMedia) {
87+
await page.emulateMediaType('screen');
88+
}
89+
90+
// set html content
91+
await page.setContent(html, { waitUntil: options.waitUntil });
92+
93+
// render to image
94+
image = (await page.screenshot(options.image)) as Buffer;
95+
} finally {
96+
// close the page
97+
await page.close();
98+
}
99+
100+
return image;
101+
};

0 commit comments

Comments
 (0)