├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── bin └── download-emoji-font.sh ├── composer.json ├── config └── sidecar-browsershot.php ├── package-lock.json ├── package.json ├── resources └── lambda │ ├── browsershot.js │ └── fonts │ └── NotoColorEmoji.ttf └── src ├── BrowsershotLambda.php ├── Commands └── InternalBrowsershotSetupCommand.php ├── Functions └── BrowsershotFunction.php └── SidecarBrowsershotServiceProvider.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.6.0...HEAD) 9 | 10 | ## [v2.6.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.5.1...v2.6.0) - 2025-05-08 11 | 12 | ### Added 13 | 14 | - Add Support for Laravel 12 ([#139](https://github.com/stefanzweifel/sidecar-browsershot/pull/139)) 15 | 16 | ## [v2.5.1](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.5.0...v2.5.1) - 2025-03-23 17 | 18 | ### Changed 19 | 20 | - Update Chrome versions ([#140](https://github.com/stefanzweifel/sidecar-browsershot/pull/140)) 21 | 22 | ## [v2.5.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.4.0...v2.5.0) - 2024-12-05 23 | 24 | ### Added 25 | 26 | - Add support for spatie/browsershot v5 ([#137](https://github.com/stefanzweifel/sidecar-browsershot/pull/137)) 27 | 28 | ## [v2.4.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.3.3...v2.4.0) - 2024-11-13 29 | 30 | ### Added 31 | 32 | - Add Support for PHP 8.4 ([#136](https://github.com/stefanzweifel/sidecar-browsershot/pull/136)) 33 | 34 | ## [v2.3.3](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.3.2...v2.3.3) - 2024-05-16 35 | 36 | ### Fixed 37 | 38 | - Fix downstream breaking change in throw() method by passing default value [a682b2](https://github.com/stefanzweifel/sidecar-browsershot/commit/a682b2d6cc5dfc47bc9e26526417a3f233f9b0e4) 39 | 40 | ## [v2.3.2](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.3.1...v2.3.2) - 2024-05-16 41 | 42 | ### Changed 43 | 44 | - Bump up hammerstone/sidecar version ([#132](https://github.com/stefanzweifel/sidecar-browsershot/pull/132)) 45 | 46 | ## [v2.3.1](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.3.0...v2.3.1) - 2024-03-21 47 | 48 | ### Fixed 49 | 50 | - Fix support for Laravel 11 ([#120](https://github.com/stefanzweifel/sidecar-browsershot/pull/120)) 51 | 52 | ## [v2.3.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.2.0...v2.3.0) - 2024-03-21 53 | 54 | ### Added 55 | 56 | - Add Support for Laravel 11 ([#111](https://github.com/stefanzweifel/sidecar-browsershot/pull/111)) 57 | 58 | ## [v2.2.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.1.0...v2.2.0) - 2024-02-20 59 | 60 | ### Added 61 | 62 | - Switch to Node 20 Runtime ([#115](https://github.com/stefanzweifel/sidecar-browsershot/pull/115)) 63 | 64 | ## [v2.1.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v2.0.0...v2.1.0) - 2024-02-17 65 | 66 | ### Changed 67 | 68 | - Update used AWS Lambda Layers to use puppeteer-core v22 and Chromium v121.0.0 ([#113](https://github.com/stefanzweifel/sidecar-browsershot/pull/113)) 69 | 70 | ## [v2.0.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.13.1...v2.0.0) - 2023-12-30 71 | 72 | Maintenance release to support `spatie/browsershot` v4. Besides renaming a configuration key, there are no breaking changes. If you do image manipulations you now need to install `spatie/image` separately. 73 | 74 | We also dropped support for older PHP and Laravel versions to make maintenance easier. 75 | 76 | See our [upgrade guide](https://github.com/stefanzweifel/sidecar-browsershot/blob/5d3d8be55400ba461f7ff369e3a653d81ea6e3c3/UPGRADING.md#from-v1-to-v2) for details. 77 | 78 | ### Changed 79 | 80 | - [BREAKING] Rename `sidecar-browsershot.layer`-config to `sidecar-browsershot.layers`-config ([#103](https://github.com/stefanzweifel/sidecar-browsershot/pull/103)) 81 | - Support Browsershot v4 ([#107](https://github.com/stefanzweifel/sidecar-browsershot/pull/107)) 82 | - Improve Reference Test to use Pixelmatch ([#108](https://github.com/stefanzweifel/sidecar-browsershot/pull/108)) 83 | 84 | ### Removed 85 | 86 | - Drop Support for PHP 8.0 and PHP 8.1 and Laravel 8 and Laravel 9 ([#106](https://github.com/stefanzweifel/sidecar-browsershot/pull/106)) 87 | 88 | ## [v1.13.1](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.13.0...v1.13.1) - 2023-12-16 89 | 90 | ### Fixed 91 | 92 | - Add internal support for Chromium Result ([#105](https://github.com/stefanzweifel/sidecar-browsershot/pull/105)) 93 | 94 | ## [v1.13.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.12.0...v1.13.0) - 2023-11-06 95 | 96 | ### Added 97 | 98 | - Add support for adding custom fonts to Chromium ([#101](https://github.com/stefanzweifel/sidecar-browsershot/pull/101)) 99 | 100 | ## [v1.12.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.11.1...v1.12.0) - 2023-10-16 101 | 102 | ### Added 103 | 104 | - Add Support for PHP 8.3 ([#98](https://github.com/stefanzweifel/sidecar-browsershot/pull/98)) 105 | 106 | ## [v1.11.1](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.11.0...v1.11.1) - 2023-10-11 107 | 108 | ### Fixed 109 | 110 | - Read the content of a file in s3 into a string ([#93](https://github.com/stefanzweifel/sidecar-browsershot/pull/93)) 111 | 112 | ## [v1.11.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.10.0...v1.11.0) - 2023-10-09 113 | 114 | ### Added 115 | 116 | - Add `sidecar-browsershot.timeout` a config to allow the overriding of default timeout value ([#90](https://github.com/stefanzweifel/sidecar-browsershot/pull/90)) 117 | 118 | ## [v1.10.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.9.1...v1.10.0) - 2023-09-20 119 | 120 | ### Added 121 | 122 | - Update to Node 18 Runtime and update used Chromium Version ([#85](https://github.com/stefanzweifel/sidecar-browsershot/pull/85)) 123 | 124 | ### Changed 125 | 126 | - Bump actions/checkout from 3 to 4 ([#84](https://github.com/stefanzweifel/sidecar-browsershot/pull/84)) 127 | - Fix GitHub Actions badges in `README.md` ([#82](https://github.com/stefanzweifel/sidecar-browsershot/pull/82)) 128 | 129 | ## [v1.9.1](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.9.0...v1.9.1) - 2023-07-05 130 | 131 | ### Changed 132 | 133 | - Raise minumum required spatie/browsershot version to v3.57.8. 134 | 135 | ### Fixed 136 | 137 | - Fix for renamed browser.js file in browsershot 3.57.8 ([#78](https://github.com/stefanzweifel/sidecar-browsershot/pull/78)) 138 | 139 | ## [v1.9.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.8.1...v1.9.0) - 2023-05-13 140 | 141 | ### Added 142 | 143 | - Add Support for Image Manipulations when using `saveToS3` ([#71](https://github.com/stefanzweifel/sidecar-browsershot/pull/71)) 144 | 145 | ## [v1.8.1](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.8.0...v1.8.1) - 2023-05-01 146 | 147 | ### Fixed 148 | 149 | - Only support x86_64 architecture ([#68](https://github.com/stefanzweifel/sidecar-browsershot/pull/68)) 150 | 151 | ## [v1.8.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.7.0...v1.8.0) - 2023-04-28 152 | 153 | ### Added 154 | 155 | - Added storage config setting ([#64](https://github.com/stefanzweifel/sidecar-browsershot/pull/64)) 156 | 157 | ### Changed 158 | 159 | - Upgrade to use Pest v2 ([#62](https://github.com/stefanzweifel/sidecar-browsershot/pull/62)) 160 | 161 | ## [v1.7.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.6.4...v1.7.0) - 2023-03-29 162 | 163 | ### Added 164 | 165 | - Add `readHtmlFromS3()`-method ([#60](https://github.com/stefanzweifel/sidecar-browsershot/pull/60)) 166 | 167 | ## [v1.6.4](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.6.3...v1.6.4) - 2023-03-02 168 | 169 | ### Changed 170 | 171 | - Add Support for Sidecar v0.4.0 ([#58](https://github.com/stefanzweifel/sidecar-browsershot/pull/58)) 172 | 173 | ## [v1.6.3](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.6.2...v1.6.3) - 2023-02-27 174 | 175 | ### Changed 176 | 177 | - Cleanup puppeteer_dev_chrome_profile folders in tmp after running Puppeteer ([#54](https://github.com/stefanzweifel/sidecar-browsershot/pull/54)) 178 | 179 | ### Fixed 180 | 181 | - Store Emoji Font in package ([#56](https://github.com/stefanzweifel/sidecar-browsershot/pull/56)) 182 | 183 | ## [v1.6.2](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.6.1...v1.6.2) - 2023-02-22 184 | 185 | ### Changed 186 | 187 | - Include emoji font in lambda bundle ([#51](https://github.com/stefanzweifel/sidecar-browsershot/pull/51)) 188 | 189 | ## [v1.6.1](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.6.0...v1.6.1) - 2023-02-14 190 | 191 | ### Fixed 192 | 193 | - Use sidecar.aws_region value in saveToS3 method ([#48](https://github.com/stefanzweifel/sidecar-browsershot/pull/48)) 194 | 195 | ## [v1.6.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.5.0...v1.6.0) - 2023-02-04 196 | 197 | ### Added 198 | 199 | - Add Support for Laravel 10 ([#45](https://github.com/stefanzweifel/sidecar-browsershot/pull/45)) 200 | 201 | ## [v1.5.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.4.1...v1.5.0) - 2022-12-28 202 | 203 | ### Added 204 | 205 | - Load Emoji Font to support Emoji Characters ([#42](https://github.com/stefanzweifel/sidecar-browsershot/pull/42)) 206 | 207 | ## [v1.4.1](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.4.0...v1.4.1) - 2022-11-25 208 | 209 | ### Fixed 210 | 211 | - Trim base64 PDF Response by overriding base64pdf method ([#38](https://github.com/stefanzweifel/sidecar-browsershot/pull/38)) 212 | 213 | ## [v1.4.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.3.0...v1.4.0) - 2022-11-06 214 | 215 | ### Added 216 | 217 | - Add PHP 8.2 Support ([#35](https://github.com/stefanzweifel/sidecar-browsershot/pull/35)) 218 | 219 | ### Fixed 220 | 221 | - Fix Typo in browsershot.js ([#31](https://github.com/stefanzweifel/sidecar-browsershot/pull/31)) 222 | 223 | ## [v1.3.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.2.1...v1.3.0) - 2022-08-15 224 | 225 | ### Changed 226 | 227 | - Update to Chrome Layer v31 (Supports Node.js 16. Uses Chromium v103) ([#27](https://github.com/stefanzweifel/sidecar-browsershot/pull/27)) 228 | - Use GitHub Actions max-parallel setting to run tests ([#29](https://github.com/stefanzweifel/sidecar-browsershot/pull/29)) 229 | 230 | ## [v1.2.1](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.2.0...v1.2.1) - 2022-07-15 231 | 232 | ### Fixed 233 | 234 | - Return Etag value from saveToS3 method ([#24](https://github.com/stefanzweifel/sidecar-browsershot/pull/24)) 235 | 236 | ## [v1.2.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.1.0...v1.2.0) - 2022-07-10 237 | 238 | ### Added 239 | 240 | - Add ability to save files directly to S3 ([#14](https://github.com/stefanzweifel/sidecar-browsershot/pull/14), [#21](https://github.com/stefanzweifel/sidecar-browsershot/pull/21)), 241 | 242 | ## [v1.1.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.0.1...v1.1.0) - 2022-05-29 243 | 244 | ### Added 245 | 246 | - Add `sidecar-browsershot` config ([#18](https://github.com/stefanzweifel/sidecar-browsershot/pull/18)) 247 | - Add support for Warming ([#18](https://github.com/stefanzweifel/sidecar-browsershot/pull/18)) 248 | 249 | ## [v1.0.1](https://github.com/stefanzweifel/sidecar-browsershot/compare/v1.0.0...v1.0.1) - 2022-04-02 250 | 251 | ## Fixed 252 | 253 | - Browsershot 3.52.4 comptability ([#12](https://github.com/stefanzweifel/sidecar-browsershot/pull/12)) 254 | 255 | ## [v1.0.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v0.2.0...v1.0.0) - 2022-03-06 256 | 257 | ## Changed 258 | 259 | - Official Support for Laravel 9 ([#7](https://github.com/stefanzweifel/sidecar-browsershot/pull/7)) 260 | 261 | ## [v0.2.0](https://github.com/stefanzweifel/sidecar-browsershot/compare/v0.1.0...v0.2.0) - 2022-03-03 262 | 263 | ## Changed 264 | 265 | - Increase maxBuffer to 100 MB ([#8](https://github.com/stefanzweifel/sidecar-browsershot/pull/8)) 266 | 267 | ## Fixed 268 | 269 | - Fix Typo in README ([#4](https://github.com/stefanzweifel/sidecar-browsershot/pull/4)) 270 | 271 | ## v0.1.0 - 2022-02-13 272 | 273 | - Initial release 274 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Stefan Zweifel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Run Browsershot on AWS Lambda with Sidecar for Laravel 2 | 3 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/wnx/sidecar-browsershot.svg?style=flat-square)](https://packagist.org/packages/wnx/sidecar-browsershot) 4 | [![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/stefanzweifel/sidecar-browsershot/run-tests.yml?label=tests&style=flat-square)](https://github.com/stefanzweifel/sidecar-browsershot/actions?query=workflow%3Arun-tests+branch%3Amain) 5 | [![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/stefanzweifel/sidecar-browsershot/laravel-pint-fixer.yml?label=code%20style&style=flat-square)](https://github.com/stefanzweifel/sidecar-browsershot/actions?query=workflow%3A%22Laravel+Pint%22+branch%3Amain) 6 | [![Total Downloads](https://img.shields.io/packagist/dt/wnx/sidecar-browsershot.svg?style=flat-square)](https://packagist.org/packages/wnx/sidecar-browsershot) 7 | 8 | This package allows you to run [Browsershot](https://github.com/spatie/browsershot) on [AWS Lambda](https://aws.amazon.com/lambda/) through [Sidecar](https://github.com/hammerstonedev/sidecar). 9 | 10 | You won't need to install Node, Puppeteer or Google Chrome on your server. The heavy lifting of booting a headless Google Chrome instance is happening on AWS Lambda. 11 | 12 | ## Requirements 13 | 14 | This package requires that [`spatie/browsershot`](https://github.com/spatie/browsershot) and [`hammerstone/sidecar`](https://github.com/hammerstonedev/sidecar) have been installed in your Laravel application. 15 | 16 | Follow their installation and configuration instructions. (You can skip the installation of puppeteer and Google Chrome for Browsershot though.) 17 | 18 | ## Installation 19 | 20 | You can install the package via composer: 21 | 22 | ```bash 23 | composer require wnx/sidecar-browsershot 24 | ``` 25 | 26 | You can publish the config file with: 27 | 28 | ```bash 29 | php artisan vendor:publish --tag="sidecar-browsershot-config" 30 | ``` 31 | 32 | Register the `BrowsershotFunction::class` in your `sidecar.php` config file. 33 | 34 | ```php 35 | /* 36 | * All of your function classes that you'd like to deploy go here. 37 | */ 38 | 'functions' => [ 39 | \Wnx\SidecarBrowsershot\Functions\BrowsershotFunction::class, 40 | ], 41 | ``` 42 | 43 | Deploy the Lambda function by running: 44 | 45 | ```shell 46 | php artisan sidecar:deploy --activate 47 | ``` 48 | 49 | See [Sidecar documentation](https://hammerstone.dev/sidecar/docs/main/functions/deploying) for details. 50 | 51 | > [!Note] 52 | > You should redeploy the Lambda function, whenever you upgrade `spatie/browsershot`. 53 | 54 | ## Usage 55 | 56 | You can use `BrowsershotLambda` like the default `Browsershot`-class coming from the Spatie package. 57 | All you need to do is replace `Browsershot` with `BrowsershotLambda`. 58 | 59 | ```php 60 | use Wnx\SidecarBrowsershot\BrowsershotLambda; 61 | 62 | // an image will be saved 63 | BrowsershotLambda::url('https://example.com')->save($pathToImage); 64 | 65 | // a pdf will be saved 66 | BrowsershotLambda::url('https://example.com')->save('example.pdf'); 67 | 68 | // save your own HTML to a PDF 69 | BrowsershotLambda::html('

Hello world!!

')->save('example.pdf'); 70 | 71 | // Get HTML of a URL and store it on a given disk 72 | $html = BrowsershotLambda::url('https://example.com')->bodyHtml(); 73 | Storage::disk('s3')->put('example.html', $html); 74 | ``` 75 | 76 | ## Warming 77 | 78 | sidecar-browsershot supports [warming](https://hammerstone.dev/sidecar/docs/main/functions/warming) for faster execution. 79 | 80 | To enable this feature set the `SIDECAR_BROWSERSHOT_WARMING_INSTANCES` variable in your `.env` to the desired number of instances Sidecar should warm for you. 81 | 82 | ```shell 83 | SIDECAR_BROWSERSHOT_WARMING_INSTANCES=5 84 | ``` 85 | 86 | Alternatively you can publish the `sidecar-browsershot.php` config file and change the `warming` setting yourself. 87 | 88 | ## Reading source from S3 89 | 90 | You can store an HTML file on AWS S3 and pass the path to Lambda for it to create the PDF or image from. 91 | This is necessary for large source files in order to avoid restrictions on the size of Lambda requests. 92 | 93 | ```php 94 | use Wnx\SidecarBrowsershot\BrowsershotLambda; 95 | 96 | // Use an HTML file from S3 to generate a PDF 97 | BrowsershotLambda::readHtmlFromS3('html/example.html')->save('example.pdf'); 98 | 99 | // You can also pass a disk name if required (default: 's3') 100 | BrowsershotLambda::readHtmlFromS3('html/example.html', 's3files')->save('example.pdf'); 101 | ``` 102 | 103 | ## Saving directly to S3 104 | 105 | You can store your file directly on AWS S3 if you want to keep it there, or to avoid the size limit on Lambda responses. 106 | 107 | You just need to pass a path and optional disk name (default: 's3') to the `saveToS3` method. 108 | - You must have an S3 disk defined in config/filesystems.php 109 | - You must give S3 write permissions to your sidecar-execution-role 110 | 111 | ```php 112 | use Wnx\SidecarBrowsershot\BrowsershotLambda; 113 | 114 | // an image will be saved on S3 115 | BrowsershotLambda::url('https://example.com')->saveToS3('example.jpg'); 116 | 117 | // a pdf will be saved on S3 118 | BrowsershotLambda::url('https://example.com')->saveToS3('example.pdf'); 119 | 120 | // save your own html to a PDF on S3 121 | BrowsershotLambda::html('

Hello world!!

')->saveToS3('example.pdf', 'example-store'); 122 | ``` 123 | 124 | ## Image Manipulation 125 | Like the original Browsershot package, you can [manipulate the image](https://spatie.be/docs/browsershot/v4/usage/creating-images#content-sizing-the-image) size and format. 126 | 127 | To perform image manipulations on the screenshot, you need to install the optional dependency `spatie/image`. v3 or higher is required. 128 | 129 | > **Note** 130 | > If you're using `fit()` in combination with `saveToS3`, the image will be downloaded from S3 to your local disc, manipulated and then uploaded back to S3. 131 | 132 | ```php 133 | // Take screenshot at 1920x1080 and scale it down to fit 200x200 134 | BrowsershotLambda::url('https://example.com') 135 | ->windowSize(1920, 1080) 136 | ->fit(\Spatie\Image\Enums\Fit::Contain, 200, 200) 137 | ->save('example.jpg'); 138 | 139 | // Take screenshot at 1920x1080 and scale it down to fit 200x200 and save it on S3 140 | // Note: To do the image manipulation, BrowsershotLambda will download the image 141 | // from S3 to the local disc of your app, manipulate it and then upload it back to S3. 142 | BrowsershotLambda::url('https://example.com') 143 | ->windowSize(1920, 1080) 144 | ->fit(\Spatie\Image\Enums\Fit::Contain, 200, 200) 145 | ->saveToS3('example.jpg'); 146 | ``` 147 | 148 | ## Register Custom Fonts 149 | 150 | By default, sidecar-browsershot includes the "Noto Color Emoji"-font, to ensure that emojis are rendered correctly. 151 | If you want to use custom fonts, you can put them all into a `resources/sidecar-browsershot/fonts`-folder. (You can customize the location of that folder in the `sidecar-browsershot.fonts` config) 152 | 153 | sidecar-browsershot will include all files in that folder when deploying the Lambda function and will register them automatically in Chromium for you. 154 | 155 | ## Testing 156 | 157 | The testsuite makes connections to AWS and runs the deployed Lambda function. In order to run the testsuite, you will need an active [AWS account](https://aws.amazon.com/). 158 | 159 | We can use the native `sidecar:configure` artisan command to create the necessary AWS credentials for Sidecar. First copy the `testbench.example.yaml` file to `testbench.yaml`. 160 | Then run `./vendor/bin/testbench sidecar:configure` to start the Sidecar setup process. (You only have to do the setup once) 161 | 162 | ```bash 163 | cp testbench.example.yaml testbench.yaml 164 | cp .env.example .env 165 | ./vendor/bin/testbench sidecar:configure 166 | ``` 167 | 168 | After finishing the Sidecar setup process, you will have received a couple of `SIDECAR_*` environment variables. Add these credentials to `.env`. 169 | 170 | Now we can deploy our local `BrowsershotFunction` to AWS Lambda. Run the following command in your terminal, before executing the testsuite. 171 | 172 | ```bash 173 | ./vendor/bin/testbench sidecar-browsershot:setup 174 | ``` 175 | 176 | After the successful deployment, you can run the testsuite. 177 | 178 | ```bash 179 | composer test 180 | ``` 181 | 182 | ## Changelog 183 | 184 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 185 | 186 | ## Contributing 187 | 188 | Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details. 189 | 190 | ## Security Vulnerabilities 191 | 192 | Please review [our security policy](../../security/policy) on how to report security vulnerabilities. 193 | 194 | ## Credits 195 | 196 | - [Stefan Zweifel](https://github.com/stefanzweifel) 197 | - [Aaron Francis](https://github.com/aarondfrancis) 198 | - [All Contributors](../../contributors) 199 | 200 | ## License 201 | 202 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 203 | -------------------------------------------------------------------------------- /bin/download-emoji-font.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DOWNLOAD_URL=https://raw.githubusercontent.com/googlefonts/noto-emoji/main/fonts/NotoColorEmoji.ttf 4 | 5 | curl -o resources/lambda/NotoColorEmoji.ttf $DOWNLOAD_URL 6 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wnx/sidecar-browsershot", 3 | "description": "A Sidecar function to run Browsershot on Lambda.", 4 | "keywords": [ 5 | "wnx", 6 | "laravel", 7 | "sidecar", 8 | "browsershot", 9 | "lambda", 10 | "sidecar-browsershot" 11 | ], 12 | "homepage": "https://github.com/stefanzweifel/sidecar-browsershot", 13 | "license": "MIT", 14 | "authors": [ 15 | { 16 | "name": "Stefan Zweifel", 17 | "email": "stefan@stefanzweifel.dev", 18 | "role": "Developer" 19 | } 20 | ], 21 | "require": { 22 | "php": "^8.2", 23 | "hammerstone/sidecar": "^0.4 || ^0.5 || ^0.6 || ^0.7", 24 | "illuminate/contracts": "^10.0 || ^11.0 || ^12.0", 25 | "spatie/browsershot": "^4.0 || ^5.0", 26 | "spatie/laravel-package-tools": "^1.9.2" 27 | }, 28 | "require-dev": { 29 | "ext-imagick": "*", 30 | "laravel/pint": "^1.13", 31 | "league/flysystem-aws-s3-v3": "^1.0|^2.0|^3.0", 32 | "nunomaduro/collision": "^7.0|^8.0", 33 | "orchestra/testbench": "^8.0|^9.0|^10.0", 34 | "pestphp/pest": "^2.0|^3.0", 35 | "pestphp/pest-plugin-laravel": "^2.0|^3.0", 36 | "phpstan/extension-installer": "^1.1", 37 | "phpstan/phpstan-deprecation-rules": "^1.0", 38 | "phpstan/phpstan-phpunit": "^1.0", 39 | "phpunit/phpunit": "^10 | ^11.0", 40 | "spatie/image": "^3.3", 41 | "spatie/pixelmatch-php": "dev-main" 42 | }, 43 | "autoload": { 44 | "psr-4": { 45 | "Wnx\\SidecarBrowsershot\\": "src", 46 | "Wnx\\SidecarBrowsershot\\Database\\Factories\\": "database/factories" 47 | } 48 | }, 49 | "autoload-dev": { 50 | "psr-4": { 51 | "Wnx\\SidecarBrowsershot\\Tests\\": "tests" 52 | } 53 | }, 54 | "scripts": { 55 | "analyse": "vendor/bin/phpstan analyse", 56 | "test": "vendor/bin/pest", 57 | "test-coverage": "vendor/bin/pest --coverage", 58 | "download-emoji-font": "sh ./bin/download-emoji-font.sh" 59 | }, 60 | "config": { 61 | "sort-packages": true, 62 | "allow-plugins": { 63 | "pestphp/pest-plugin": true, 64 | "phpstan/extension-installer": true 65 | } 66 | }, 67 | "extra": { 68 | "laravel": { 69 | "providers": [ 70 | "Wnx\\SidecarBrowsershot\\SidecarBrowsershotServiceProvider" 71 | ], 72 | "aliases": { 73 | "SidecarBrowsershot": "Wnx\\SidecarBrowsershot\\Facades\\SidecarBrowsershot" 74 | } 75 | } 76 | }, 77 | "minimum-stability": "dev", 78 | "prefer-stable": true 79 | } 80 | -------------------------------------------------------------------------------- /config/sidecar-browsershot.php: -------------------------------------------------------------------------------- 1 | env('SIDECAR_BROWSERSHOT_MEMORY', 2048), 12 | 13 | /** 14 | * The default ephemeral storage available to SidecarBrowsershot, in megabytes. (Defaults to 512MB) 15 | * 16 | * @see https://hammerstone.dev/sidecar/docs/main/functions/customization#storage 17 | */ 18 | 'storage' => env('SIDECAR_BROWSERSHOT_STORAGE', 512), 19 | 20 | /** 21 | * The default timeout to use for SidecarBrowsershot, in seconds. (Defaults to 300) 22 | * 23 | * @see https://hammerstone.dev/sidecar/docs/main/functions/customization#timeout 24 | */ 25 | 'timeout' => env('SIDECAR_BROWSERSHOT_TIMEOUT', 300), 26 | 27 | /** 28 | * Define the number of warming instances to boot. 29 | * 30 | * @see https://hammerstone.dev/sidecar/docs/main/functions/warming 31 | */ 32 | 'warming' => env('SIDECAR_BROWSERSHOT_WARMING_INSTANCES', 0), 33 | 34 | /** 35 | * AWS Layers to use by the Lambda function. 36 | * Defaults to "shelfio/chrome-aws-lambda-layer" and "sidecar-browsershot-layer" in your respective AWS region. 37 | * 38 | * If you customize this, you must include both "sidecar-browsershot-layer" and "shelfio/chrome-aws-lambda-layer" 39 | * in your list, as the config overrides the default values. 40 | * (See BrowsershotFunction@layers for more details) 41 | * 42 | * @see https://github.com/shelfio/chrome-aws-lambda-layer 43 | * @see https://github.com/stefanzweifel/sidecar-browsershot-layer 44 | */ 45 | 'layers' => [ 46 | // "arn:aws:lambda:us-east-1:821527532446:layer:sidecar-browsershot-layer:2", 47 | // "arn:aws:lambda:us-east-1:764866452798:layer:chrome-aws-lambda:42", 48 | ], 49 | 50 | /** 51 | * Path to local directory containing fonts to be installed in the Lambda function. 52 | * During deployment, BorwsershotLambda will scan this directory for 53 | * any files and will bundle them into the Lambda function. 54 | */ 55 | 'fonts' => resource_path('sidecar-browsershot/fonts'), 56 | ]; 57 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sidecar-browsershot", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "sidecar-browsershot", 9 | "version": "1.0.0", 10 | "dependencies": { 11 | "pixelmatch": "^5.3.0" 12 | } 13 | }, 14 | "node_modules/pixelmatch": { 15 | "version": "5.3.0", 16 | "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz", 17 | "integrity": "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==", 18 | "dependencies": { 19 | "pngjs": "^6.0.0" 20 | }, 21 | "bin": { 22 | "pixelmatch": "bin/pixelmatch" 23 | } 24 | }, 25 | "node_modules/pngjs": { 26 | "version": "6.0.0", 27 | "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", 28 | "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", 29 | "engines": { 30 | "node": ">=12.13.0" 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sidecar-browsershot", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "pixelmatch": "^5.3.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /resources/lambda/browsershot.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const { execSync } = require('child_process'); 3 | const chromium = require('@sparticuz/chromium'); 4 | const { S3 } = require("@aws-sdk/client-s3"); 5 | 6 | exports.handle = async function (event) { 7 | if (event.warming) { 8 | return; 9 | } 10 | 11 | // sparticuz/chromium specific settings. 12 | // https://github.com/Sparticuz/chromium#usage 13 | // Use legacy headless mode. 14 | chromium.setHeadlessMode = true; 15 | // Disable webgl. 16 | chromium.setGraphicsMode = false; 17 | 18 | // Add custom fonts to chromium. 19 | const fontsFileNames = fs.readdirSync('/var/task/fonts/'); 20 | for (const fontFileName of fontsFileNames) { 21 | await chromium.font(`/var/task/fonts/${fontFileName}`); 22 | } 23 | 24 | // Constant file where we write out options. 25 | const options = '/tmp/browsershot.js'; 26 | 27 | event.options = event.options || {}; 28 | 29 | // If there's a path, the developer is saving something to 30 | // a file. We'll write a constant path and let the PHP 31 | // side handle writing to the developer's disk. 32 | if (event.options.path) { 33 | event.options.path = '/tmp/browsershot'; 34 | } 35 | 36 | // If arbitrary HTML should be rendered, store the passed 37 | // HTML in a temporary file and use the path as the URL. 38 | if (event._html) { 39 | fs.writeFileSync('/tmp/index.html', event._html); 40 | event.url = 'file:///tmp/index.html'; 41 | } else if (event.options.s3Source) { 42 | // If the source is S3, then download the file into a temporary file to be used as the URL. 43 | const s3 = new S3({ 44 | region: event.options.s3Source.region, 45 | accessKeyId: event.options.s3Source.key, 46 | secretAccessKey: event.options.s3Source.secret, 47 | }); 48 | 49 | const params = { 50 | Bucket: event.options.s3Source.bucket, 51 | Key: event.options.s3Source.path, 52 | } 53 | 54 | const result = await s3.getObject(params); 55 | const fileContents = await streamToString(result.Body); 56 | fs.writeFileSync('/tmp/index.html', fileContents); 57 | 58 | event.url = 'file:///tmp/index.html'; 59 | } 60 | // Get the executable path from the chrome layer. 61 | event.options.executablePath = await chromium.executablePath(); 62 | 63 | // Combine the developers args with the ones from the layer. 64 | event.options.args = [ 65 | ...(event.options.args || []), 66 | ...chromium.args, 67 | ]; 68 | 69 | // Write the options to disk 70 | fs.writeFileSync(options, JSON.stringify(event)); 71 | 72 | // Exec spatie's browser command. 73 | let result = execSync(`node ./browser.cjs '-f file://${options}'`, { 74 | // Set maxBuffer to 100 MB 75 | maxBuffer: 1024 * 1024 * 100 76 | }); 77 | 78 | // Delete puppeteer profiles from temp directory to free up space 79 | fs.readdirSync('/tmp').forEach(file => { 80 | if (file.startsWith('puppeteer_dev_chrome_profile')) { 81 | fs.rmdirSync(`/tmp/${file}`, { recursive: true }); 82 | } 83 | }); 84 | 85 | // If there was a path, then read the file and return it. 86 | if (event.options.path) { 87 | let contents = fs.readFileSync(event.options.path); 88 | 89 | fs.unlinkSync(event.options.path); 90 | 91 | // If the file destination is S3, then write 92 | // the file and return the ETag as confirmation. 93 | if (event.options.s3) { 94 | const accessKeyId = event.options.s3.key; 95 | const secretAccessKey = event.options.s3.secret; 96 | const s3 = new S3({ 97 | region: event.options.s3.region, 98 | accessKeyId: event.options.s3.key, 99 | secretAccessKey: event.options.s3.secret, 100 | }); 101 | 102 | let type; 103 | 104 | switch (event.options.type) { 105 | case "png": 106 | type = 'image/png'; 107 | break; 108 | case "jpeg": 109 | type = 'image/jpeg'; 110 | break; 111 | default: 112 | type = 'application/pdf'; 113 | } 114 | 115 | const params = { 116 | Bucket: event.options.s3.bucket, 117 | Key: event.options.s3.path, 118 | Body: contents, 119 | ContentType: type, 120 | } 121 | 122 | const result = await s3.putObject(params); 123 | 124 | return result.ETag; 125 | } 126 | 127 | return new Buffer.from(contents).toString('base64'); 128 | } 129 | 130 | // Otherwise, return the string. 131 | return result.toString(); 132 | }; 133 | 134 | /** 135 | * Read a stream into a string. 136 | */ 137 | const streamToString = function(stream) { 138 | return new Promise((resolve, reject) => { 139 | const chunks = []; 140 | stream.on('data', (chunk) => chunks.push(chunk)); 141 | stream.on('error', reject); 142 | stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8'))); 143 | }); 144 | }; 145 | -------------------------------------------------------------------------------- /resources/lambda/fonts/NotoColorEmoji.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stefanzweifel/sidecar-browsershot/382b4149bad5c546b9e774a8b14d62f8d3db6e3d/resources/lambda/fonts/NotoColorEmoji.ttf -------------------------------------------------------------------------------- /src/BrowsershotLambda.php: -------------------------------------------------------------------------------- 1 | isError()) { 34 | $this->throwError($response); 35 | } 36 | 37 | // If the response is not valid JSON, it's probably a base64 encoded string representing a binary file. 38 | // In this case, we will return the base64 decoded string. 39 | if (json_decode($response->body(), true) === null) { 40 | $result = base64_decode($response->body()); 41 | } else { 42 | $result = $response->body(); 43 | 44 | // If the response is valid JSON, we can cast it to a Chromium Result. 45 | // It will contain the result and additional information about the Chromium process. 46 | if (is_array($chromiumResult = json_decode($response->body(), true))) { 47 | $this->chromiumResult = new ChromiumResult($chromiumResult); 48 | } 49 | } 50 | 51 | $s3 = Arr::get($command, 'options.s3'); 52 | $path = Arr::get($command, 'options.path'); 53 | 54 | if ($path && ! $s3) { 55 | file_put_contents($path, $result); 56 | 57 | return $path; 58 | } 59 | 60 | // If ChromiumResult is available, return the result from there. 61 | if ($this->chromiumResult) { 62 | return $this->chromiumResult->getResult(); 63 | } 64 | 65 | // The result can now be either a base64 deocded string representing a binary file or a string representing 66 | // the ETag of a file on S3. 67 | return $result; 68 | } 69 | 70 | /** 71 | * @throws ElementNotFound 72 | */ 73 | protected function throwError(SettledResult $response): void 74 | { 75 | $message = $response->errorAsString(); 76 | 77 | if (Str::contains($message, 'Error: No node found for selector')) { 78 | $selector = Str::after($message, 'Error: No node found for selector: '); 79 | $selector = head(explode("\n", $selector)); 80 | 81 | throw new ElementNotFound($selector); 82 | } 83 | 84 | $response->throw(2); 85 | } 86 | 87 | /** 88 | * @throws CouldNotTakeBrowsershot 89 | */ 90 | public function saveToS3(string $targetPath, string $disk = 's3'): string 91 | { 92 | $this->setOption('s3', [ 93 | 'path' => $targetPath, 94 | 'region' => config('sidecar.aws_region'), 95 | 'bucket' => config("filesystems.disks.$disk.bucket"), 96 | ]); 97 | 98 | $extension = strtolower(pathinfo($targetPath, PATHINFO_EXTENSION)); 99 | 100 | if ($extension === '') { 101 | throw CouldNotTakeBrowsershot::outputFileDidNotHaveAnExtension($targetPath); 102 | } 103 | 104 | $command = $extension === 'pdf' 105 | ? $this->createPdfCommand($targetPath) 106 | : $this->createScreenshotCommand($targetPath); 107 | 108 | $output = $this->callBrowser($command); 109 | 110 | if (empty($output)) { 111 | throw CouldNotTakeBrowsershot::chromeOutputEmpty("$targetPath on S3 disk: $disk", $output, $command); 112 | } 113 | 114 | if (! $this->imageManipulations->isEmpty()) { 115 | $this->applyManipulationsOnS3($targetPath, $disk); 116 | } 117 | 118 | return $output; 119 | } 120 | 121 | public function applyManipulationsOnS3(string $imagePath, string $disk = 's3'): void 122 | { 123 | // Download the image from S3 to a temporary file and apply the manipulations. 124 | /** @var string $fileContent */ 125 | $fileContent = Storage::disk($disk)->get($imagePath); 126 | Storage::disk('local')->put($imagePath, $fileContent); 127 | 128 | $localPath = Storage::disk('local')->path($imagePath); 129 | 130 | $this->imageManipulations->apply($localPath); 131 | 132 | // Upload the manipulated image back to S3 and delete the temporary file. 133 | /** @var string $fileContent */ 134 | $fileContent = Storage::disk('local')->get($imagePath); 135 | Storage::disk($disk)->put($imagePath, $fileContent); 136 | Storage::disk('local')->delete($imagePath); 137 | } 138 | 139 | /** 140 | * Tell BrowsershotLambda to load HTML from a file that is stored in S3. 141 | */ 142 | public static function readHtmlFromS3(string $sourcePath, string $disk = 's3'): self 143 | { 144 | return (new BrowsershotLambda) 145 | ->setOption('s3Source', [ 146 | 'path' => $sourcePath, 147 | 'region' => config('sidecar.aws_region'), 148 | 'bucket' => config("filesystems.disks.$disk.bucket"), 149 | ]); 150 | } 151 | 152 | public function base64pdf(): string 153 | { 154 | $command = $this->createPdfCommand(); 155 | 156 | return rtrim($this->callBrowser($command)); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/Commands/InternalBrowsershotSetupCommand.php: -------------------------------------------------------------------------------- 1 | set('sidecar.functions', [BrowsershotFunction::class]); 23 | config()->set('sidecar.env', 'testing'); 24 | config()->set('sidecar.aws_key', env('SIDECAR_ACCESS_KEY_ID')); 25 | config()->set('sidecar.aws_secret', env('SIDECAR_SECRET_ACCESS_KEY')); 26 | config()->set('sidecar.aws_region', $region); 27 | config()->set('sidecar.aws_bucket', $bucket); 28 | config()->set('sidecar.execution_role', env('SIDECAR_EXECUTION_ROLE')); 29 | 30 | $deploy = $this->confirm("Deploy Lambda function to {$region} and bucket {$bucket}?", true); 31 | $this->info("Deploying Lambda function to {$region} and bucket {$bucket}."); 32 | 33 | if (! $deploy) { 34 | $this->info('Nothing deployed.'); 35 | 36 | return self::SUCCESS; 37 | } 38 | 39 | $this->info('Deploy function …'); 40 | 41 | $exitCode = $this->call(Deploy::class, [ 42 | '--activate' => true, 43 | '--env' => 'testing', 44 | ]); 45 | 46 | if ($exitCode !== self::SUCCESS) { 47 | $this->error('Deploy command failed'); 48 | 49 | return self::FAILURE; 50 | } 51 | 52 | $this->comment('All done'); 53 | 54 | return self::SUCCESS; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Functions/BrowsershotFunction.php: -------------------------------------------------------------------------------- 1 | includeStrings([ 27 | 'browser.cjs' => $this->modifiedBrowserJs(), 28 | ]) 29 | ->includeExactly([ 30 | __DIR__.'/../../resources/lambda/browsershot.js' => 'browsershot.js', 31 | ]) 32 | ->includeExactly($this->customFonts()); 33 | } 34 | 35 | protected function customFonts(): array 36 | { 37 | $fonts = collect(); 38 | $fontDirectory = Str::finish(config('sidecar-browsershot.fonts'), DIRECTORY_SEPARATOR); 39 | 40 | // Check if the custom fonts folder exists. 41 | if (file_exists($fontDirectory)) { 42 | // Loop through all files in the custom fonts folder. 43 | 44 | /** @var array $fontFiles */ 45 | $fontFiles = scandir($fontDirectory); 46 | 47 | foreach ($fontFiles as $file) { 48 | if (is_file($fontDirectory.$file)) { 49 | $fonts->prepend("fonts/$file", $fontDirectory.$file); 50 | } 51 | } 52 | } 53 | 54 | // By default, we include the NotoColorEmoji font. 55 | $fonts->prepend('fonts/NotoColorEmoji.ttf', __DIR__.'/../../resources/lambda/fonts/NotoColorEmoji.ttf'); 56 | 57 | // Ensure that we only have unique font values. 58 | return $fonts->unique()->toArray(); 59 | } 60 | 61 | /** 62 | * We get puppeteer out of the layer, which Spatie doesn't allow 63 | * for. We'll just overwrite their browser.cjs to add it. 64 | * 65 | * @return string 66 | */ 67 | protected function modifiedBrowserJs() 68 | { 69 | if (app()->environment('testing')) { 70 | /** @var string $browser */ 71 | $browser = file_get_contents('vendor/spatie/browsershot/bin/browser.cjs'); 72 | } else { 73 | /** @var string $browser */ 74 | $browser = file_get_contents(base_path('vendor/spatie/browsershot/bin/browser.cjs')); 75 | } 76 | 77 | // Remove their reference. 78 | $browser = str_replace('const puppet = (pup || require(\'puppeteer\'));', '', $browser); 79 | 80 | // Use pupeteer-core instead. 81 | return "const puppet = require('puppeteer-core'); \n".$browser; 82 | } 83 | 84 | /** 85 | * {@inheritDoc} 86 | */ 87 | public function runtime() 88 | { 89 | return 'nodejs20.x'; 90 | } 91 | 92 | /** 93 | * {@inheritDoc} 94 | */ 95 | public function memory() 96 | { 97 | return config('sidecar-browsershot.memory'); 98 | } 99 | 100 | /** 101 | * {@inheritDoc} 102 | */ 103 | public function storage() 104 | { 105 | // Defaults to the main sidecar config value if the sidecar-browsershot config hasn't been updated to include this new key. 106 | return config('sidecar-browsershot.storage', parent::storage()); 107 | } 108 | 109 | /** 110 | * {@inheritDoc} 111 | */ 112 | public function timeout() 113 | { 114 | // Defaults to the main sidecar config value if the sidecar-browsershot config hasn't been updated to include this new key. 115 | return config('sidecar-browsershot.timeout', parent::timeout()); 116 | } 117 | 118 | /** 119 | * {@inheritDoc} 120 | */ 121 | public function architecture() 122 | { 123 | return Architecture::X86_64; 124 | } 125 | 126 | /** 127 | * {@inheritDoc} 128 | */ 129 | public function warmingConfig() 130 | { 131 | return WarmingConfig::instances(config('sidecar-browsershot.warming')); 132 | } 133 | 134 | public function layers() 135 | { 136 | if ($layers = config('sidecar-browsershot.layers')) { 137 | return $layers; 138 | } 139 | 140 | $region = config('sidecar.aws_region'); 141 | 142 | if ($region === 'ap-northeast-2') { 143 | $chromeAwsLambdaVersion = 49; 144 | } else { 145 | $chromeAwsLambdaVersion = 50; 146 | } 147 | 148 | // Add Layers that each contain `puppeteer-core` and `@sparticuz/chromium` 149 | // https://github.com/stefanzweifel/sidecar-browsershot-layer 150 | // https://github.com/shelfio/chrome-aws-lambda-layer 151 | return [ 152 | "arn:aws:lambda:{$region}:821527532446:layer:sidecar-browsershot-layer:2", 153 | "arn:aws:lambda:{$region}:764866452798:layer:chrome-aws-lambda:{$chromeAwsLambdaVersion}", 154 | ]; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/SidecarBrowsershotServiceProvider.php: -------------------------------------------------------------------------------- 1 | name('sidecar-browsershot') 20 | ->hasConfigFile() 21 | ->hasCommand(InternalBrowsershotSetupCommand::class); 22 | } 23 | 24 | public function bootingPackage(): void 25 | { 26 | // Make default fonts publishable for package consumers 27 | $this->publishes([ 28 | __DIR__.'/../resources/lambda/fonts' => config('sidecar-browsershot.fonts'), 29 | ], 'sidecar-browsershot-fonts'); 30 | } 31 | } 32 | --------------------------------------------------------------------------------