繁体   English   中英

如何配置使用 createServer 创建的服务器以在已创建时填充 cors?

[英]how to configure server created with createServer to fullfill cors when it is already created?

我有这个代码:

var gqlServer =require('./server.js')

var server=gqlServer()
var port = process.env.PORT||5000

server.listen({port:port}, ()=>
  console.log(`🚀 Server ready at http://localhost:${port}`)
)

server.js是:

var cors=require('cors')
const http=require('http')
const express = require('express')
const {ApolloServer,gql,PubSub} = require('apollo-server-express')
var firebase =require('firebase/app')
require('firebase/database')

// const pubsub=new PubSub()

const app = express()
var whiteList=['https://totorotos.firebaseapp.com',
'https://totorotos.web.app','http://localhost:8080']
app.use(cors({origin:whiteList}))
const httpServer=http.createServer(app)
var io = new require('socket.io')(httpServer,{
  origins:whiteList
})

const firebaseConfig = {
    apiKey: "*********",
    authDomain: "******",
    databaseURL: "********",
    projectId: "********i",
    storageBucket: "********",
    messagingSenderId: "********",
    appId: "********",
    measurementId: "********"
  }

firebase.initializeApp(firebaseConfig)
var database = firebase.database()

const typeDefs = gql`
  type Query {
    hello: String,
    getEmails:[String!]
    getPosts(email:String): [GetPosts]
  }
  type Mutation{
    postMessage(message:String,email:String!,
      name:String,photo:String,date:String!): Boolean
  }
  type GetPosts{
    email:String!
    name:String
    date:String!
    photo:String
    message:String
  }
`

const resolvers = {
  Query: {
    hello: () => 'Hello roger!',
    getEmails:async()=>{
      const result=[]
      await database.ref('posts/').orderByChild('email')
      .once('value', function(snapshot) {
        snapshot.forEach(function(childSnapshot) {
          var childKey = childSnapshot.key
          var childData = childSnapshot.val()
          result.push(childData.email)
        })
      })
      const res2= [...new Set(result)]
      return res2
    },
    getPosts:async(_,args)=>{
      const result=[]
      await database.ref('posts/').orderByChild('email').equalTo(args.email)
      .once('value', function(snapshot) {
        snapshot.forEach(function(childSnapshot) {
          var childKey = childSnapshot.key
          var childData = childSnapshot.val()
          result.push(childData)
        })
      })
      return result
    }
  },
  Mutation:{
    postMessage:async(_,args)=>
    {      
      await database.ref('posts/').push({
        message: args.message,
        email:args.email,
        name:args.name,
        photo:args.photo,
        date:args.date
      })
      io.emit('updated', {email:args.email})
    //   pubsub.publish('POST_ADDED',{name:'paquito',
    // comment:'como estas tronco?'});
      return true
    }
  },
  // Subscription: {
  //   postAdded: {
  //     subscribe: () => pubsub.asyncIterator(['POST_ADDED']),
  //     resolve: payload => {
  //       return payload
  //     }
  //   }
  // }
}

function gqlServer() {
  const server = new ApolloServer({
    typeDefs,
    resolvers,
    // Enable graphiql gui
    introspection: true,
    playground: true
  })

//   var whiteList=['https://totorotos.firebaseapp.com',
// 'https://totorotos.web.app']
  // server.applyMiddleware({app, path: '/', cors: {origin:whiteList,credentials:true}})
server.applyMiddleware({app,path:'/',cors:false})

  // server.installSubscriptionHandlers(httpServer)
  return httpServer
}

module.exports = gqlServer

这很好用。 那是当localhost:8080尝试连接到localhost:5000这是有效的。 当我用这个发布 firebase 云函数时,问题就出现了:

const functions = require('firebase-functions')
const express=require('express')
const cors=require('cors')({ origin: true })
const admin = require('firebase-admin')
const gqlServer=require('./server/index')

admin.initializeApp();
var server=gqlServer()
exports.api1=functions.https.onRequest(server)

server/index与以前相同( server.js )。 这样,当我尝试从totorotos.web.app连接到 url 云函数时出现错误(cors 问题)。 如何配置server以在已创建 cors 时完成它? 任何意义上的任何帮助都将不胜感激。 谢谢你。

对于使用普通 nodejs http 服务器(未使用 Express 框架)启用 CORS,没有可以设置所需标头然后继续路由到其他请求处理程序的中间件架构,因此您必须在实际请求处理程序中执行此操作。

仅供参考,中间件架构是 Express 框架的主要优势之一,它允许您在许多请求处理程序可以使用的一个地方设置 COR 策略。

无论如何,这是一个普通的 nodejs http 服务器传入请求的样子。

// add new listener to the http server for requests
server.on('request', (req, res) => {
    // check if this is the path we are interested in
    // if there could be query parameters, then you have to parse them off first
    if (req.url === "/somePath") {
        // If desired, set these more specifically such as only specific origins
        // or CORS only allowed on specific methods
        const headers = {
            'Access-Control-Allow-Origin': '*',     
            'Access-Control-Allow-Methods': 'OPTIONS, POST, GET',
            // add other headers as needed
        };

        // if pre-flight request, handle it here
        if (req.method === 'OPTIONS') {
            res.writeHead(204, headers);
            res.end();
            return;
        } else if (req.method === "GET") {
            res.writeHead(200, headers);
            // handle rest of the GET request here
            // ...
            res.end();
        } else {
            res.writeHead(405);
            res.end();
        }
    }
});

这是一篇关于一般主题的文章:在没有 Express 的 nodejs http 服务器中启用 CORS

处理 OPTIONS 请求是很多人不理解或不知道放入的东西。对于 CORS,这称为“预飞行”请求,在某些情况下,浏览器会将 OPTIONS 请求用作权限在实际发送真实请求之前检查服务器是否允许请求。 如果浏览器选择这样做,则预检请求还必须具有适当的 CORS 标头,因为这是浏览器决定是否允许该请求的方式。

有多种情况会导致浏览器发出飞行前请求。 简而言之,这是 CORS 规范未定义为“简单”的任何请求。 您可以在此处阅读更多相关信息。 可以使请求变得不简单的事情是:除了几个选择的自定义标头,除 GET、HEAD 或 POST 之外的任何动词,除application/x-www-form-urlencoded之外的请求的 Content-Type 标头, multipart/form-datatext/plain等等...

如果您需要使用跨源请求(例如 cookie)发送凭据,那么您可以在此处阅读更多限制。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM