Я создал простое приложение, которое принимает URL и преобразует его в PDF. Он сохраняет результирующий PDF-файл в контейнере S3 и возвращает URL-адрес PDF-файла. Он использует Chrome (работает без заголовка) для преобразования URL в PDF. Я использовал серверный фреймворк AWS Lambda и пакет chrome - aws -lambda npm. Когда я выполняю эту настройку локально, используя сервер, все это прекрасно работает. Я могу использовать почтальон, чтобы сделать запрос с URL, и он возвращает URL результирующего PDF. Когда я развертываю эту настройку на AWS Lambda, она возвращает 502 ответ внутренней ошибки сервера. Когда я просматриваю журналы AWS для своего приложения, я вижу следующее:
{
"errorType": "Error",
"errorMessage": "ENOENT: no such file or directory, open '//../bin/chromium.br'",
"code": "ENOENT",
"errno": -2,
"syscall": "open",
"path": "//../bin/chromium.br",
"stack": [
"Error: ENOENT: no such file or directory, open '//../bin/chromium.br'"
]
}
Вот основной обработчик приложения:
import AWS from 'aws-sdk'
import middy from 'middy'
import chromium from 'chrome-aws-lambda'
import {
cors,
doNotWaitForEmptyEventLoop,
httpHeaderNormalizer,
httpErrorHandler
} from 'middy/middlewares'
const handler = async (event) => {
// Request body is passed in as a JSON encoded string in 'event.body'
const data = JSON.parse(event.body)
const executablePath = event.isOffline
? './node_modules/puppeteer/.local-chromium/linux-706915/chrome-linux/chrome'
: await chromium.executablePath
const browser = await chromium.puppeteer.launch({
args: chromium.args,
defaultViewport: chromium.defaultViewport,
executablePath: executablePath,
headless: true
})
const page = await browser.newPage()
await page.goto(data.url, {
waitUntil: ['networkidle0', 'load', 'domcontentloaded']
})
const pdfStream = await page.pdf()
var upload = new AWS.S3.ManagedUpload({
params: {
Bucket: 'bucketname',
Body: pdfStream,
Key: `${Date.now()}-result.pdf`,
ACL: 'public-read'
}
})
var promise = upload.promise()
return promise.then(
function (data) {
console.log(data.Location)
return {
statusCode: 200,
body: data.Location
}
},
function (err) {
console.log('Error', err)
return {
statusCode: 500,
body: err
}
}
)
}
export const generate = middy(handler)
.use(httpHeaderNormalizer())
.use(cors())
.use(doNotWaitForEmptyEventLoop())
.use(httpErrorHandler())
Вот конфигурация фреймворка без сервера file:
service: print-pdf
package:
individually: true
provider:
name: aws
runtime: nodejs12.x
region: us-east-2
stage: prod
plugins:
- serverless-bundle # Package our functions with Webpack
- serverless-offline
# Create our resources with separate CloudFormation templates
resources:
# API Gateway Errors
- ${file(resources/api-gateway-errors.yml)}
# S3
- ${file(resources/s3-bucket.yml)}
# 'iamRoleStatements' defines the permission policy for the Lambda function.
# In this case Lambda functions are granted with permissions to access S3.
iamRoleStatements:
- Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
Resource: "arn:aws:s3:us-east-2:*:*"
functions:
give-me-the-pdf:
handler: handler.generate
events:
- http:
path: pdf
method: post
cors: true
authorizer: aws_iam
Вот пакет. json:
{
"name": "print-pdf",
"version": "1.0.0",
"main": "handler.js",
"author": "Dean Andreakis <dean@deanware.com>",
"license": "MIT",
"private": true,
"scripts": {
"test": "serverless-bundle test"
},
"dependencies": {
"chrome-aws-lambda": "^1.20.4",
"middy": "^0.28.4",
"puppeteer-core": "^1.20.0"
},
"devDependencies": {
"aws-sdk": "^2.597.0",
"jest": "^24.9.0",
"puppeteer": "^2.0.0",
"serverless": ">=1.48.1",
"serverless-bundle": "^1.2.5",
"serverless-dotenv-plugin": "^2.1.1",
"serverless-offline": "^5.3.3"
}
}
Почему Chrome не найден при развертывании в AWS вместо локального запуска?