Общайтесь через обратный прокси-сервер Nginx, чтобы связаться со шлюзом NestJS с помощью websockets

#vue.js #nginx #websocket #nestjs

Вопрос:

Я пытаюсь использовать веб-пакеты между моим передним (VueJS) и задним (NestJS).

Оба они находятся в контейнерах, соответственно контейнер frontend и контейнер main . Оба контейнера находятся в одной сети и могут достигать друг друга (с помощью axios или curl).

Моя спина-это NestJS с базовым шлюзом как таковым:

 @WebSocketGateway()
export class ChatGateway {
  constructor(private readonly chatService: ChatService) {}
  private readonly logger = new Logger(ChatGateway.name);
  
  @SubscribeMessage('createChat')
  create(@MessageBody() createChatDto: CreateChatDto) {
    //return this.chatService.create(createChatDto);
  }

  @SubscribeMessage('findAllChat')
  findAll() {
    //return this.chatService.findAll();
  }

  @SubscribeMessage('findOneChat')
  findOne(@MessageBody() id: number) {
    //return this.chatService.findOne(id);
  }

  @SubscribeMessage('updateChat')
  update(@MessageBody() updateChatDto: UpdateChatDto) {
    //return this.chatService.update(updateChatDto.id, updateChatDto);
  }

  @SubscribeMessage('removeChat')
  remove(@MessageBody() id: number) {
    //return this.chatService.remove(id);
  }

  @SubscribeMessage('test')
  handleTest(client: Socket, data: string) {
    this.logger.debug("THIS IS A TEST. A MESSAGE HAS BEEN SUCCESSFULLY RECEIVED !");
    this.logger.debug(data);
    return '';
  }
}
 

Это базовый шлюз, созданный NestJS. единственным дополнением к нему является «тестовая» часть.

Примечание: Весь сервер прослушивает порт 3000.

Мой интерфейс работает под управлением NginX, действующего в качестве обратного прокси-сервера. Ее зовут nginx.conf:

 #user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
  worker_connections  1024;
}
http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;
  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
  access_log  /var/log/nginx/access.log  main;
  sendfile        on;
  keepalive_timeout  65;
  server {
    listen       80;
    server_name  localhost;
    location / {
    add_header 'Access-Control-Allow-Origin' '*';
      root   /usr/share/nginx/html;
      index  index.html;
      try_files $uri $uri/ /index.html;
    }

  location /api/ {
    add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;

    proxy_pass http://main:3000/;
  }
  location /chat/ {
    add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    proxy_pass http://main:3000/;
  }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   /usr/share/nginx/html;
    }
  }
}
 

Because my front and my back are on different containers, this is the best solution I found to avoid CORS issues.
The location /chat/ { part is inspired by NginX’s documentation on the subject.

Then for the front end in itself, I tried using VueSocketIO, then tried the classic socket.io.
This is the script part of one of my components.

     import io from 'socket.io-client';

    export default {
        data() {
            return {
                socket: null,
            }
        },
        methods: {
            clickButton() {
                this.socket.emit('test', "HELLO");
                console.log('CLICK');
            }
        },
        created () {
            this.socket = io('http://main:3000');
            console.log(this.socket);
        }
    }
 

This gives out different errors depending on the browser.

Chrome:

 polling-xhr.js:268 GET http://main:3000/socket.io/?EIO=3amp;transport=pollingamp;t=Ngb4oiX net::ERR_NAME_NOT_RESOLVED
 

Firefox:

 Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://main:3000/socket.io/?EIO=3amp;transport=pollingamp;t=Ngb9kXo. (Reason: CORS request did not succeed).
 

Safari: Ошибки нет, но все равно не работает

Я не знаю, почему появляется эта ошибка. ЕСЛИ кто-нибудь знает причину, по которой это не работает, я с радостью приму ее. Большое спасибо.