Nginx и Websockets

В Nginx наконец добавили долгожданную функциональность по про- ксированию Websockets.
В связи с этим спешу поделиться конфигами и небольшими подробностями. Для тех кто не знал, ранее проксирование было возможно через сторонний модуль, с ограничениями которые многих не устраивали. Теперь на одном порту можно проксировать http и ws траффик, более того, например под одним SSL сертификатом, и все это с родным знакомым синтаксисом. Ws доступны начиная с версии 1.3.13, а буквально сегодня добавили поддержку еще в модули ngx_http_uwsgi_module и ngx_http_scgi_module для 1.3.14

Вот, что говорит документация на счет используемого механизма.

Для превращения соединения между клиентом и сервером из HTTP/1.1 в WebSocket используется доступный в HTTP/1.1 механизм смены протокола.

Но есть сложность: поскольку “Upgrade” является hop-by-hop заголовком, то он не передаётся от клиента к проксируемому серверу. При прямом проксировании клиенты могут использовать метод CONNECT, чтобы обойти эту проблему. Однако при обратном проксировании такой подход не работает, так как клиент ничего о проксирующем сервере не знает, и требуется специальная обработка на проксирующем сервере.

Начиная с версии 1.3.13, в nginx предусмотрен особый режим работы, который позволяет установить туннель между клиентом и проксируемым сервером, если проксируемый сервер вернул ответ с кодом 101 (Switching Protocols), и клиент попросил сменить протокол с помощью заголовка “Upgrade” в запросе.

Как уже отмечалось выше, hop-by-hop заголовки, включая “Upgrade” и “Connection”, не передаются от клиента к проксируемому серверу, поэтому, для того чтобы проксируемый сервер узнал о намерении клиента сменить протокол на WebSocket, эти заголовки следует передать явно:

Конфиг

Простой пример:

location /ws/ {
    proxy_pass http://localhost:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

}




Более сложный пример, в котором значение поля “Connection” в заголовке запроса к проксируемому серверу зависит от наличия поля “Upgrade” в заголовке запроса клиента:

http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        ...

        location /ws/ {
            proxy_pass http://localhost:8080;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }


И немного неочевидный, но важный параметр это proxy_read_timeout, который стоит по дефолту в значении 60s, по истечении которых коннект обрывается, чего в случае ws обычно совсем не нужно.

Поэтому, мы добавили:

http {
      ...
      proxy_read_timeout 950s;
      ...
}



Скорее всего вашему приложению нужны будут другие цифры таймаута, поэтому не копипастите бездумно;)

UPD:

На официальном сайте есть руководство.
И не забываем читать документацию по директивам:




Скопипастил с Habrahabr




Вас также может заинтересовать:

Nginx с Виндой и ... (или установка Nginx под Windows в качестве сервиса)
Уязвимость в nginx — nginx security advisory (CVE-2013-4547)
Nginx + CentOS 5.5 + aio
Релиз nginx 1.0.0
Nginx нашёл инвесторов на $3 млн.
Анонсирован выпуск Nginx 0.9