Skip to content

Commit

Permalink
Merge pull request #1059 from TMS-Uni-Stuttgart/puppeteer-to-gotenberg
Browse files Browse the repository at this point in the history
Puppeteer to gotenberg
  • Loading branch information
nk-coding authored Oct 22, 2024
2 parents 559e269 + a156759 commit 8a649f4
Show file tree
Hide file tree
Showing 13 changed files with 3,032 additions and 3,099 deletions.
8 changes: 8 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,13 @@ services:
networks:
- tms_dev_db

gotenberg:
container_name: gotenberg
image: gotenberg/gotenberg:8
ports:
- '2000:3000'
networks:
- tms_dev_db

networks:
tms_dev_db:
8 changes: 8 additions & 0 deletions docs/docs/assets/dev/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,13 @@ services:
networks:
- tms_dev_db

gotenberg:
container_name: gotenberg
image: gotenberg/gotenberg:8
ports:
- '2000:3000'
networks:
- tms_dev_db

networks:
tms_dev_db:
11 changes: 8 additions & 3 deletions docs/docs/assets/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ services:
image: ghcr.io/dudrie/tutor-management-system:<version>
container_name: tms-server
restart: on-failure:1
cap_add:
# This one is needed so puppeteer properly works inside the container (see: https://developers.google.com/web/tools/puppeteer/troubleshooting#tips)
- SYS_ADMIN
depends_on:
- mysql
networks:
Expand All @@ -43,6 +40,14 @@ services:
# Replace with the path to the folder containing the configuration and template files of the TMS.
- <path-to-CONFIG>:/tms/server/config

gotenberg:
container_name: gotenberg
image: gotenberg/gotenberg:8
ports:
- '2000:3000'
networks:
- tms_db

volumes:
db_data:

Expand Down
5,939 changes: 2,926 additions & 3,013 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions scripts/build-test-docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ services:
volumes:
- ./config:/tms/server/config

gotenberg:
container_name: gotenberg
image: gotenberg/gotenberg:8
ports:
- '2000:3000'
networks:
- tms_db

volumes:
db_data:

Expand Down
24 changes: 13 additions & 11 deletions server/config/development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ handbookUrl: 'https://dudrie.github.io/Tutor-Management-System/'

# Configuration for the database access. More information can be found in the documentation.
database:
host: localhost
port: 3306
databaseName: tms-big-db
maxRetries: 2
reconnectTimeout: 10000
host: localhost
port: 3306
databaseName: tms-big-db
maxRetries: 2
reconnectTimeout: 10000

defaultSettings:
canTutorExcuseStudents: true
defaultTeamSize: 3
canTutorExcuseStudents: true
defaultTeamSize: 3

# Settings used for the puppeteer instance
puppeteer:
# Timeout in ms
timeout: 30000
# Settings used for the gotenberg instance
gotenberg:
host: localhost
port: 2000
# Timeout in ms
timeout: 30000
24 changes: 13 additions & 11 deletions server/config/production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ handbookUrl: 'https://dudrie.github.io/Tutor-Management-System/'

# Configuration for the database access. More information can be found in the documentation.
database:
host: tms_sql
port: 3306
databaseName: tms-db
maxRetries: 2
reconnectTimeout: 10000
host: tms_sql
port: 3306
databaseName: tms-db
maxRetries: 2
reconnectTimeout: 10000

defaultSettings:
canTutorExcuseStudents: true
defaultTeamSize: 3
canTutorExcuseStudents: true
defaultTeamSize: 3

# Settings used for the puppeteer instance
puppeteer:
# Timeout in ms
timeout: 30000
# Settings used for the gotenberg instance
gotenberg:
host: gotenberg
port: 3000
# Timeout in ms
timeout: 30000
4 changes: 2 additions & 2 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@
"@nestjs/passport": "^9.0.0",
"@nestjs/platform-express": "^9.0.11",
"@nestjs/swagger": "^6.1.0",
"axios": "^1.7.7",
"bcryptjs": "^2.4.3",
"body-parser": "^1.20.0",
"class-validator": "^0.13.2",
"excel4node": "^1.8.0",
"express-session": "^1.17.3",
"form-data": "^4.0.1",
"highlight.js": "^10.7.2",
"jszip": "^3.10.1",
"luxon": "^1.25.0",
Expand All @@ -48,7 +50,6 @@
"passport": "^0.6.0",
"passport-local": "^1.0.0",
"pug": "^3.0.2",
"puppeteer": "5.5.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.5.6",
Expand All @@ -73,7 +74,6 @@
"@types/passport": "^1.0.10",
"@types/passport-local": "^1.0.34",
"@types/pug": "^2.0.6",
"@types/puppeteer": "5.4.2",
"@types/supertest": "^2.0.12",
"@types/uuid": "^8.3.4",
"jest": "^29.0.0",
Expand Down
70 changes: 25 additions & 45 deletions server/src/module/pdf/subservices/PDFGenerator.core.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// noinspection HtmlRequiredLangAttribute,HtmlRequiredTitleElement

import { Logger } from '@nestjs/common';
import axios from 'axios';
import FormData from 'form-data';
import fs from 'fs';
import puppeteer from 'puppeteer';
import { StaticSettings } from '../../settings/settings.static';
import { StaticSettings } from 'module/settings/settings.static';

/**
* @param T Type of the options passed to `generatePDF`.
Expand All @@ -29,52 +30,31 @@ export abstract class PDFGenerator<T = Record<string, unknown>> {
*/
protected async generatePDFFromBodyContent(body: string): Promise<Buffer> {
const html = await this.putBodyInHTML(body);
let browser: puppeteer.Browser | undefined;

this.logger.debug('Starting browser...');
this.logger.debug(`\tExec path: ${process.env.TMS_PUPPETEER_EXEC_PATH}`);
const gotenbergConfig = StaticSettings.getService().getGotenbergConfiguration();

try {
browser = await puppeteer.launch({
args: ['--disable-dev-shm-usage'],
executablePath: process.env.TMS_PUPPETEER_EXEC_PATH,
timeout: StaticSettings.getService().getPuppeteerConfiguration()?.timeout,
});

this.logger.debug('Browser started.');

const page = await browser.newPage();
this.logger.debug('Page created.');

await page.setContent(html, { waitUntil: 'domcontentloaded' });
this.logger.debug('Page content loaded');

const buffer = await page.pdf({
format: 'A4',
margin: {
top: '1cm',
right: '1cm',
bottom: '1cm',
left: '1cm',
},
// Fixes CSS 'background' not being respected in printed PDFs.
printBackground: true,
});

this.logger.debug('PDF created.');

await browser.close();

this.logger.debug('Browser closed');

return buffer;
const form = new FormData();
form.append('files', html, { filename: 'index.html', contentType: 'text/html' });

this.logger.debug('Sending request to Gotenberg for PDF generation...');

const response = await axios.post(
`http://${gotenbergConfig?.host}:${gotenbergConfig?.port}/forms/chromium/convert/html`,
form,
{
headers: {
...form.getHeaders(),
},
timeout: gotenbergConfig?.timeout,
responseType: 'arraybuffer',
}
);

this.logger.debug('PDF generated successfully from Gotenberg.');

return Buffer.from(response.data);
} catch (err) {
if (browser) {
await browser.close();
}

Logger.error(JSON.stringify(err, null, 2));

this.logger.error('Failed to generate PDF:', err);
throw err;
}
}
Expand Down
6 changes: 3 additions & 3 deletions server/src/module/settings/model/ApplicationConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Type } from 'class-transformer';
import { IsNumber, IsOptional, IsString, IsUrl, Min, ValidateNested } from 'class-validator';
import { ClientSettingsDTO } from '../settings.dto';
import { DatabaseConfiguration } from './DatabaseConfiguration';
import { PuppeteerConfiguration } from './PuppeteerConfiguration';
import { GotenbergConfiguration } from './GotenbergConfiguration';

export class ApplicationConfiguration {
@IsOptional()
Expand All @@ -28,7 +28,7 @@ export class ApplicationConfiguration {
readonly defaultSettings: ClientSettingsDTO | undefined;

@IsOptional()
@Type(() => PuppeteerConfiguration)
@Type(() => GotenbergConfiguration)
@ValidateNested()
readonly puppeteer: PuppeteerConfiguration | undefined;
readonly gotenberg: GotenbergConfiguration | undefined;
}
14 changes: 14 additions & 0 deletions server/src/module/settings/model/GotenbergConfiguration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { IsNumber, IsString, Min } from 'class-validator';

export class GotenbergConfiguration {
@IsString()
readonly host!: string;

@IsNumber({}, { always: true })
@Min(0)
readonly timeout!: number;

@IsNumber({}, { always: true })
@Min(0)
readonly port!: number;
}
7 changes: 0 additions & 7 deletions server/src/module/settings/model/PuppeteerConfiguration.ts

This file was deleted.

8 changes: 4 additions & 4 deletions server/src/module/settings/settings.static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
DatabaseConnectionOptions,
} from './model/DatabaseConfiguration';
import { ENV_VARIABLE_NAMES, EnvironmentConfig } from './model/EnvironmentConfig';
import { PuppeteerConfiguration } from './model/PuppeteerConfiguration';
import { GotenbergConfiguration } from './model/GotenbergConfiguration';

export class StaticSettings {
private static service: StaticSettings = new StaticSettings();
Expand Down Expand Up @@ -74,10 +74,10 @@ export class StaticSettings {
}

/**
* @returns Configuration for the puppeteer instance. Can be `undefined`.
* @returns Configuration for the gotenberg instance. Can be `undefined`.
*/
getPuppeteerConfiguration(): PuppeteerConfiguration | undefined {
return this.config.puppeteer;
getGotenbergConfiguration(): GotenbergConfiguration | undefined {
return this.config.gotenberg;
}

/**
Expand Down

0 comments on commit 8a649f4

Please sign in to comment.