首页 > 解决方案 > 使用 express.static 时如何在 aws lambda 和 aws sam 中不返回 json

问题描述

我正在使用 aws lambda 和 aws 的 sma cli 工具制作一个无服务器网站(主要是为了测试向 api 发出真实请求)。我想使用 express.static 函数提供资产,但有问题。当我使用它时,我收到一个关于它不返回 json 的错误,错误说它需要这样做才能工作。我现在有 2 个功能:视图(提供 ejs 文件)和资产(提供静态文件,如 css 和前端 js)。这是我的template.yml:

# This is the SAM template that represents the architecture of your serverless application
# https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-basics.html

# The AWSTemplateFormatVersion identifies the capabilities of the template
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/format-version-structure.html
AWSTemplateFormatVersion: 2010-09-09
Description: >-
  [Description goes here]

# Transform section specifies one or more macros that AWS CloudFormation uses to process your template
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-section-structure.html
Transform:
- AWS::Serverless-2016-10-31

# Resources declares the AWS resources that you want to include in the stack
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html
Resources:
  assets:
    Type: AWS::Serverless::Function
    Properties:
      Handler: amplify/backend/function/assets/src/index.handler
      Runtime: nodejs14.x
      MemorySize: 512
      Timeout: 100
      Description: serves the assets
      Events:
        Api:
          Type: Api
          Properties:
            Path: /assets/{folder}/{file}
            Method: GET
  views:
    Type: AWS::Serverless::Function
    Properties:
      Handler: amplify/backend/function/views/src/index.handler
      Runtime: nodejs14.x
      MemorySize: 512
      Timeout: 100
      Description: serves the views
      Events:
        Api:
          Type: Api
          Properties:
            Path: /
            Method: GET

Outputs:
  WebEndpoint:
    Description: "API Gateway endpoint URL for Prod stage"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"

还有我的资产函数代码:index.js:

const awsServerlessExpress = require('aws-serverless-express');
const app = require('./app');

const server = awsServerlessExpress.createServer(app);

exports.handler = (event, context) => {
  console.log(`EVENT: ${JSON.stringify(event)}`);
  return awsServerlessExpress.proxy(server, event, context, 'PROMISE').promise;
};

应用程序.js:

const express = require('express'),

    app = express()
app.use(express.json())
app.use('/assets', express.static('assets'))

app.listen(3000);

module.exports = app

是否有一些我应该知道的 template.yml 配置选项或者我必须更改我的代码?

标签: amazon-web-servicesexpressaws-lambdaserverless

解决方案


我在 node js 中使用 fs 制作了自己的解决方案。我在视图函数中做了一个简单的代码,如下所示:

app.get('/assets/*', (req, res) => {
    if (!fs.existsSync(__dirname + `/${req.url}`)) {
        res.sendStatus(404).send(`CANNOT GET ${req.url}`);
        return;
    }
    res.send(fs.readFileSync(__dirname + `/${req.url}`, 'utf-8'));
})

我还编辑了 template.yml 以使其路径为 /assets/{folder}/{file} 的 api 用于视图函数,并删除了 assets 函数并将包含所有资产的 assets 文件夹移动到 views 函数目录

编辑:对于某些 resson 的几乎所有内容,内容类型 http 标头始终设置为 text/html,但是将代码更改为此可以修复它:

app.get('/assets/*', (req, res) => {
    if (!fs.existsSync(`${__dirname}${req.url}`)) {
        res.sendStatus(404).send(`CANNOT GET ${req.url}`);
        return;
    }
    res.contentType(path.basename(req.url))
    res.send(fs.readFileSync(__dirname + `${req.url}`, 'utf-8'));
})

所有这些都是在 res 对象上使用 contentType 函数。您只需传入文件名,它就会自动找到正确的内容类型。


推荐阅读