簡體   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