Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add chromium headless backend #482

Draft
wants to merge 1 commit into
base: v2-unstable
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/spec/ export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/phpspec.yaml export-ignore
12 changes: 9 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,19 @@
"psr/http-message": "^2.0"
},
"autoload": {
"psr-4": {
"KnpLabs\\Snappy\\": "src/"
}
"psr-4": { "KnpLabs\\Snappy\\": "src/" },
"exclude-from-classmap": [
"/spec/"
]
},
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"require-dev": {
"nyholm/psr7": "^1.8",
"beberlei/assert": "^3.3",
"phpspec/phpspec": "^7.4"
}
}
5 changes: 5 additions & 0 deletions phpspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
suites:
chrome_headless:
namespace: KnpLabs\Snappy
src_path: 'src/Backend/ChromeHeadless'
spec_path: 'src/Backend/ChromeHeadless/spec'
3 changes: 3 additions & 0 deletions src/Backend/ChromeHeadless/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/vendor
/composer.lock
/Dockerfile
5 changes: 5 additions & 0 deletions src/Backend/ChromeHeadless/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/.github/ export-ignore
/spec/ export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/phpspec.yaml export-ignore
2 changes: 2 additions & 0 deletions src/Backend/ChromeHeadless/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/composer.lock
/vendor
75 changes: 75 additions & 0 deletions src/Backend/ChromeHeadless/ChromeHeadlessToPdf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

namespace KnpLabs\Snappy\Backend\ChromeHeadless;

use KnpLabs\Snappy\Core\FileToPdf;
use KnpLabs\Snappy\Core\UriToPdf;
use Psr\Http\Message\StreamFactoryInterface;
use Psr\Http\Message\StreamInterface;
use Psr\Http\Message\UriInterface;
use Symfony\Component\Process\Process;

final class ChromeHeadlessToPdf implements FileToPdf, UriToPdf
{
public function __construct(private string $binary, private StreamFactoryInterface $streamFactory)
{
}

public function generateFromFile(\SplFileInfo $file, \ArrayAccess|array $options = []): StreamInterface
{
$path = $file->getRealPath();

if (!$path) {
throw new \RuntimeException('The input file does not exist');
}

return $this->generate($path, $options);
}

public function generateFromUri(UriInterface $url, \ArrayAccess|array $options = []): StreamInterface
{
return $this->generate((string) $url, $options);
}

private function generate(string $path, \ArrayAccess|array $options = []): StreamInterface
{
$escapedBinary = \escapeshellarg($this->binary);
$binary = is_executable($escapedBinary) ? $escapedBinary : $this->binary;

if (array_key_exists('print-to-pdf', $options)) {
$output = $options['print-to-pdf'];
} else {
$output = tempnam(sys_get_temp_dir(), 'snappy_');

$options['print-to-pdf'] = \escapeshellarg($output);
}

$args = [];

foreach ($options as $key => $value) {
$args[] = null === $value ? "--{$key}" : "--{$key}={$value}";
}

$command = implode(' ', [$binary, ...$args, $path]);

$process = Process::fromShellCommandline($command);

$process->run();

$result = $process->getExitCode();
$stdout = $process->getOutput();
$stderr = $process->getErrorOutput();

if (0 !== $result) {
throw new \RuntimeException("The command {$command} returned an exit code {$result}. stdout: {$stdout}. stderr: {$stderr}");
}

if (!file_exists($output)) {
throw new \RuntimeException("The output file {$output} does not exist");
}

return $this->streamFactory->createStreamFromFile($output);
}
}
22 changes: 22 additions & 0 deletions src/Backend/ChromeHeadless/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM composer:2.5.8 as composer

###############

FROM php:8.0.29-alpine3.16

RUN mkdir -p /opt/app \
&& adduser -D docker \
&& chown -R docker:docker /opt/app

USER docker

COPY --from=composer /usr/bin/composer /usr/bin/composer

WORKDIR /opt/app

COPY --chown=docker . /opt/app

RUN composer install

ENTRYPOINT ["/bin/sh", "-c"]
CMD ["vendor/bin/phpspec run"]
47 changes: 47 additions & 0 deletions src/Backend/ChromeHeadless/composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "knplabs/snappy-backend-chrome-headless",
"type": "library",
"description": "Easily create PDF and images in Symfony from HTML inputs",
"keywords": ["knplabs", "knp", "snappy", "pdf", "bundle"],
"homepage": "http://github.com/KnpLabs/snappy",
"license": "MIT",
"authors": [
{
"name": "KnpLabs",
"homepage": "https://knplabs.com"
},
{
"name": "Symfony Community",
"homepage": "http://github.com/KnpLabs/snappy/contributors"
}
],
"repositories": [
{
"type": "path",
"url": "../../Core"
}
],
"require": {
"php": ">=8.0",
"symfony/process": "~5.0||~6.0",
"psr/log": "^2.0||^3.0",
"psr/http-message": "^2.0",
"knplabs/snappy-core": "@dev"
},
"autoload": {
"psr-4": { "KnpLabs\\Snappy\\Backend\\ChromeHeadless\\": "" },
"exclude-from-classmap": [
"/spec/"
]
},
"autoload-dev": {
"psr-4": {
"KnpLabs\\Snappy\\Backend\\ChromeHeadless\\Spec\\": "spec/"
}
},
"require-dev": {
"phpspec/phpspec": "^7.4",
"beberlei/assert": "^3.3",
"nyholm/psr7": "^1.8"
}
}
5 changes: 5 additions & 0 deletions src/Backend/ChromeHeadless/phpspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
suites:
default:
namespace: KnpLabs\Snappy\Backend\ChromeHeadless
psr4_prefix: KnpLabs\Snappy\Backend\ChromeHeadless
src_path: '%paths.config%'
33 changes: 33 additions & 0 deletions src/Backend/ChromeHeadless/spec/ChromeHeadlessToPdf/example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<title>Lorem Ipsum</title>
</head>
<body>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam et ex in leo euismod ornare. Etiam id pretium urna. Nam diam ligula, blandit tincidunt felis placerat, luctus porttitor orci. In auctor leo a egestas tristique. Mauris in hendrerit dui. Sed maximus nisl eu ante consequat porttitor. Cras scelerisque fermentum molestie. Vivamus hendrerit metus id eros placerat, non malesuada nunc posuere. Nunc bibendum risus est, aliquet pharetra eros sodales at. Morbi et sapien id nunc fermentum viverra non vel sem. In ut velit at risus consequat fermentum et eu risus. Ut dignissim auctor justo, sodales tincidunt tellus accumsan eget. Fusce viverra leo id erat congue, a accumsan tortor hendrerit. Cras volutpat mauris purus, a feugiat turpis mollis fringilla. Sed a sollicitudin elit. Curabitur nunc velit, auctor a lorem et, ornare suscipit sapien.</p>
<p>Vivamus at purus consectetur, commodo nulla ut, aliquam sapien. Integer a augue non massa vulputate interdum eget ut mauris. Etiam at purus non leo condimentum bibendum. Vivamus tristique ullamcorper augue, vitae placerat justo placerat vitae. Donec molestie velit orci. Fusce quis ornare diam. Curabitur a lacus quam. Nam finibus, sapien sed auctor scelerisque, lectus erat lobortis neque, non viverra nisi dui id ipsum.</p>
<p>Suspendisse potenti. Donec maximus, diam eu volutpat maximus, sapien eros aliquam mauris, quis imperdiet odio ex eu eros. Maecenas metus justo, tempor non sollicitudin nec, porta ac velit. Morbi lacinia, est suscipit ultricies semper, magna nisl facilisis diam, vitae rutrum ante eros in justo. In rutrum metus sed sapien ultrices commodo. Proin porttitor facilisis leo in varius. Nulla rutrum lacinia ultricies. Etiam vel auctor eros, at pharetra neque. In risus quam, luctus a odio sed, interdum molestie enim. Aenean aliquet blandit tellus, condimentum vehicula ex interdum et. Pellentesque vel tortor orci.</p>
<p>Morbi odio justo, mattis scelerisque ante in, mattis rhoncus enim. Mauris ac tempus neque. Morbi porttitor consectetur justo id tristique. Nulla lorem est, pretium malesuada imperdiet sit amet, commodo eget odio. Integer vel lectus efficitur, iaculis leo nec, commodo lacus. Etiam ornare elit eu nibh facilisis, id elementum tortor iaculis. Aliquam pharetra urna et est tincidunt rhoncus. In augue orci, pellentesque sit amet consectetur ac, mattis at elit.</p>
<p>Praesent viverra suscipit lacus, eget scelerisque lacus tincidunt id. Duis bibendum lacinia tincidunt. Sed consectetur eu ipsum in commodo. Mauris dapibus urna lobortis diam fringilla varius. Nunc et dui nec mauris malesuada rutrum at feugiat mauris. Nullam ullamcorper nec purus quis dignissim. Fusce congue, ligula sed efficitur varius, elit sem auctor sem, ut volutpat risus libero ac purus. Nullam dignissim est ut commodo accumsan. Nunc aliquet ac sapien ut faucibus. Quisque aliquam quam id sapien interdum, ut aliquet mi molestie. Aenean condimentum vitae lectus a finibus. Quisque placerat eleifend mauris in pharetra. Aenean velit risus, tincidunt porta facilisis eget, porta et sapien. Sed pharetra libero quis lobortis placerat.</p>
<p>Maecenas velit nisi, auctor vitae enim et, faucibus rutrum enim. Praesent pellentesque sodales nisi a faucibus. Sed varius tortor ut lorem condimentum porta. Donec fermentum ante ligula, nec sagittis sapien aliquam consequat. Pellentesque faucibus nisl ut tincidunt hendrerit. Pellentesque dictum molestie arcu, id fringilla libero consequat ut. Proin tristique lorem at leo tristique venenatis.</p>
<p>Donec pellentesque nunc quam, ut posuere neque vulputate faucibus. Phasellus eu pulvinar velit. Pellentesque varius tincidunt leo. Etiam eget nisi est. Cras aliquam gravida massa, non commodo odio condimentum ac. In hac habitasse platea dictumst. Fusce bibendum tempor metus, ac scelerisque lacus feugiat non. Duis nisl tortor, ultricies porttitor mauris eget, commodo bibendum nibh. Etiam non eros condimentum erat porttitor fringilla non at turpis.</p>
<p>Integer eget efficitur metus, in cursus augue. Aliquam sapien leo, elementum non aliquet at, facilisis ut dolor. Morbi in nibh in est tempus dapibus. Donec lorem ante, aliquet at posuere vel, sollicitudin et odio. Duis quis elementum arcu. Aenean sed augue lorem. Proin egestas vitae augue quis sollicitudin. Fusce volutpat diam ut felis vestibulum, ac sagittis nulla mattis. Duis semper, mauris ut facilisis sagittis, odio turpis sagittis felis, in aliquam risus augue sit amet enim. Nullam elementum pellentesque lectus ac malesuada. Proin ut magna leo.</p>
<p>Duis blandit ipsum mi. Vivamus iaculis vulputate dui, id iaculis ligula vestibulum sit amet. Aliquam enim arcu, convallis sit amet consequat sed, mollis hendrerit tellus. Curabitur eu eleifend enim. Vivamus congue vitae orci vehicula scelerisque. Praesent iaculis sapien ac magna suscipit, in maximus massa congue. Duis massa orci, facilisis eget eros sed, posuere commodo sem. Aliquam erat volutpat.</p>
<p>Vivamus mattis eget purus quis tincidunt. Integer consectetur massa ac enim condimentum, quis molestie ipsum dapibus. Vivamus blandit porta lacus, id scelerisque elit venenatis at. Sed at lectus et nibh laoreet efficitur. Phasellus semper, lacus sit amet venenatis auctor, purus lorem malesuada orci, sed venenatis metus turpis vel neque. Sed convallis magna non arcu rhoncus viverra. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nullam sed faucibus augue, nec ullamcorper massa. Interdum et malesuada fames ac ante ipsum primis in faucibus. Mauris fringilla finibus neque, at dapibus magna commodo in. Suspendisse egestas, tortor id vehicula rutrum, lectus sapien consectetur libero, id sodales erat neque sed mauris. Duis non mattis lectus.</p>
<p>Nulla placerat, lorem id sagittis aliquam, nibh eros molestie nisl, et sagittis orci risus eu ligula. Mauris faucibus velit tempor quam viverra, nec faucibus purus tincidunt. Nulla ac arcu ac tellus aliquam ultricies ac eget augue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Donec laoreet orci nulla, non porta diam tincidunt et. Nulla facilisi. Mauris semper sagittis ante, ac tempus erat gravida ut. Mauris metus nisl, fermentum mollis consequat vel, condimentum quis nibh. In hac habitasse platea dictumst. Ut ut cursus diam, fringilla scelerisque augue. Maecenas pretium dignissim erat et elementum. Donec sit amet justo vulputate tellus ultrices maximus. Quisque tempor tortor mauris, ut varius dolor ultrices vel. Vestibulum nunc lectus, aliquam eu tempor in, tincidunt non lorem.</p>
<p>Nulla non metus ut ligula mollis feugiat et et diam. Donec interdum accumsan massa at sodales. Curabitur tempus risus quis augue elementum egestas. Fusce arcu nibh, sodales quis eros nec, ornare finibus mauris. Proin iaculis commodo orci tincidunt pellentesque. Vestibulum viverra euismod ante nec condimentum. Proin at quam laoreet, viverra erat in, condimentum mauris. Proin et egestas massa. Etiam in ornare diam, eu sagittis risus.</p>
<p>Maecenas molestie nisi nec risus facilisis, at dapibus lectus scelerisque. Pellentesque ornare ac lectus nec tristique. Nunc porttitor accumsan felis, sit amet sagittis libero faucibus id. Donec auctor magna et sapien consectetur, eget lobortis turpis elementum. Curabitur lobortis diam non condimentum ornare. Aliquam erat volutpat. Donec iaculis nunc vitae elit porta efficitur. Pellentesque in ipsum condimentum, vestibulum ipsum in, imperdiet ipsum. Sed at sapien massa. Cras fermentum turpis eget lorem elementum mattis. Nunc facilisis porttitor elit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.</p>
<p>Donec ac enim ut leo scelerisque auctor eu ullamcorper ex. Sed tortor risus, gravida id semper faucibus, accumsan sit amet diam. Vivamus odio turpis, ultricies at nisl ut, posuere aliquam ex. Donec ut odio condimentum, ultrices elit eu, semper est. Curabitur risus odio, lacinia in malesuada nec, sollicitudin vel ex. Vivamus in lacus arcu. Donec feugiat finibus sapien, at vulputate ante consequat et. Donec feugiat, nisl sed lobortis auctor, est risus elementum est, quis viverra nisl diam at nunc.</p>
<p>Quisque efficitur fringilla ante, non sollicitudin sapien aliquet sed. Proin quam orci, eleifend et feugiat eget, tempus sed massa. Sed rhoncus mattis dui, ac semper nunc blandit eu. Maecenas id ligula neque. Quisque tortor lacus, condimentum at nisl id, hendrerit facilisis quam. Sed vehicula quam quam, id semper erat tempus eget. Mauris vestibulum metus a pharetra interdum. Integer efficitur luctus mi, ac lobortis dui sagittis ac. Praesent gravida metus ac purus tincidunt elementum. Sed nunc felis, imperdiet nec tortor eget, aliquam imperdiet arcu. Nulla ac magna maximus, volutpat ante eget, convallis diam. Proin quis ipsum massa. Sed posuere augue vitae tellus pulvinar porta. In hac habitasse platea dictumst. Vestibulum mattis augue ac ligula egestas, eget sagittis ante euismod.</p>
<p>Vestibulum volutpat consequat varius. Proin posuere vel purus et vulputate. In semper, orci non vestibulum semper, mauris nisl elementum sem, vitae cursus urna est nec mauris. Pellentesque urna lacus, finibus a pharetra hendrerit, viverra quis ipsum. Suspendisse lacinia augue in pharetra facilisis. Donec consequat vitae quam tempor consequat. Nam condimentum congue augue, et sollicitudin nisi ullamcorper dictum. Fusce sed euismod elit.</p>
<p>Praesent varius consectetur mauris, in consectetur urna sagittis id. Etiam pulvinar sollicitudin purus in egestas. Phasellus gravida erat non dui euismod sagittis. Duis aliquam eu arcu eget pretium. Sed purus felis, vestibulum vitae consequat ut, semper ut enim. Nunc a tortor ut nunc egestas viverra non et lorem. Nulla placerat nunc sed ligula interdum euismod. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; In pellentesque consectetur dictum. Sed posuere arcu et gravida auctor. Etiam mollis mauris sit amet maximus tempus. Sed posuere urna id nunc lobortis vestibulum. Nullam vitae congue felis, sed accumsan ligula. Sed a posuere diam. Aenean a mauris finibus, vehicula justo eu, lobortis neque.</p>
<p>Quisque vitae nulla quis velit pulvinar tristique. Donec mattis dignissim laoreet. Vestibulum molestie ultricies nunc, laoreet commodo libero interdum ut. Curabitur vel scelerisque nisl, eget tincidunt est. Vestibulum ac eleifend eros. Donec viverra posuere felis id molestie. Integer suscipit tortor a finibus rutrum. Vivamus sed molestie odio, a lacinia magna. Etiam sodales fermentum libero eu porta. Pellentesque vitae justo a nibh tempor tincidunt.</p>
<p>In pretium ex id ante efficitur posuere. Praesent sollicitudin non nisl in venenatis. Nulla nec justo quis nibh pellentesque vehicula. Praesent feugiat blandit purus, eget aliquet lectus. Curabitur non mattis lectus. Aenean tincidunt metus quis vulputate pretium. Nullam ultrices egestas elementum. Quisque molestie, dui ut mattis ornare, lectus odio tincidunt felis, sed rhoncus nisi ante iaculis erat. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Quisque ut gravida nunc.</p>
<p>Etiam ac lacus nisi. Morbi ac dignissim nisi. Ut dapibus, nibh quis tempor posuere, neque sapien suscipit neque, non suscipit dolor nibh ac eros. Cras condimentum commodo fermentum. Aenean ultricies consequat ex vitae convallis. Donec vestibulum nisi et gravida pretium. Integer ornare purus lacus, sit amet venenatis dui molestie a. Duis blandit, urna sit amet scelerisque lacinia, ante velit blandit orci, vel dictum risus ligula sit amet massa.</p>
<p>Nunc felis purus, fermentum et quam quis, lobortis eleifend magna. Mauris vel accumsan nulla. Mauris aliquet ultrices ex, ut feugiat felis consequat vitae. In suscipit sit amet ligula et pellentesque. Vestibulum eu nisi posuere, vulputate ipsum et, semper magna. Nam ac volutpat dui. Curabitur luctus a mauris ut congue. Nunc sit amet ultricies ante, non porta leo. Pellentesque ac risus et nibh placerat sodales. Morbi consequat turpis eu felis euismod, in semper nisl posuere. Praesent sodales pretium ligula eu commodo. Nulla semper lorem sed nulla aliquet molestie. In libero dui, aliquam in justo eu, molestie malesuada dui. Suspendisse porta eros id eleifend eleifend.</p>
<p>Aliquam pellentesque turpis sed est molestie, nec elementum leo tempor. Vivamus ut purus eget turpis faucibus ornare commodo id velit. Donec at ultrices ligula. Curabitur et nibh vel neque vulputate blandit sit amet non lectus. Vestibulum egestas nulla tincidunt massa dapibus, vitae commodo nunc tristique. Donec non ultrices eros. Aenean et justo felis.</p>
<p>Sed vitae molestie enim. Etiam nec vulputate lacus. Cras non erat nec augue porta sagittis. Nunc placerat ex ut condimentum dictum. Nunc commodo sapien non malesuada rhoncus. Sed porttitor eu ex et fringilla. Vestibulum ac justo ac sapien lacinia pretium nec ac dolor. Duis sodales non neque sed dignissim. Sed tortor lorem, ultrices id ipsum ut, sagittis ullamcorper nisl. Mauris molestie libero nec justo facilisis, eget sollicitudin enim convallis. Sed hendrerit euismod orci at luctus. Cras ultricies augue ut quam ultricies, nec faucibus nibh tincidunt. Vivamus facilisis, justo non tristique eleifend, urna turpis hendrerit velit, ac bibendum mauris eros quis tellus.</p>
<p>Integer in mi accumsan, suscipit enim eu, pulvinar arcu. Ut eget ultricies dui. Integer ac mi faucibus, dapibus elit non, fringilla lacus. Suspendisse ac nunc a justo bibendum mollis et sit amet nibh. Etiam pulvinar nulla vitae massa tristique tristique. Suspendisse ut enim dignissim, varius magna sed, dapibus mi. Quisque at turpis vulputate, dictum odio at, aliquet tellus. Integer in neque viverra enim sodales fermentum. Sed eget tempus magna. Sed ut nulla vitae tellus tempus aliquam. In vitae fermentum dolor. Pellentesque vitae urna quis ipsum convallis dignissim. Proin vel hendrerit ante.</p>
<p>Phasellus convallis elit id tristique laoreet. Nunc suscipit erat vitae odio volutpat elementum. Nam viverra, dolor nec placerat ultrices, neque metus dignissim est, ac placerat nibh nisi non turpis. Quisque in nunc libero. Cras eget venenatis mi. Vivamus sit amet tellus accumsan, malesuada nunc auctor, interdum nulla. Cras pretium, nisl egestas blandit consequat, nulla nunc maximus nibh, quis fringilla nibh eros vitae quam. Donec finibus lacinia nulla vitae placerat. Pellentesque dictum malesuada lorem, in vehicula arcu suscipit vitae. Donec vel mauris lorem.</p>
</body>
</html>
Loading