#node.js #angular #express #websocket #angular-universal
#node.js #angular #экспресс #websocket #angular-универсальный
Вопрос:
Я пытаюсь добавить веб-сокеты на сервер, который использует angular universal. Насколько я могу судить, express обрабатывает мой запрос до того, как он попадет в мои сокеты, но я могу ошибаться в этом.
Я получаю эту ошибку в Chrome: WebSocket connection to 'ws://localhost:4200/socket' failed: Connection closed before receiving a handshake response
и я получаю эту ошибку в firefox: Firefox can’t establish a connection to the server at ws://localhost:4200/socket.
когда я запускаю отдельный сервер nodejs без кода angular, websockets работают нормально.
Вот соответствующая часть моего server.ts
import 'zone.js/dist/zone-node'
import { ngExpressEngine } from '@nguniversal/express-engine'
import * as express from 'express'
import { join } from 'path'
import { AppServerModule } from './src/main.server'
import { APP_BASE_HREF } from '@angular/common'
import { existsSync } from 'fs'
import * as WebSocket from 'ws'
// The Express app is exported so that it can be used by serverless Functions.
export function app() {
const server = express()
const distFolder = join(process.cwd(), 'dist/CAHClone/browser')
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index'
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}))
server.set('view engine', 'html')
server.set('views', distFolder)
server.use(express.json())
// Serve static files from /browser
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}))
// All regular routes use the Universal engine
server.get('*', (req, res, next) => {
if (req.url === '/socket') return next() // leave '/socket' open for the websockets
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] })
})
return server
}
function run() {
const port = process.env.PORT || 4000
// Start up the Node server
const expressApp = app()
const server = expressApp.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`)
})
// Websockets
const wss = setupWebsockets(server)
}
function setupWebsockets(server) {
const wss = new WebSocket.Server({ server, path: '/socket' })
wss.on('connection', ws => {
console.log('Client connected.')
ws.send({message: 'Hi there!'})
})
wss.on('message', msg => {
console.log('Client said: ' msg.toString())
})
return wss
}
declare const __non_webpack_require__: NodeRequire
const mainModule = __non_webpack_require__.main
const moduleFilename = mainModule amp;amp; mainModule.filename || ''
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run()
}
export * from './src/main.server'
И вот server.js файл, который работает без кода, связанного с angular
const express = require('express')
const WebSocket = require('ws')
const { join } = require('path')
const { existsSync } = require('fs')
// The Express app is exported so that it can be used by serverless Functions.
function app() {
const server = express()
server.use(express.json())
server.use('*', (req, res, next) => {
if (req.url === '/socket') return next()
res.end('Hello, world!')
})
return server
}
function setupWebsockets(server) {
const wss = new WebSocket.Server({ server, path: '/socket' })
console.log('set up websocket server');
wss.on('connection', ws => {
console.log('Client connected.');
ws.send('Hi there!')
})
wss.on('message', msg => {
console.log('Client said: ' msg.toString());
})
}
function run() {
const port = process.env.PORT || 4000
const expressApp = app()
const server = expressApp.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`)
})
// Websockets
const wsServer = setupWebsockets(server)
}
run()
Может ли кто-нибудь помочь мне понять, какая часть angular universal нарушает мои websockets и как это исправить?
Комментарии:
1. Вы пытаетесь подключиться к порту 4200.. но ваши серверы, похоже, работают на 4000 ..?
2. @MikeOne Спасибо, но я не думаю, что это проблема, angular, похоже, устанавливает для process.port.env значение 4200 при запуске
npm run dev:srr
. Я внимательно посмотрю на порты, чтобы увидеть, есть ли там что-то не так. Для сервера JS я намеренно использую 4000, и я подключаюсь к нему при тестировании.3. Проблема на самом деле, похоже, связана с портом. Angular использует то, что кажется случайным портом, а также 4200, и веб-сокеты работают на этом случайном порту, но не на 4200. Я продолжу расследование, но если у кого-нибудь есть дополнительная информация о том, как это работает, пожалуйста, дайте мне знать.
4. Обновление: это работает нормально, если я запускаю
npm run build:ssr
, за которым следуетnpm run serve:ssr
, проблема, похоже, связана со средой разработки, настроенной сnpm run dev:ssr
Ответ №1:
Я столкнулся с этой проблемой с модулем ‘ws’ и передачей на экспресс-сервер. Попробуйте создать свой сервер с помощью модуля «http» и передать его как в express, так и в «ws». Я также рекомендую позаботиться о любой авторизации, которую вы собираетесь выполнить в случае «обновления», если это необходимо.