簡體   English   中英

Netlify 上的 Expressjs Lambda function 根據每個請求創建新的 session

[英]Expressjs on Netlify Lambda function creates new session on every request

晚上好,當我在本地運行我的 Expressjs API 而不使用 lambda 函數時,一切正常,但是一旦我引入 lambda function,它就會根據每個請求創建一個新的 session。 下面是我的server.jsDashboard.js ,它們顯示了我是如何撥打電話的。

本地和本地之間的區別,但 lambda 是 lambda function 即 ExpressAPI 在localhost:9000上運行,而 React 客戶端在localhost:3000上運行,但是當我使用 ExpressAPI 也為我的 React 應用程序提供服務時,一切都在localhost:8080

NetlifyServer.js

 'use-strict'; const express = require('express'); var expressSession = require('express-session'); const cors = require('cors'); const path = require('path'); const app = express(); const axios = require('axios'); const mongoose = require('mongoose'); //const MongoStore = require('connect-mongo'); const rateLimit = require("express-rate-limit"); const serverless = require('serverless-http'); require('dotenv').config() process.env.SILENCE_EMPTY_LAMBDA_WARNING = true // Middleware const saveLoggedInUserMiddleware = require('../Middleware/SaveLoggedInUserMiddleware'); const hostValidationMiddleware = require('../Middleware/HostValidationMiddleware'); const sessionValidationMiddleware = require('../Middleware/SessionValidationMiddleware'); const updateUserDataMiddleware = require('../Middleware/UpdateUserDataMiddleware'); //Routers const StoreInvoiceRouter = require('../Routes/Store-Update-Invoices'); const UserInvoicesRouter = require('../Routes/GetUserInvoices'); const UpdateUserProfileRouter = require('../Routes/UpdateUserProfile'); async function connectToDB() { // Database await mongoose.connect(process.env.mongo_url, { useNewUrlParser: true, useUnifiedTopology: true }, () => { console.log('[connectToDB]: Connected to DB'); }) } connectToDB(); // Implemented a rate limiter which is a TEMPORARY FIX for the infinite loop by the useEffect const limiter = rateLimit({ windowMs: .1 * 60 * 1000, // 10 seconds limit max: 4 }); // Creating the session in order to save user data to req.session app.use( expressSession({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, }) ); app.use('/.netlify/functions/NetlifyServer/fetchUserInvoices', limiter); app.use(express.json()); app.use(cors()); app.use('/.netlify/functions/NetlifyServer/', hostValidationMiddleware, sessionValidationMiddleware, StoreInvoiceRouter); app.use('/.netlify/functions/NetlifyServer/', saveLoggedInUserMiddleware, UserInvoicesRouter); app.use('/.netlify/functions/NetlifyServer/', updateUserDataMiddleware, UpdateUserProfileRouter); // Function makes call to endpoint that runs deletion login, this allows the client to only have to be refreshed once to // render changes on the frontend. async function updateDBCall() { const url = `${process.env.REACT_APP_STORE_INVOICES}`; const axiosConfig = { method: 'get', url }; await axios(axiosConfig).catch((e) => {console.log(e)}); console.log('[updateDBCall]: Executed call to STORE_INVOICES') }; // Supporting functions updateDBCall(); app.listen(process.env.PORT || 8080, () => { console.log(`Server listening on 8080`); }); module.exports.handler = serverless(app);

儀表板.js

 import React, {useEffect, useState} from "react"; import { useAuth0 } from "@auth0/auth0-react"; import axios from 'axios'; import LogRocket from 'logrocket'; // @material-ui/core import { makeStyles } from "@material-ui/core/styles"; import Icon from "@material-ui/core/Icon"; import Button from '@material-ui/core/Button'; // core components import GridItem from "components/Grid/GridItem.js"; import GridContainer from "components/Grid/GridContainer.js"; import Card from "components/Card/Card.js"; import CardHeader from "components/Card/CardHeader.js"; import CardIcon from "components/Card/CardIcon.js"; import CardFooter from "components/Card/CardFooter.js"; import Snackbar from "components/Snackbar/Snackbar.js"; import StorageIcon from '@material-ui/icons/Storage'; import MessageIcon from '@material-ui/icons/Message'; import styles from "assets/jss/material-dashboard-react/views/dashboardStyle.js"; export default function Dashboard() { // Abstracted Authentication variables const { user, isAuthenticated, isLoading,} = useAuth0(); // Initilizing the state as an empty array because response is an object that is an array of objects var [data, setData] = useState([]); const [loggedInUser, setLoggedInUser] = useState({}); // Positioning State for notification const [tc, setTC] = useState(true); const [bl, setBL] = useState(true); // Styling const useStyles = makeStyles(styles); const classes = useStyles(); // Time Conversions const moment = require('moment'); moment().format(); const showNotification = (place) => { switch (place) { case "bl": if (bl) { setTimeout(function() { setBL(false); }, 2000); } break; default: break; } }; async function fetchUserInvoices() { // Making a call to external api await fetch(`${process.env.REACT_APP_FETCH_USER_INVOICES}`,).then(async (res) => { // Saving response to the invoiceResponse variable const invoiceResponse = await res.json(); // Updating state to contain our object which is an array of objects setData(invoiceResponse); console.log('[fetchUserInvoices:', invoiceResponse); }).catch(err => err); } // send user data to a test endpoint in the backend (WORKS) async function sendLoggedInUser(info) { try { // Example is a POST call to API const url = `${process.env.REACT_APP_SAVE_USER}`; const axiosConfig = { method: 'post', url, data: info }; await axios(axiosConfig).catch((e) => {console.log(e)}); console.log('[sendLoggedInUser]: LoggedInUser sent to server'); } catch (error) { console.log('[sendLoggedInUser]: An Error has Occured', error) } } async function updateDB() { try { // Below is a GET Call to API const url = `${process.env.REACT_APP_STORE_INVOICES}`; const axiosConfig = { method: 'get', url, }; await axios(axiosConfig).catch((e) => {console.log(e)}); } catch (error) { console.log('[updateDB]: An Error has occured', error) } } useEffect(() => { // setting the state to include the logged in user object to be sent to server. setLoggedInUser(user); }, [user]) return ( isAuthenticated && ( <div> <GridContainer> <GridItem xs={12} sm={6} md={3}> {data? invoiceData: <div>Invoices could not be retrieved at this time. PLease try to refresh or contact your Administrator.</div>} <Snackbar place="tc" color="info" icon={MessageIcon} message={`Welcome ${user.nickname} You have ${data.length} open Invoices`} open={tc} closeNotification={() => setTC(false)} close /> <Snackbar place="bl" color="success" icon={StorageIcon} message="Invoices Successfully fetched from Database." open={bl} closeNotification={() => setBL(false)} close /> </GridItem> </GridContainer> </div> ) ); }

來自express-session 文檔

警告默認的服務器端 session 存儲MemoryStore不是為生產環境設計的。

由於 Lambda 函數在臨時環境中運行,因此您將丟失 memory 中的 session 存儲。這就是它為每個請求創建一個新的 session 的原因。

您將需要為快速會話使用 持久存儲

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM