对于我的全栈应用程序的后端,我使用 ApolloGraphQL 4.0 和 Express。我可以成功地使用我的解析器(TypeOrm 和 TypeGraphql)从我的数据库(PostgreSQL)写入和检索数据。 我将 express-session 与 connect-redis 包一起使用来处理会话并为我的注册解析器设置一个 cookie,但是当尝试将数据存储在会话对象中时,我收到以下关于我的会话对象的错误消息:
TypeError: Cannot read properties of undefined (reading 'session')
并且没有设置cookie。
我试过不同版本的 connect-redis 包,我试过更改不同中间件的顺序等等,但无论我做什么,我都会得到同样的错误,并且没有设置 cookie。 这是我的 index.ts:
import "reflect-metadata";
import AppDataSource from "./data-source";
import { ApolloServer } from "@apollo/server";
import { expressMiddleware } from "@apollo/server/express4";
import { ApolloServerPluginDrainHttpServer } from "@apollo/server/plugin/drainHttpServer";
import express, { Request, Response } from "express";
import http from "http";
import cors from "cors";
import { json } from "body-parser";
import { Hello } from "./resolvers/hello";
import { UserResolver } from "./resolvers/user";
import { buildSchema } from "type-graphql";
import RedisStore from "connect-redis";
import session from "express-session";
import { createClient } from "redis";
export type MyContext = {
req: Request & { session: Express.Session };
res: Response;
};
const main = async () => {
await AppDataSource.initialize();
const app = express();
app.set("trust proxy", 1);
app.set(
"Access-Control-Allow-Origin",
"https://sandbox.embed.apollographql.com"
);
app.set("Access-Control-Allow-Credentials", true);
const httpServer = http.createServer(app);
const port = 3000;
const corsOptions = {
origin: "https://sandbox.embed.apollographql.com",
credentials: true,
};
const redisClient = createClient();
redisClient.connect().catch(console.error);
const redisStore = new RedisStore({
client: redisClient,
prefix: "myapp:",
});
const apolloServer = new ApolloServer({
schema: await buildSchema({
resolvers: [Hello, UserResolver],
}),
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});
await apolloServer.start();
app.use(
session({
name: "qid",
store: redisStore,
resave: false,
saveUninitialized: false,
secret: "weotjweptoijwepitn",
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 365 * 10,
httpOnly: true,
sameSite: "none",
secure: true,
},
}),
cors(corsOptions),
json(),
expressMiddleware(apolloServer, {
context: async ({ req, res }) => ({ req, res }),
})
);
httpServer.listen(port, () => {
console.log(`Server now running on port: ${port}`);
});
};
main();
这就是我的 userResolver 在注册后让用户保持登录状态的样子:
import { Resolver, Mutation, Arg, Query, Ctx } from "type-graphql";
import User from "../entities/User";
import { MyContext } from "../index";
@Resolver()
export class UserResolver {
@Mutation(() => User)
async register(
@Arg("username") username: string,
@Arg("password") password: string,
@Arg("email") email: string,
@Ctx("req") { req }: MyContext,
): Promise<User> {
const user = await User.create({
username,
email,
password,
}).save();
try {
req.session.userId = user.id;
}
catch (error) {
console.log(error);
console.error(error);
}
return user;
}
@Query(() => [User])
async findAllUsers(): Promise<User[]> {
const Users = await User.find({
select: {
id: true,
username: true,
email: true,
},
});
return Users;
}
}