parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

Класс websocket

moko 17.10 21:59

Во встроенный веб-сервер парсера добавлена поддержка WebSocket (RFC 6455): двусторонний канал между браузером и скриптом по одному долгому соединению.

Когда JS делает запрос по протоколу ws://, он отправляет заголовок Upgrade: websocket. Серверный код при наличии заголовка принимает соединение и работает в цикле, пока оно открыто. Один запрос на всё соединение: конфигурация и auto.p выполняются один раз, состояние можно хранить в обычных переменных. Примерный код:
@main[]
^if($env:HTTP_UPGRADE eq websocket){
        ^websocket:accept[]
        ^while(true){
                $message[^websocket:receive(30)]
                ^if($message is hash){
                        ^if($message.type eq close){^break[]}
                        $response[^answer[$message]]
                        ^websocket:send[$response]
                }
        }
}{
        ... страница с JS ...
}
Со стороны браузера:
const ws = new WebSocket('ws://' + location.host + '/');
ws.onopen = () => ws.send('привет');
ws.onmessage = (e) => console.log(e.data);
Класс websocket статический, доступные методы:
- ^websocket:accept[] - принять соединение. Поля $response:, заданные до этого, уходят вместе с заголовками websocket.
- ^websocket:receive(секунды) - ждёт сообщение не дольше таймаута. Если ничего не пришло, вернёт void, иначе hash: $.type[text|binary|close], $.data (для binary это файл) и для close ещё
поле $.code. Ping/pong и фрагментацию парсер обрабатывает сам.
- ^websocket:send[строка или файл] - строка уходит текстовым сообщением, файл бинарным.
- ^websocket:ping[], ^websocket:ping[данные].
- ^websocket:close[], ^websocket:close(код), ^websocket:close(код;причина).

Подробности:
- Текст по сети идёт в UTF-8. Строки при отправке обрабатываются как обычный вывод, в httpd по умолчанию как html, таким образом ^websocket:send[$form:name] экранирует опасные символы.
- Размер сообщения ограничен $LIMITS.post_max_size (по умолчанию 10 МБ, как у POST). Большее сообщение закрывает соединение с кодом 1009.
- Закрытая вкладка приходит как $.type[close] с кодом 1001, обрыв связи без закрытия с кодом 1006.
- После @main парсер сам корректно закрывает соединение: шлёт Close и ждёт ответ клиента не дольше $HTTPD.timeout.
- При проксировании через nginx нужно передавать заголовки Upgrade и Connection (proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";).

В тесты добавлено демонстрационное приложение, страница и серверная часть в одном файле. Запуск через run_server.sh, затем надо открыть http://localhost:8100/ в браузере. Сервер 20 раз в секунду присылает свой статус (время, CPU, память, номер сообщения). Дополнительно есть эхо, ping/pong, отправка бинарных данных и закрытие. Можно открыть несколько вкладок.

Как обычно, уже доступно в ночных сборках.