在 Node.js 应用程序中调用 notFoundHandler() 后,GraphQL 路径无法访问

问题描述 投票:0回答:1

我在将 GraphQL 集成到 Node.js 应用程序中时遇到问题。 最初一切正常,但添加 notFoundHandler() 后,位于 localhost:3000/graphql 的 GraphQL 端点不再可访问。

这是我对这个问题的理解:

  • GraphQL 的 server.start() 函数是异步的。
  • 应用程序的构造函数不能是异步的。
  • 这会导致 notFoundHandler() 在 app.use('/graphql', cors(), expressMiddleware(server)); 之前应用。
  • 因此,对 /graphql 的请求被错误地路由到 notFoundHandler()。

我正在寻求有效解决这一冲突的解决方案。

我的申请具体细节:

  • Node.js 版本:20.10.0
  • GraphQL 库:@apollo/server
  • 服务器框架:Express

我考虑了潜在的方法:

  • 在 app.use('/graphql',cors(),expressMiddleware(server)); 之后调用 setGraphQL 方法中的 notFoundHandler(app)

我愿意接受以下方面的任何建议或见解:

  • 在构造函数约束内启动 GraphQL 服务器的替代方法。
  • 在此场景中处理异步操作和中间件顺序的最佳实践。
  • 潜在的配置调整或特定于库的解决方法。

任何指导将不胜感激!

为了更清晰地了解代码结构,我分享以下摘录:

package.json

{
  "name": "gql4",
  "version": "1.0.0",
  "description": "",
  "main": "www.mjs",
  "scripts": {
    "start": "nodemon www.mjs"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@apollo/server": "^4.10.0",
    "cors": "^2.8.5",
    "express": "^4.18.2",
    "nodemon": "^3.0.2"
  }
}

www.mjs

import {Application} from './app.mjs'
new Application();

schema.js

const {GraphQLObjectType,GraphQLSchema, GraphQLInt, GraphQLString} = require('graphql');

const RootQuery = new GraphQLObjectType({
  name: 'RootQuery',
  fields: {
    blogs : {
        type : new GraphQLObjectType({
            name: "blogsType",
            fields : {
                id: {type: GraphQLInt},
                title: {type: GraphQLString},
                text: {type: GraphQLString}
            }
        }),
        resolve: ()=>{
            return {
                id: 1,
                title: "title of blog",
                text: 'text of blog',
            }
        }
      }
    }
});


const graphQlSchema = new GraphQLSchema({
  query: RootQuery
});


module.exports = {
  graphQlSchema
};

notFound.handler.js

module.exports = function notFoundHandler(app){
    app.use((req,res,next)=>{
        res.status(404).json({
            message: "Not Found Route"
        })
    })
}

app.mjs

import express from 'express';
import cors from 'cors';
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import notFoundHandler from './notFound.handler.js';
import  {graphQlSchema} from './schema.js';

const app = express();


class Application{
    constructor(){
        this.setExpress();
        this.setConfigs();
        this.setRoutes();
        this.setGraphQL();
        notFoundHandler(app);
    }

    setExpress(){
        const PORT = 3020;
        app.listen(PORT,()=>console.log(`Server is running on port ${PORT}`));
    }

    setConfigs(){
        app.use(express.json());
        app.use(express.urlencoded({extended:true}))
        app.use(cors())
    }

    setRoutes(){
        app.get('/',(req,res)=>res.json("Welcome"))
    }

    async setGraphQL(){
        const server = new ApolloServer({
            schema: graphQlSchema
        })

        await server.start();
        app.use('/graphql',cors(),expressMiddleware(server));
    }
 }
export { Application }

作为第一个解决方案,我在 app.use('/graphql',cors(),expressMiddleware(server)); 之后调用 setGraphQL 方法中的 notFoundHandler(app)

效果很好,但我认为这不是最佳实践。

async setGraphQL(){
        const server = new ApolloServer({
            schema: graphQlSchema
        })

        await server.start();
        app.use('/graphql',cors(),expressMiddleware(server));
        notFoundHandler(app);
    }
node.js express async-await graphql apollo-server
1个回答
0
投票

几小时后,我找到了另外两种方法来解决这个问题。

第一个解决方案:

app.mjs

constructor(){
    this.setExpress();
    this.setConfigs();
    this.setRoutes();        
    (async()=>{
        await this.setGraphQL();
        this.setErrorHandler(app);
    })()
}

(async()=>{...})():它使用箭头函数语法 (()=>{}) 定义匿名异步函数。通过在末尾添加 () 即可立即调用该函数。

await this.setGraphQL();:在匿名异步函数内部,它等待当前对象(this)上名为 setGraphQL() 的方法完成。此方法可能为服务器设置 GraphQL 功能。

this.setErrorHandler(app);:在匿名异步函数中,setGraphQL() 完成后,它会在当前对象(this)上调用名为 setErrorHandler() 的方法并传递一个 app 参数。此方法可能会为服务器设置一个错误处理程序。

第二种解决方案:

在第二个解决方案中,我修改了 notFoundHandler() 函数。

notFound.handler.js

module.exports = function notFoundHandler(app){
app.use((req,res,next)=>{
    if(req.path == '/graphql'){
        next();
    }else{
        res.status(404).json({
            message: "Not Found Route"
        })
    }
})

}

notFoundHandler()中有一个if语句:if (req.path == '/graphql') { ... }。这将检查请求的路径是否等于“/graphql”。

如果 if 语句中的条件为 true,则调用 next() 函数。该函数用于将控制权传递给应用程序请求响应周期中的下一个中间件函数。

如果 if 语句中的条件为 false,则执行 else 块。

在 else 块中,res.status(404) 用于将 HTTP 响应状态代码设置为 404(未找到)。

© www.soinside.com 2019 - 2024. All rights reserved.