【问题标题】:increase express post body limit to proxied api增加代理 api 的快递邮件正文限制
【发布时间】:2018-11-07 18:48:56
【问题描述】:

我有一个单独的前端和后端,所有对http://frontend.com/api 的请求都被代理到后端。但是,我们允许上传的图片最大为 10mb,这受到所有请求正文中 express 的 1mb 内部限制的限制。

我有以下配置:

const express = require('express');
const consola = require('consola');
const { Nuxt, Builder } = require('nuxt');
const helmet = require('helmet');

// Express
const app = express();
const host = process.env.HOST || '127.0.0.1';
const port = process.env.PORT || 8080;

app.set('port', port);

// Import and Set Nuxt.js options
const config = require('../nuxt.config.js');

config.dev = !(process.env.NODE_ENV === 'production');

async function start() {
  // Init Nuxt.js
  const nuxt = new Nuxt(config);

  if (config.dev) {
    const builder = new Builder(nuxt);
    await builder.build();
  }

  // NOTE: Only in production mode
  if (!config.dev) {
    // Helmet default security + Referrer + Features
    app.use(helmet());
  }

  // Proxy /api to proper backend
  app.use('/api', proxy(process.env.API_ENDPOINT || 'http://localhost:3000'));

  // Give nuxt middleware to express
  app.use(nuxt.render);

  // Listen the server
  app.listen(port, host);
  consola.ready({
    message: `Server listening on http://${host}:${port}`,
    badge: true,
  });
}
start();

我尝试添加 body-parser,直到我发现这仅适用于非 multipart/form 类型的请求。考虑到这不是一个快速的后端,而只是用于服务 SSR(使用 nuxt),我不知道如何让它与 multer 或 busboy 之类的东西一起使用。

无需将 nginx 设置为反向代理就可以做到这一点吗?

【问题讨论】:

  • 我使用了听起来与您类似的设置,并使用 multer 并使用它设置我的上传限制。如果您想查看,我可以在答案中发布我的代码。我还没有尝试过超过 1mb 的文件,所以不能保证,但它可能会起作用。告诉我。
  • 很高兴看到一个示例,想知道您是硬编码端点还是仅将其用作解析主体的代理。
  • “受到所有请求正文中 express 的 1mb 内部限制”。但是,没有这样的事情。也许您正在使用的其他中间件之一(helmetproxy)负责施加限制。您收到的错误的堆栈跟踪可能会提供一些见解。
  • @robertklep 你是对的,我可以发誓我读到 express 在某处施加了限制,然后想一想,作为一个很难改变的默认值不会很有利可图.我能找到的唯一明确限制是 json 正文:expressjs.com/en/api.html#express.json。最后,“express-force-https”为所有代理请求设置了 1mb 的硬限制。改变这个解决了这个问题。如果你能给出答案,我很乐意接受:)。
  • @user1213904 express-force-https 也没有设置限制:)

标签: node.js express nuxt.js


【解决方案1】:

Express 本身不会对正文大小施加任何限制,因为它根本不处理请求正文。

但是,某些中间件确实施加了限制,例如 body-parserexpress-http-proxy,这就是您正在使用的。

要将限制增加到 10MB:

app.use('/api', proxy(process.env.API_ENDPOINT || 'http://localhost:3000', {
  limit: '10mb'
));

【讨论】:

    【解决方案2】:

    我的工作方式是我在一个配置文件中定义我的 api 基本 url,我在 api/init.js 文件中引用它。该文件被添加到 nuxt.config.js 中的插件中。这是那个文件:

    import axios from 'axios'
    import {baseURL} from '~/config'
    import cookies from 'js-cookie'
    import {setAuthToken, resetAuthToken} from '~/utils/auth'
    import { setUser, setCart } from '../utils/auth'
    
    axios.defaults.baseURL = baseURL
    
    const token = cookies.get('x-access-token')
    const currentUser = cookies.get('userDetails')
    const currentCart = cookies.get('userCart')
    
    if (token) {
        setAuthToken(token)
        setUser(currentUser)
        setCart(currentCart)
    } else {
        resetAuthToken()
    }
    

    后端在它自己的服务器上运行,我使用node index.js 启动它,它是我的 init.js 查找的基本 url。后端 index.js 如下所示:

    const mysql = require('mysql')
    const express = require('express')
    const bodyParser = require('body-parser')
    const config = require('./config')
    const jwt = require('jsonwebtoken')
    const bcrypt = require('bcrypt')
    const multer = require('multer')
    const auth = require('./auth')
    const files = require('./files')
    const create = require('./create')
    const get = require('./get')
    const delet = require('./delet')
    const blogFiles = require('./blogFiles')
    
    const db = mysql.createConnection(config.db)
    const app = express()
    
    app.use(bodyParser.json())
    app.use(bodyParser.urlencoded({
      extended: true
    }))
    
    app.use((req, res, next) => {
        res.header('Access-Control-Allow-Origin', '*')
        res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, OPTIONS')
        res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, x-access-token, userDetails, userCart')
        if (req.method === 'OPTIONS') {
          res.sendStatus(200)
        }
        else {
          next()
        }
    })
    
    app.use((err, req, res, next) => {
      if (err.code === 'LIMIT_FILE_TYPES') {
          res.status(422).json({ error: 'Only images are allowed'})
          return
      }
      if (err.code === 'LIMIT_FILE_SIZE') {
          res.status(422).json({ error: `Too Large. Max filesize is ${MAX_SIZE/1000}kb` })
          return
      }
    })
    
    app.use('/auth', auth({db, express, bcrypt, jwt, jwtToken: config.jwtToken}))
    app.use('/files', files({db, express, multer}))
    app.use('/blogFiles', blogFiles({db, express, multer}))
    app.use('/create', create({db, express}))
    app.use('/get', get({db, express}))
    app.use('/delet', delet({db, express}))
    
    app.get('/test', (req, res) => {
      db.query('select 1+1', (error, results) => {
        if (error) {
          return res.status(500).json({type: 'error', error})
        }
        res.json({type: 'success', message: 'Test OK', results})
      })
    })
    
    app.listen(config.port)
    console.log('App is running on port ' + config.port)
    

    files.js 处理文件上传,你可以看到 index.js 需要它。在那里,我使用 multer 来处理上传限制等。这是文件.js

    module.exports = ({db, express, multer }) => {
        const routes = express.Router()
    
        const fileFilter = function(req, file, cb) {
            const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
            if (!allowedTypes.includes(file.mimetype)) {
                const error = new Error('Wrong file type')
                error.code = 'LIMIT_FILE_TYPES'
                return cb(error, false)
            }
    
            cb(null, true)
        }
    
        const MAX_SIZE = 250000
    
        var storage = multer.diskStorage({
            destination: function (req, file, cb) {
              cb(null, '../frontend/assets/images')
            },
            filename: function (req, file, cb) {
              cb(null, file.originalname)
            }
          })
    
        const upload = multer ({
            storage: storage,
            fileFilter,
            limits: {
                fileSize: MAX_SIZE
            },
    
        })
    
        routes.post('/upload', upload.single('file'), (req, res) => {
          res.json({ file: req.file })
        })
    
        return routes
      }
    

    如您所见,我在这里为我的文件上传设置了 MAX_SIZE,所以猜测您可以设置任何限制,当 multer 正在处理它时,它将超越 express 设置的任何限制。

    【讨论】:

    • 感谢您的明确回答,但不幸的是我的后端在 Rails 中。我没有考虑将所有请求传递给frontend/api 的代理将强制执行 1mb 的硬限制。总而言之,您的答案是一个明确的未来参考。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-25
    • 2016-06-24
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    相关资源
    最近更新 更多