[英]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-data
或text/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.