简体   繁体   English

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

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

I have this code:我有这个代码:

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}`)
)

and server.js being: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

and this works fine.这很好用。 that is when localhost:8080 tries to connect to localhost:5000 this works.那是当localhost:8080尝试连接到localhost:5000这是有效的。 the problem comes when I publish the firebase cloud function with this:当我用这个发布 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)

being server/index the same as before ( server.js ). server/index与以前相同( server.js )。 with that, I get an error (cors issue) when trying to connect to the url cloud function from totorotos.web.app .这样,当我尝试从totorotos.web.app连接到 url 云函数时出现错误(cors 问题)。 how can I configure server to accomplish cors when it is already created?如何配置server以在已创建 cors 时完成它? Any help in any sense will be very appreciated.任何意义上的任何帮助都将不胜感激。 Thank you.谢谢你。

For enabling CORS with a plain nodejs http server (no Express framework being used), there is no middleware architecture that can set the desired headers and then continue routing to the other request handlers so you have to do it IN the actual request handler.对于使用普通 nodejs http 服务器(未使用 Express 框架)启用 CORS,没有可以设置所需标头然后继续路由到其他请求处理程序的中间件架构,因此您必须在实际请求处理程序中执行此操作。

FYI, the middleware architecture is one of the primary benefits of the Express framework which allows you to set CORs policies in one place that lots of request handlers can use.仅供参考,中间件架构是 Express 框架的主要优势之一,它允许您在许多请求处理程序可以使用的一个地方设置 COR 策略。

Anyway, here's what it would look like for a plain nodejs http server incoming request.无论如何,这是一个普通的 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();
        }
    }
});

Here's an article on the general topic: Enable CORS in nodejs http server without Express .这是一篇关于一般主题的文章:在没有 Express 的 nodejs http 服务器中启用 CORS

Handling the OPTIONS request is something that many people don't understand or don't know to put in. For CORS, this is called a "pre-flight" request and under some circumstances, the browser will use the OPTIONS request as a permissions check to see if the server allows the request before actually sending the real request.处理 OPTIONS 请求是很多人不理解或不知道放入的东西。对于 CORS,这称为“预飞行”请求,在某些情况下,浏览器会将 OPTIONS 请求用作权限在实际发送真实请求之前检查服务器是否允许请求。 If the browser chooses to do that, the pre-flight request must also have appropriate CORS headers as that's how the browser decides if the request is allowed or not.如果浏览器选择这样做,则预检请求还必须具有适当的 CORS 标头,因为这是浏览器决定是否允许该请求的方式。

There are a variety of circumstances that will cause the browser to issue the pre-flight request.有多种情况会导致浏览器发出飞行前请求。 In a nutshell, it's any request that the CORS specification doesn't define as "simple".简而言之,这是 CORS 规范未定义为“简单”的任何请求。 You can read more about that here .您可以在此处阅读更多相关信息。 Things that can make a request not be simple are: custom headers beyond a few select ones, any verb other than GET, HEAD or POST, Content-Type header on the request other than application/x-www-form-urlencoded , multipart/form-data or text/plain and so on...可以使请求变得不简单的事情是:除了几个选择的自定义标头,除 GET、HEAD 或 POST 之外的任何动词,除application/x-www-form-urlencoded之外的请求的 Content-Type 标头, multipart/form-datatext/plain等等...

If you require credentials be sent with the cross origin request (such as cookies), then there are further restrictions you can read about here .如果您需要使用跨源请求(例如 cookie)发送凭据,那么您可以在此处阅读更多限制。

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

相关问题 如何在http.createServer() 函数中获取创建的服务器的链接? - How to get the link of the created server in the http.createServer() function? 如何将数据发送到使用net.createServer()连接事件创建的特定套接字? - How to send data to specific sockets created using net.createServer() connection event? 创建后的骨干模型已经具有属性 - Backbone model when created already has attributes CrossUI如何重用已经创建的对话框? - CrossUI how to reuse already created dialogs? 如何检查对象是否已经创建? - How to check if an object has been already created? 如何在已创建的编辑器上设置数据? - How to set data on an already created editor? 如何使用 mongoose 为已创建的文档编写子文档 - How to write subdocuments for an already created document with mongoose 如何获取仅已创建组的列表? - How to get list of only already created groups? 使用 createServer() 时如何获取 node.js 服务器可用 IP - How to get node.js server available IPs when using createServer() 已创建 paymentintent 时如何防止在另一个选项卡中更改购物车 - How to prevent shopping cart alterations in another tab when paymentintent is already created
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM