как настроить сервер, созданный с помощью createServer, для полного заполнения, когда он уже создан? - PullRequest
0 голосов
/ 02 февраля 2020

У меня есть этот код:

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, это работает. проблема возникает, когда я публикую sh облачную функцию 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). при этом я получаю сообщение об ошибке (проблема cors) при попытке подключиться к облачной функции url из totorotos.web.app. Как я могу настроить server для выполнения sh Cors, когда он уже создан? Любая помощь в любом смысле будет очень признательна. Спасибо.

1 Ответ

1 голос
/ 03 февраля 2020

Для включения CORS с простым nodejs http-сервером (без использования Express framework) не существует промежуточной архитектуры, которая могла бы устанавливать желаемые заголовки и затем продолжать маршрутизацию к другим обработчикам запросов, поэтому вам придется это делать В фактическом обработчике запросов.

FYI, архитектура промежуточного программного обеспечения является одним из основных преимуществ инфраструктуры Express, которая позволяет вам устанавливать политики CORs в одном месте, которое может использовать множество обработчиков запросов.

В любом случае, вот как это выглядит для простого 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();
        }
    }
});

Вот статья на общую тему c: Включение CORS в nodejs http-сервер без Express.

Обработка запроса OPTIONS - это то, что многие люди не понимают или не знают, что вставить. Для CORS это называется «предполетным» "запрос и при некоторых обстоятельствах браузер будет использовать запрос OPTIONS в качестве проверки разрешений, чтобы увидеть, разрешает ли сервер запрос перед фактической отправкой г реальная просьба. Если браузер решит это сделать, предполетный запрос также должен иметь соответствующие заголовки CORS, поскольку именно так браузер решает, разрешить запрос или нет.

Существуют различные обстоятельства, которые вызывают браузер оформить предполетный запрос. В двух словах, это любой запрос, который спецификация CORS не определяет как «простой». Вы можете прочитать больше об этом здесь . Что может сделать запрос непростым: пользовательские заголовки, кроме нескольких выбранных, любой глагол, отличный от GET, HEAD или POST, заголовок Content-Type в запросе, отличный от application/x-www-form-urlencoded, multipart/form-data или text/plain и и так далее ...

Если вам требуется, чтобы учетные данные отправлялись вместе с запросом перекрестного происхождения (например, cookie-файлы), существуют дополнительные ограничения, которые можно прочитать о здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...