下面是我如何设置app.js:
/**
* Importing Packages
*/
require("dotenv").config({ path: `./env/.env-${process.env.NODE_ENV}` });
const express = require("express");
const logger = require("morgan");
const moment = require("moment");
const cors = require("cors");
const path = require("path");
const bodyParser = require('body-parser');
const app = express();
const fs = require("fs");
const { ApolloServer, gql } = require("apollo-server-express");
const { mergeGraphQLTypes, mergeResolvers } = require("@graphql-tools/merge");
const { makeExecutableSchema } = require("@graphql-tools/schema");
const { applyMiddleware } = require("graphql-middleware");
const { createServer } = require("http"); // newly added
const {
ApolloServerPluginDrainHttpServer,
ApolloServerPluginLandingPageLocalDefault } = require("apollo-server-core");
const { WebSocketServer } = require("ws");
const { useServer } = require("graphql-ws/lib/use/ws");
const graphqlUploadExpress = require("graphql-upload/graphqlUploadExpress.js");
const GraphQLUpload = require("graphql-upload/GraphQLUpload.js");
require("./database/db");
require("./helper/function");
const Stripe = require("./stripe/stripeRoute");
const Cron = require("./scheduleCron/scheduleCronRoute");
const generateFolder = Helper("generate-folder");
/* Get the Queries & Mutation type and merge them togather for the schema */
const Query = mergeGraphQLTypes(require("./queries")(gql));
/* Get the resolvers array and merge them togather for the schema */
const Resolvers = mergeResolvers(require("./resolvers"));
Resolvers.Upload = GraphQLUpload;
/* Get all the middlewares.
Note:- This we can return as array of middleware object
The object pattern are mentioned in the middleware folder index.js file */
const Middlewares = require("./middlewares");
/* For the use of middleware we must create an executable schema and pass the
query and resolvers we acquired before. */
const schema = makeExecutableSchema({ typeDefs: Query, resolvers: Resolvers });
/* Apply middlewares to the schema. */
const schemaWithMiddleware = applyMiddleware(schema, Middlewares.verifyUser);
/* Create the main Apollo Server from the schema */
// Added for Websocket Subscriptions Starts //
const httpServer = createServer(app);
// Set up WebSocket server.
const wsServer = new WebSocketServer({
//port: 8443,
server: httpServer,
path: "/",
});
const serverCleanup = useServer({schema}, wsServer);
// Added for Websocket Subscriptions Ends //
const server = new ApolloServer({
schema: schemaWithMiddleware,
context: ({ req, res }) => {
return { req, res };
},
formatError: (err) => {
// logger.info(err);
return err;
},
uploads: false,
plugins: [
// Proper shutdown for the HTTP server.
ApolloServerPluginDrainHttpServer({httpServer}),
{
async serverWillStart() {
return {
async renderLandingPage() {
const html = `<!DOCTYPE html>
<html>
<head>
<title>Welcome To TestDrive</title>
</head>
<body>
<img src="https://testdrive.co/images/api-screen.jpg" style="display: block; margin-left: auto; margin-right: auto; width:auto;">
</body>
</html>`;
return { html };
},
async drainServer() {
await serverCleanup.dispose();
},
}
}
}
]
});
/* Setting up port */
const port = process.env.PORT || 8000;
/* Generating logs */
var accessLogStream = fs.createWriteStream(
path.join(
__dirname,
`${generateFolder.generateLogFolder()}/access-${moment().format(
"YYYY-MM-DD"
)}.log`
),
{ flags: "a" }
);
// setting up the logger
app.use(logger("combined", { stream: accessLogStream }));
app.use(function (err, req, res, next) {
logger.error(
`${req.method} - ${err.message} - ${req.originalUrl} - ${req.ip}`
);
next(err);
});
/* Setting up stripe payment */
app.use(
express.json({
// We need the raw body to verify webhook signatures.
// Let's compute it only when hitting the Stripe webhook endpoint.
verify: function (req, res, buf) {
if (req.originalUrl.startsWith("/webhook")) {
req.rawBody = buf.toString();
}
},
})
);
/* Setting up graphql upload */
app.use(
graphqlUploadExpress({
maxFileSize: 30000000,
maxFiles: 20,
})
);
/* Cors Setup */
var corsOptions = {
origin: process.env.CORS_ALLOW_URL,
allowedHeaders: [
"Content-Type",
"Authorization",
"Accept",
"x-www-form-urlencoded",
"x-access-token",
],
credentials: true,
};
app.use(cors(corsOptions));
app.use(express.static("public"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(Stripe);
app.use(Cron);
/* Initiating the Apollo server */
server
.start()
.then((r) => {
/**
* The following line is require as we are using the apollo-server-express
*/
server.applyMiddleware({ app, path: "/" });
// Now that our HTTP server is fully set up, actually listen.
httpServer.listen(port, () => {
console.log(`🚀 Query endpoint ready at http://localhost:${port}${server.graphqlPath}`);
console.log(`🚀 Subscription endpoint ready at ws://localhost:${port}${server.graphqlPath}`);
});
})
.catch((err) => {
console.log("Could not start the apollo server", err);
});
这是我的nginx设置:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream sockettest.testdrive.co {
server 100.242.100.242:5555; # host and port of local running server instance
}
server {
ssl on;
listen 443 ssl http2;
server_name apistg.testdrive.co;
ssl_certificate /etc/testdrives/testcert.pem;
ssl_certificate_key /etc/testdrives/testkey.pem;
root /var/www/apistg.testdrive.co/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
location / {
proxy_pass http://100.242.100.242:5555/;
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
location /subscription { # websocket endpoint
proxy_pass http://sockettest.testdrive.co/;
# upstream url and host
proxy_redirect default;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
}
location /graphql {
proxy_pass http://100.242.100.242:5555/graphql;
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
# Secure Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "origin-when-cross-origin" always;
add_header "X-XSS-Protection" "1; mode=block";
}
WebSocket在chrome,opera等中运行良好。只有在Firefox中,我得到这个错误:-
Firefox can’t establish a connection to the server at wss://testdrive.co/subscription.
不。Firefox中并不总是发生这种情况。5次中有2次,Firefox没有显示此错误。但5次中有3次,此问题正在发生。
我怎么解决这个问题?有人说可能是fixed通过nginx中的proxy_pass(在已接受答案的评论部分)但是我不能修复它。我发现的另一个work around是在Firefox中手动访问链接http://testdrive.co/subscription并接受证书警告。但是该项目是一个SAAS应用程序。我不能't要求所有用户打开链接并接受如下证书警告:
1条答案
按热度按时间9cbw7uwe1#
请检查下面的链接。https://www.nginx.com/blog/websocket-nginx/?amp=1
如果你有一个SaaS服务,你需要激活https,http不安全,浏览器不能正常工作。
你必须检查WS和WSS是否在浏览器外正常,如果连接正常,检查浏览器和证书。
希望能帮上忙