You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Serverless部署Node.js API到AWS API Gateway后出现内部服务器错误

Node.js Serverless部署AWS后Internal Server Error问题排查

问题场景

本地运行正常的Node.js S3文件上传应用,通过Serverless框架部署到AWS后,调用接口时返回Internal server error,疑似权限或配置问题导致。

用户提供的配置与代码

serverless.yml

service: nodejss3uploader

frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs16.x
  memorySize: 2048
  stage: prod
  timeout: 15
  region: us-east-1
  iam:
    role:
      statements:
        # Allow functions to list all buckets
        - Effect: Allow
          Action: 's3:ListBucket'
          Resource: '*'
        # Allow functions to read/write objects in a bucket
        - Effect: Allow
          Action:
            - 's3:GetObject'
            - 's3:PutObject'
          Resource:
            - 'arn:aws:s3:::bucket-assets/*'

functions:
  uploadtoS3:
    handler: handler.uploadtoS3
    events:
      - http: 
          path: upload/aws
          method: POST
    environment:
      AWS_ACCESS_ID: 123654123654123
      AWS_SKEY: awesomeawskeypackage
      AWS_S3_BUCKET: bucket-assets

handler.js

'use strict';
const app = require('./bin/www');
const serverless = require('serverless-http');
module.exports.handler = serverless(app);

www.js

var app = require('../app');
var debug = require('debug')('fileuploader:server');
var http = require('http');

var port = normalizePort(process.env.PORT || '80');
app.set('port', port);

var server = http.createServer(app);

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

修复方案

1. 删除硬编码的AWS密钥

Serverless部署的Lambda会自动关联配置的IAM角色权限,无需在环境变量中硬编码AWS_ACCESS_ID和AWS_SKEY,这不仅会导致权限验证异常,还存在密钥泄露的安全风险。直接移除这两个环境变量:

# 从environment中删除以下两行
# AWS_ACCESS_ID: 123654123654123
# AWS_SKEY: awesomeawskeypackage

2. 修正Lambda与Express的集成逻辑

www.js中启动HTTP服务器的逻辑在Lambda环境中完全多余,会和Serverless的请求转发机制冲突。调整handler.js,直接引用根目录的Express应用:

'use strict';
const app = require('./app'); // 直接导入Express应用
const serverless = require('serverless-http');
module.exports.uploadtoS3 = serverless(app); // 导出的函数名需与serverless.yml中handler配置一致

可以保留www.js用于本地开发,但Lambda部署时不再需要调用它。

3. 优化S3 IAM权限配置

现有权限中s3:ListBucket使用通配符*不够规范,建议指定具体桶资源;如果上传时需要设置文件ACL或元数据,需补充对应权限:

iam:
  role:
    statements:
      - Effect: Allow
        Action: 's3:ListBucket'
        Resource: 'arn:aws:s3:::bucket-assets' # 明确指定目标桶
      - Effect: Allow
        Action:
          - 's3:GetObject'
          - 's3:PutObject'
          - 's3:PutObjectAcl' # 若需设置文件访问权限,添加此动作
        Resource: 'arn:aws:s3:::bucket-assets/*'

4. 查看Lambda日志定位具体错误

登录AWS控制台,进入Lambda服务找到uploadtoS3函数,在监控->日志中查看完整错误堆栈,这是定位这类问题最直接的方式,能明确是权限不足、代码错误还是其他配置问题。

内容的提问来源于stack exchange,提问作者Santosh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:25:15