GithubHelp home page GithubHelp logo

lua-resty-websocket's Introduction

Name

OpenResty - Turning Nginx into a Full-Fledged Scriptable Web Platform

Table of Contents

Description

OpenResty is a full-fledged web application server by bundling the standard nginx core, lots of 3rd-party nginx modules, as well as most of their external dependencies.

This bundle is maintained by Yichun Zhang (agentzh).

Because most of the nginx modules are developed by the bundle maintainers, it can ensure that all these modules are played well together.

The bundled software components are copyrighted by the respective copyright holders.

The homepage for this project is on openresty.org.

For Users

Visit the download page on the openresty.org web site to download the latest bundle tarball, and follow the installation instructions in the installation page.

For Bundle Maintainers

The bundle's source is at the following git repository:

https://github.com/openresty/openresty

To reproduce the bundle tarball, just do

make

at the top of the bundle source tree.

Please note that you may need to install some extra dependencies, like perl, dos2unix, and mercurial. On Fedora 22, for example, installing the dependencies is as simple as running the following commands:

sudo dnf install perl dos2unix mercurial

Back to TOC

Additional Features

In additional to the standard nginx core features, this bundle also supports the following:

Back to TOC

resolv.conf parsing

syntax: resolver address ... [valid=time] [ipv6=on|off] [local=on|off|path]

default: -

context: http, stream, server, location

Similar to the resolver directive in standard nginx core with additional support for parsing additional resolvers from the resolv.conf file format.

When local=on, the standard path of /etc/resolv.conf will be used. You may also specify arbitrary path to be used for parsing, for example: local=/tmp/test.conf.

When local=off, parsing will be disabled (this is the default).

This feature is not available on Windows platforms.

Back to TOC

Mailing List

You're very welcome to join the English OpenResty mailing list hosted on Google Groups:

https://groups.google.com/group/openresty-en

The Chinese mailing list is here:

https://groups.google.com/group/openresty

Back to TOC

Report Bugs

You're very welcome to report issues on GitHub:

https://github.com/openresty/openresty/issues

Back to TOC

Copyright & License

The bundle itself is licensed under the 2-clause BSD license.

Copyright (c) 2011-2019, Yichun "agentzh" Zhang (章亦春) [email protected], OpenResty Inc.

This module is licensed under the terms of the BSD license.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Back to TOC

lua-resty-websocket's People

Contributors

add-sp avatar agentzh avatar bungle avatar chenyyyang avatar chipitsine avatar chronolaw avatar edwardbetts avatar fingerliu avatar gerrard-ynwa avatar gszr avatar jprjr avatar spacewander avatar spk avatar thibaultcha avatar xiaocang avatar zhuizhuhaomeng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lua-resty-websocket's Issues

server example

I think in your server example you are writing err from send_close instead of the err from recv_frame in ngx.log(ngx.INFO ....)

How to use client as a proxy?

Hi, I want to use nginx as as wescoket proxy, so I could hold the connection by nginx while my backend server restarting.

I wrote listen to a new port 8080, and newed a resty.websocket.client to connection my backend server, which listens to port 80.
our Api requests use http Authentication header to verify user, how could I proxy the whole header using the resty.websocket.client while connecting? how could I save the websocket requests while backend restarting, then reconnect to backend?

I am a newer for lua-resty-websocket. could you give me some help or docs?
Thx

[idea] support HTTP connection reuse

Maybe we can reuse an HTTP connection to establish a WebSocket client?

A direct implementation may be to allow users to pass sock(ngx.socket.tcp) as an argument:

function _M.new(self, opts, sock_reuse)
    local sock, err
    if sock_reuse == nil then
        sock, err= tcp()
    else
        sock = sock_reuse
    end
    if not sock then
        return nil, err
    end

    local max_payload_len, send_unmasked, timeout
    if opts then
        max_payload_len = opts.max_payload_len
        send_unmasked = opts.send_unmasked
        timeout = opts.timeout

        if timeout then
            sock:settimeout(timeout)
        end
    end

    return setmetatable({
        sock = sock,
        max_payload_len = max_payload_len or 65535,
        send_unmasked = send_unmasked,
    }, mt)
end

and then we may do this:

local httpc = require("resty.http").new()
-- some requests
-- ...
local wsock = require("resty.websock.client"):new(nil, httpc.sock)
-- and we shall not use httpc after here

(The code is for demonstration. It should be organized in a better way)

websocket 上下游 触发nginx coredump

现在遇到一个openresty coredump的案列,使用场景是作为一个websocket的服务。

使用openresty 作为现有TCP服务器的一个 websocket 接入层

0:openresty的版本 1.11.23
1:客户端到收到客户端的websocket请求,升级协议
2:鉴权成功,连接到后端TCP server。标记 socket1
3:主循环A,阻塞在 ws_recv_loop 函数.不断接收数据,json_decode之后,转化为二进制数据,发送到 socket1
4: 升级协议的同时使用,ngx.thread.spawn 开启新的轻线程B,,从 socket1 读取数据【 recvFromIMServer阻塞在read函数,】
5:读取socket1的数据,读取proto解析为json 下发给 websocket.

大致代码如下

local function im_recv_loop(userid,chatServer)
   ngx.log(ngx.CRIT,'create thread ,userid: ',userid)
   while true do
   	local pack,err	=	chatServer:recvFromIMServer( userid )
   	if not pack then
   		ngx.log(ngx.ERR,userid,',recv bad pack skip : ',err) 
   		break
   	end

   		local bytes, err	 =	chatServer:sendToClient(pack)
   		if not bytes then
   			ngx.log(ngx.ERR, "failed to send text: ", err) 
   			break
   		end

   end
   ngx.log(ngx.ERR,userid,',wb closing sock')
   chatServer:close()
   -- chatServer close 内部 关闭 上游的tcp ,同时关闭
end


local function ws_recv_loop(wb,userid,token)


   	local chatServer	=	chatServer:new(userid,wb)
   	  
   	local ret 			=	chatServer:startLogin(token,userid)
   	
   	if not ret then 
   		chatServer:close()
   		return 
   	end

   	local push_thread 	=	ngx_thread_spawn(im_recv_loop,userid,chatServer)
   	
   	-- 作为收报的时间处理 
   	local _type,_err 		=	''
   	while true do
                                local data, typ, err = wb:recv_frame()
                               if wb.fatal then
   		             _type	=	'fatal'
                                   ngx.log(ngx.ERR, userid," failed to receive frame: ", err)
                                  break
                             end
   		  
   		local timeout 	=	false
   		if ( err and  sub(err,-7) =='timeout') then
   			timeout	=	true
   		end

   		if not err or timeout==false  then
   		  ngx.log(ngx.CRIT,typ,',userid: ',userid, ",data: ", data,',err: ',err)
   		end
   		 _type	=	typ
   		 -- 持续收报
   		 if timeout==true then 
   		 end

   		  if typ == "close" then
   			ngx.log(ngx.ERR,userid,',',typ, ",data:", data,',err:',err)
   			break
   		  elseif typ == "text" then
   			 
   			chatServer:recvFromClient(data)

   			elseif typ == 'ping' then
   				local bytes, err = wb:send_pong('')

   			elseif typ == 'pong' then

   			elseif typ == 'continuation' then
   			elseif typ == 'binary' then

   		  end

     end
     
   	ngx.log(ngx.CRIT,userid,',typ:',_type,',logout')
   	chatServer:close()  
   	
   	-- chatServer close 之后,会在内部标记 wb_closed,
   	-- 是的 chatServer  recvFromIMServer 返回nil,终止 im_recv_loop线程。
   	ngx.thread.wait(push_thread) 

end

若干coredump如下,每一次coredump产生的地方不固定,但是基本上  lj_alloc_free 这个函数,有时候还是 json_decode导致的。情况比较特殊

#0 0x00007f40cf42ce19 in lj_alloc_free (msp=0x40b71010, ptr=) at lj_alloc.c:1404
#1 0x00007f40cf3e3c27 in gc_sweep (g=0x40b713b8, p=0x4036ddc0, lim=37) at lj_gc.c:406
#2 0x00007f40cf3e48d4 in gc_onestep (L=0x419275b8) at lj_gc.c:637
#3 0x00007f40cf3e4f28 in lj_gc_step (L=0x419275b8) at lj_gc.c:689
#4 0x00007f40cf3e91a3 in lj_meta_cat (L=0x419275b8, top=, left=0) at lj_meta.c:304
#5 0x00007f40cf3e0bfc in lj_BC_CAT () from /usr/local/openresty/luajit/lib/libluajit-5.1.so.2
#6 0x00000000004c6ac0 in ngx_http_lua_run_thread (L=0x40b71378, r=0x13ce630, ctx=0x13cf9d0, nrets=0) at ../ngx_lua-0.10.8/src/ngx_http_lua_util.c:1005
#7 0x00000000004c84dc in ngx_http_lua_content_by_chunk (L=0x40b71378, r=0x13ce630) at ../ngx_lua-0.10.8/src/ngx_http_lua_contentby.c:120
#8 0x00000000004c8884 in ngx_http_lua_content_handler_file (r=0x13ce630) at ../ngx_lua-0.10.8/src/ngx_http_lua_contentby.c:284
#9 0x00000000004c898e in ngx_http_lua_content_handler (r=0x13ce630) at ../ngx_lua-0.10.8/src/ngx_http_lua_contentby.c:222
#10 0x000000000044fe40 in ngx_http_core_content_phase (r=0x13ce630, ph=) at src/http/ngx_http_core_module.c:1379
#11 0x000000000044a12d in ngx_http_core_run_phases (r=0x13ce630) at src/http/ngx_http_core_module.c:856
#12 0x0000000000454d61 in ngx_http_process_request (r=0x13ce630) at src/http/ngx_http_request.c:1916
#13 0x0000000000455a1c in ngx_http_process_request_line (rev=0x13ef9f0) at src/http/ngx_http_request.c:1027
#14 0x0000000000438a02 in ngx_event_process_posted (cycle=, posted=0x7603d0) at src/event/ngx_event_posted.c:33
#15 0x000000000043ed48 in ngx_worker_process_cycle (cycle=0x1326040, data=) at src/os/unix/ngx_process_cycle.c:753
#16 0x000000000043d387 in ngx_spawn_process (cycle=0x1326040, proc=0x43ed10 <ngx_worker_process_cycle>, data=0xb, name=0x4fe415 "worker process", respawn=-4)
at src/os/unix/ngx_process.c:198
#17 0x000000000043e24c in ngx_start_worker_processes (cycle=0x1326040, n=32, type=-4) at src/os/unix/ngx_process_cycle.c:358
#18 0x000000000043f5ac in ngx_master_process_cycle (cycle=0x1326040) at src/os/unix/ngx_process_cycle.c:243
#19 0x000000000041cb1f in main (argc=, argv=) at src/core/nginx.c:36



#0 gc_sweep (g=0x40b713b8, p=0x40c082a8, lim=37) at lj_gc.c:395
#1 0x00007f40cf3e48d4 in gc_onestep (L=0x407f50e0) at lj_gc.c:637
#2 0x00007f40cf3e4f28 in lj_gc_step (L=0x407f50e0) at lj_gc.c:689
#3 0x00007f40cf3f1aa3 in lua_pushlstring (L=0x407f50e0, str=, len=) at lj_api.c:577
#4 0x00007f40bd9d21a2 in json_parse_object_context (l=0x407f50e0, json=0x7fff16db2540, token=) at lua_cjson.c:1208
#5 json_process_value (l=0x407f50e0, json=0x7fff16db2540, token=) at lua_cjson.c:1288
#6 0x00007f40bd9d2374 in json_parse_array_context (l=0x407f50e0, json=0x7fff16db2540, token=) at lua_cjson.c:1256
#7 json_process_value (l=0x407f50e0, json=0x7fff16db2540, token=) at lua_cjson.c:1291
#8 0x00007f40bd9d220b in json_parse_object_context (l=0x407f50e0, json=0x7fff16db2540, token=) at lua_cjson.c:1216
#9 json_process_value (l=0x407f50e0, json=0x7fff16db2540, token=) at lua_cjson.c:1288
#10 0x00007f40bd9d2374 in json_parse_array_context (l=0x407f50e0, json=0x7fff16db2540, token=) at lua_cjson.c:1256
#11 json_process_value (l=0x407f50e0, json=0x7fff16db2540, token=) at lua_cjson.c:1291
#12 0x00007f40bd9d220b in json_parse_object_context (l=0x407f50e0, json=0x7fff16db2540, token=) at lua_cjson.c:1216
#13 json_process_value (l=0x407f50e0, json=0x7fff16db2540, token=) at lua_cjson.c:1288
#14 0x00007f40bd9d2530 in json_decode (l=0x407f50e0) at lua_cjson.c:1330
#15 0x00007f40cf3e1bba in lj_BC_FUNCC () from /usr/local/openresty/luajit/lib/libluajit-5.1.so.2
#16 0x00000000004c6ac0 in ngx_http_lua_run_thread (L=0x40b71378, r=0x146d980, ctx=0x146ed20, nrets=0) at ../ngx_lua-0.10.8/src/ngx_http_lua_util.c:1005
#17 0x00000000004c84dc in ngx_http_lua_content_by_chunk (L=0x40b71378, r=0x146d980) at ../ngx_lua-0.10.8/src/ngx_http_lua_contentby.c:120
#18 0x00000000004c8884 in ngx_http_lua_content_handler_file (r=0x146d980) at ../ngx_lua-0.10.8/src/ngx_http_lua_contentby.c:284
#19 0x00000000004c898e in ngx_http_lua_content_handler (r=0x146d980) at ../ngx_lua-0.10.8/src/ngx_http_lua_contentby.c:222
#20 0x000000000044fe40 in ngx_http_core_content_phase (r=0x146d980, ph=) at src/http/ngx_http_core_module.c:1379
#21 0x000000000044a12d in ngx_http_core_run_phases (r=0x146d980) at src/http/ngx_http_core_module.c:856
#22 0x0000000000454d61 in ngx_http_process_request (r=0x146d980) at src/http/ngx_http_request.c:1916
#23 0x0000000000455a1c in ngx_http_process_request_line (rev=0x13ef8d0) at src/http/ngx_http_request.c:1027
#24 0x00000000004409e5 in ngx_epoll_process_events (cycle=, timer=, flags=) at src/event/modules/ngx_epoll_module.c:900
#25 0x0000000000438765 in ngx_process_events_and_timers (cycle=0x1326040) at src/event/ngx_event.c:242
#26 0x000000000043ed48 in ngx_worker_process_cycle (cycle=0x1326040, data=) at src/os/unix/ngx_process_cycle.c:753
#27 0x000000000043d387 in ngx_spawn_process (cycle=0x1326040, proc=0x43ed10 <ngx_worker_process_cycle>, data=0xa, name=0x4fe415 "worker process", respawn=-4)
at src/os/unix/ngx_process.c:198
#28 0x000000000043e24c in ngx_start_worker_processes (cycle=0x1326040, n=32, type=-4) at src/os/unix/ngx_process_cycle.c:358
#29 0x000000000043f5ac in ngx_master_process_cycle (cycle=0x1326040) at src/os/unix/ngx_process_cycle.c:243
#30 0x000000000041cb1f in main (argc=, argv=) at src/core/nginx.c:367


#0 gc_sweep (g=0x40b713b8, p=0x40921ea8, lim=0) at lj_gc.c:395
#1 0x00007f40cf3e48d4 in gc_onestep (L=0x402ebe58) at lj_gc.c:637
#2 0x00007f40cf3e4f28 in lj_gc_step (L=0x402ebe58) at lj_gc.c:689
#3 0x00007f40cf3f210c in lua_newuserdata (L=0x402ebe58, size=) at lj_api.c:684
#4 0x00000000004b35e2 in ngx_http_lua_var_get (L=0x402ebe58) at ../ngx_lua-0.10.8/src/ngx_http_lua_variable.c:113
#5 0x00007f40cf3e1bba in lj_BC_FUNCC () from /usr/local/openresty/luajit/lib/libluajit-5.1.so.2
#6 0x00000000004c6ac0 in ngx_http_lua_run_thread (L=0x40b71378, r=0x13e3410, ctx=0x13e47b0, nrets=0) at ../ngx_lua-0.10.8/src/ngx_http_lua_util.c:1005
#7 0x00000000004c84dc in ngx_http_lua_content_by_chunk (L=0x40b71378, r=0x13e3410) at ../ngx_lua-0.10.8/src/ngx_http_lua_contentby.c:120
#8 0x00000000004c8884 in ngx_http_lua_content_handler_file (r=0x13e3410) at ../ngx_lua-0.10.8/src/ngx_http_lua_contentby.c:284
#9 0x00000000004c898e in ngx_http_lua_content_handler (r=0x13e3410) at ../ngx_lua-0.10.8/src/ngx_http_lua_contentby.c:222
#10 0x000000000044fe40 in ngx_http_core_content_phase (r=0x13e3410, ph=) at src/http/ngx_http_core_module.c:1379
#11 0x000000000044a12d in ngx_http_core_run_phases (r=0x13e3410) at src/http/ngx_http_core_module.c:856
#12 0x0000000000454d61 in ngx_http_process_request (r=0x13e3410) at src/http/ngx_http_request.c:1916
#13 0x0000000000455a1c in ngx_http_process_request_line (rev=0x13efe70) at src/http/ngx_http_request.c:1027
#14 0x0000000000438a02 in ngx_event_process_posted (cycle=, posted=0x7603d0) at src/event/ngx_event_posted.c:33
#15 0x000000000043ed48 in ngx_worker_process_cycle (cycle=0x1326040, data=) at src/os/unix/ngx_process_cycle.c:753
#16 0x000000000043d387 in ngx_spawn_process (cycle=0x1326040, proc=0x43ed10 <ngx_worker_process_cycle>, data=0x10, name=0x4fe415 "worker process", respawn=49)
at src/os/unix/ngx_process.c:198
#17 0x000000000043f99a in ngx_reap_children (cycle=0x1326040) at src/os/unix/ngx_process_cycle.c:621
#18 ngx_master_process_cycle (cycle=0x1326040) at src/os/unix/ngx_process_cycle.c:174
#19 0x000000000041cb1f in main (argc=, argv=) at src/core/nginx.c:367

webscoekt建立连接后收到后端返回的数据帧被截断,只有32k

基于openresty搭建一个简易网关,通过websocket从网关后台(springboot工程)拉取配置数据,即openresty这里的websocket为客户端;
下面是openresty websocket的部分伪代码逻辑:
local config = {
max_payload_len=1024000,
url="ws://..."
}
local client = require "resty.websocket.client"
local wb, err = client:new({
max_payload_len = config.max_payload_len,
send_unmasked = false,
timeout = 300000
})
local ok, err = wb:connect(config.url)
local data, typ, err = wb:recv_frame()
ngx.log(ngx.ERR, "receive type: ".. typ .. ", data len:" .. string.len(data))

下面是日志的打印(data的长度只有32768):

2021/02/18 15:30:46 [error] 13054#0: *9 [lua] ws_client.lua:116: receive type: text, data len:32768, context: ngx.timer

因为数据帧的数据不完全,导致了问题;
用java模拟websocket client,从上述的网关后台可以拉取到完整的数据,排除后台的问题。

目前不知道,除了max_payload_len,openresty还有哪里可以限制这个帧的大小~

How to decode websocket frame ?

I wanna decode the frames and wait for a special frame, after decoding and analyzing this frame, I will disconnect it or let it pass. But this module just recv the frame and never put it back, so it can be a websocket server, but can't be a proxy for websocket.

Any idea to make it a proxy for websocket?

use websocket client to sync data in local redis before nginx is accessible

Hello,

Im not sure if that's possible but before I look at openresty / LUA scripting, within my microservice (nodejs), I had a websocket client that was connecting to a remote server to sync up data into redis before the service was accessible.

Those data are relative to the authentication of the users, routes, certificates and should be available before the service is up.

Can I do the same thing directly on nginx level using LUA ( and lua-resty-weboscket / lua-resty-redis ) ? As websocket and redis are not usuable in the init_* block, Im wondering how I could proceed.

Thanks

Errors in use with lua-resty-http

local serverHostPath = "test.target.domain/v1.0/test"      //step1
local httpUrl = "http://" .. serverHostPath
local wsUrl = "ws://" .. serverHostPath
local params = {
      headers = {
          -- ["Connection"] = "close",    // step2
      },
      body = "some data",
      method = "POST"
}
local http = require('resty.http')
local httpc, errmsg = http.new()
local response, errmsg = httpc:request_uri(httpUrl, params)

local websocketClient = require('resty.websocket.client')
local wb, err = websocketClient:new()
local ok, err = wb:connect(wsUrl)
wb:send_text("data")
wb:send_binary("data")
wb:send_binary()

while true do
    local data, typ, err = wb:recv_frame()      // step3
    if not data then
        return
    end
end

Hello,

My implement looks like above. Firstly, i will use lua-resty-http to request path in http protocol, then, i will use lua-resty-websocket to request same path in websocket protocol.
At step3, i will get an error "failed recv frame, err:bad RSV1, RSV2, or RSV3 bits". in step1, if i use ip:port but not domain host, it works well, or in step2, use "Connection: close" option, it also works well.

failed to send frame: failed to send frame: operation now in progress

I do not know if it is my usage is wrong. Occasionally there will be such a mistake. when I restart openresty, it will ok. restart openresty again, it will still happen.
this is my code:

local i = 0
while true do
    ngx.say(i)
    local bytes, err = wb:send_text("ping mmm")
    ngx.say("send msg:", bytes)
    if not bytes then
        ngx.say("failed to send frame: ", err)
        return
    end
    local bytes, err = wb:send_ping()
    ngx.say("send ping:", bytes)
    if not bytes then
        ngx.say("failed to send frame: ", err)
        return
    end
    local bytes, err = wb:send_pong()
    ngx.say("send pong:", bytes)
    if not bytes then
        ngx.say("failed to send frame: ", err)
        return
    end

    local data, typ, err = wb:recv_frame()
    if not data then
        ngx.say("failed to receive the frame: ", err)
        return
    end
    ngx.say("received: ", data, " (", typ, "): ", err)
    i = i + 1
    ngx.sleep(2)
end

when use curl localhost:8888,

0
send msg:14
send ping:6
send pong:6
received:  (ping): nil
1
send msg:14
send ping:6
send pong:6
received: hello (text): nil
2
send msg:14
send ping:6
send pong:6
received:  (ping): nil
3
send msg:nil
failed to send frame: failed to send frame: operation now in progress
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact

or

0
send msg:14
send ping:6
send pong:6
received:  (ping): nil
1
send msg:14
send ping:6
send pong:6
received: hello (text): nil
2
send msg:14
send ping:6
send pong:nil
failed to send frame: failed to send frame: protocol wrong type for socket
* Curl_http_done: called premature == 0

how to access websocket clients / handles from websocket server?

I am new to using websockets with openresty so I apologize if it is documented somewhere but I can't find it and have been trying for several hours unsuccessfully.

is there a way to get and loop through the websocket server handles for each client?

When a new client connects to the server, is there a way to store the socket handle to send a message directly to that socket, or disconnect the socket, etc? I thought I could just store the object in a shared dict but that is for text only and it fails when trying to json encode it:

local json=require("cjson.safe");
local cache=ngx.shared.cache;
local server = require "resty.websocket.server"
local wb, err = server:new{
timeout = 5000,
max_payload_len = 65535
}

local ok,err=json.encode(wb);
if not ok then trace("JSON ERR> " , err);
end;

trace(): JSON ERR> ,*5 lua entry thread aborted: runtime error: /usr/local/openresty/lualib/resty/core/shdict.lua:186: attempt to compare string with number

So how can I save/store the websocket client handle to access it directly?

Http链接重复利用给websocket时的错误

websocekt/client.lua

local count, err = sock:getreusedtimes()
if not count then
return nil, "failed to get reused times: " .. err
end
if count > 0 then
-- being a reused connection (must have done handshake)
return 1
end

-- do the websocket handshake:

当一个http链接关闭之后,如果这个http链接,被websocket链接从链接池里面取出来时,则这个链接的reusedtimes时大于0的,然后这个链接不会被handshake。

lj_str_new

hello

I use lua-resty-websocket as server. when we do performance test, we found lj_str_new use too much cpu by 'perf top'.
so we use stap to collect the cpu useage, and found 'lj_str_new ' use too much cpu in 'resty.websocket.protocol.recv_frame' function.

I check the latest version, it use ffi_string. we try the latest version, the cpu issuse is still exist.
Can we do any improvement ?

How to delivery the websocket across request?

I want to find all the current connect sock to the websocket server, and send response to them.(a chatting room.) I Save the socks to module table in every request. When I use the saved socks to send response,I found that the socks already closed.How Can I do , I Know the cosocket has the same
lifetime as the request.How can I shared sock across request.

Tests are failing on ppc64le

Can you please help to give more details on the below errors for test failures.
Trying to run this module on ppc64le.

t/count.t ... 1/18 WARNING: TEST 1: module size of resty.websocket.protocol - 2019/10/03 13:04:48 [warn] 15632#0: *1 [lua] _G write guard:12: __newindex(): writing a global lua variable ('n') which may lead to race conditions between concurrent requests, so prefer the use of 'local' variables
WARNING: TEST 2: module size of resty.websocket.client - 2019/10/03 13:04:48 [warn] 15648#0: *1 [lua] _G write guard:12: __newindex(): writing a global lua variable ('n') which may lead to race conditions between concurrent requests, so prefer the use of 'local' variables
t/count.t ... 13/18 WARNING: TEST 3: module size of resty.websocket.server - 2019/10/03 13:04:50 [warn] 15792#0: *1 [lua] _G write guard:12: __newindex(): writing a global lua variable ('n') which may lead to race conditions between concurrent requests, so prefer the use of 'local' variables
t/count.t ... ok
t/cs.t ...... 1/236
Failed test 'TEST 15: text frame (send masked frames on the server side) - pattern "recv_frame: mask bit: 1" should match a line in error.log (req 0)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 15: text frame (send masked frames on the server side) - pattern "recv_frame: mask bit: 1" should match a line in error.log (req 1)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.
t/cs.t ...... 13/236
Failed test 'TEST 18: directly calling close() without sending the close frame ourselves - pattern "sending the close frame" should match a line in error.log (req 0)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 18: directly calling close() without sending the close frame ourselves - pattern "sending the close frame" should match a line in error.log (req 1)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.
t/cs.t ...... 35/236
Failed test 'TEST 13: reused upstream websocket connections (set_keepalive) - pattern "recv_frame: mask bit: 0" should match a line in error.log (req 0)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 13: reused upstream websocket connections (set_keepalive) - pattern "recv_frame: mask bit: 1" should match a line in error.log (req 0)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 13: reused upstream websocket connections (set_keepalive) - pattern "recv_frame: mask bit: 0" should match a line in error.log (req 1)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 13: reused upstream websocket connections (set_keepalive) - pattern "recv_frame: mask bit: 1" should match a line in error.log (req 1)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.
t/cs.t ...... 73/236
Failed test 'TEST 17: close frame (without msg body) + close() - pattern "sending the close frame" should match a line in error.log (req 0)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 17: close frame (without msg body) + close() - pattern "sending the close frame" should match a line in error.log (req 1)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 1: text frame - pattern "recv_frame: mask bit: 0" should match a line in error.log (req 0)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 1: text frame - pattern "recv_frame: mask bit: 1" should match a line in error.log (req 0)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 1: text frame - pattern "recv_frame: mask bit: 0" should match a line in error.log (req 1)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 1: text frame - pattern "recv_frame: mask bit: 1" should match a line in error.log (req 1)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.
t/cs.t ...... 120/236
Failed test 'TEST 14: pool option - pattern "lua tcp socket keepalive create connection pool for key "my_conn_pool"" should match a line in error.log (req 0)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 14: pool option - pattern "lua tcp socket keepalive create connection pool for key "my_conn_pool"" should match a line in error.log (req 1)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.
t/cs.t ...... 197/236
Failed test 'TEST 16: text frame (send unmasked frames on the client side) - pattern "recv_frame: mask bit: 0" should match a line in error.log (req 0)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.

Failed test 'TEST 16: text frame (send unmasked frames on the client side) - pattern "recv_frame: mask bit: 0" should match a line in error.log (req 1)'
at /usr/local/share/perl5/Test/Nginx/Socket.pm line 1213.
t/cs.t ...... 229/236 # Looks like you failed 18 tests of 236.
t/cs.t ...... Dubious, test returned 18 (wstat 4608, 0x1200)
Failed 18/236 subtests
(less 2 skipped subtests: 216 okay)
t/sanity.t .. 1/324 WARNING: TEST 17: exceeding the default 65535 max frame len limit (65536 bytes) - HTTP response read failure: Connection reset by peer at /usr/local/share/perl5/Test/Nginx/Socket.pm line 2165.
WARNING: TEST 17: exceeding the default 65535 max frame len limit (65536 bytes) - HTTP response read failure: Connection reset by peer at /usr/local/share/perl5/Test/Nginx/Socket.pm line 2165.
t/sanity.t .. ok

Test Summary Report

t/cs.t (Wstat: 4608 Tests: 236 Failed: 18)
Failed tests: 3, 9, 26, 31, 51-52, 57-58, 82, 87, 99-100
105-106, 152, 158, 198, 203
Non-zero exit status: 18
Files=3, Tests=578, 19 wallclock secs ( 0.11 usr 0.02 sys + 2.10 cusr 0.99 csys = 3.22 CPU)
Result: FAIL

websocket ratelimiting

Hi. how Can I implement ws ratelimiting by using this module? not only based on the connection but also inspect all request and message which is come in a websocket connection. as you know by using a tool like websocat, users can initiate a connections and send many messages in one connection but in loadbalancer side I only see one connection in log.

Thanks for your answer.

bad RSV1, RSV2, or RSV3 bits

When I GET the address that call lua script with client example I receive error: "failed to receive the frame: bad RSV1, RSV2, or RSV3 bits"

nginx.conf:

server{
listen 80;
server_name comet.io;
location /cli{
default_type 'text/html';
content_by_lua_file 'path/to/lua/ws_client.lua';
}
}

ws_client.lua: <copy-paste from https://github.com/openresty/lua-resty-websocket#restywebsocketclient>

curl http://comet.io/cli
failed to receive the frame: bad RSV1, RSV2, or RSV3 bits

There is my ws server config:

server {
listen 8020;
    server_name comet.io;
    location /ser {
        proxy_pass http://comet.io:8010;
        proxy_http_version 1.1;
        proxy_set_header Upgrade "websocket";
        proxy_set_header Connection "Upgrade";
        proxy_set_header sec-websocket-key tfyt7uhy08yuh08909uoij;
        proxy_set_header sec-websocket-version 13;
    }
}

server {
    listen 8010;
    server_name comet.io;

    location /ser {
        default_type 'text/html';
        content_by_lua_file '/root/ws_server.lua';
    }
}

Incorrect default port for wss

The library is using port 80 instead of 443 for wss:// URLs, giving the following errors:

2017/06/03 13:20:12 [error] 5776#0: *2 SSL_do_handshake() failed (SSL: error:140770FC:SSL routines:SSL23_GET_
SERVER_HELLO:unknown protocol), context: ngx.timer

and

2017/06/03 13:10:52 [error] 3441#0: *2 peer closed connection in SSL handshake, context: ngx.timer
ssl handshake failed: handshake failed

Using :443 in the URL fixes the problem, like wss://echo.websocket.org:443

Not support websocket extensions

Hello, when I use this lib for proxy.I found that the project doesn't support websocket extension.
In client.lua,you return error when RSV1, RSV2, RSV3 are not zero.
In server.lua, you doesn't check the Sec-WebSocket-Extensions header.
Maybe the library can be more complete. Is there any plan for this?

websocket client example

Using the websocket client (from sample code in the README), I get this error below:
" ./openresty/lualib/resty/websocket/protocol.lua:21: attempt to index global 'ngx' (a nil value) "

I did set the package path as required.
package.path = package.path .. ";./openresty/?.lua

Is there a working sample for websocket client?

lua-resty-websocket能不能在定时器里面主动发送数据到客户端

我试过用ngx.timer.every在websocket连接之后设置定时器,定时器能够正常执行,但是一到wb:send_text方法就报错,如果服务端不能主动推送数据,只能在wb:recv_frame()之后才能发送的话,就不如用简单的http请求了。
求帮助!

测试代码
local server = require "resty.websocket.server"
local wb, err = server:new{
timeout = 5000, -- in milliseconds
max_payload_len = 65535,
}
if not wb then
ngx.log(ngx.ERR, "failed to new websocket: ", err)
return ngx.exit(444)
end

ngx.timer.every(5, function (premature, wb)
ngx.log(ngx.ERR, nil == wb)
local bytes, err = wb:send_text("hello")--此处报错
if not bytes then
ngx.log(ngx.ERR, "failed to send text: ", err)
return ngx.exit(444)
end
end, wb)

while true do
local data, typ, err = wb:recv_frame()
if wb.fatal then
ngx.log(ngx.ERR, "failed to receive frame: ", err)
return ngx.exit(444)
end
if not data then
local bytes, err = wb:send_ping()
if not bytes then
ngx.log(ngx.ERR, "failed to send ping: ", err)
return ngx.exit(444)
end
elseif typ == "close" then break
elseif typ == "ping" then
local bytes, err = wb:send_pong()
if not bytes then
ngx.log(ngx.ERR, "failed to send pong: ", err)
return ngx.exit(444)
end
elseif typ == "pong" then
ngx.log(ngx.INFO, "client ponged")
elseif typ == "text" then
local bytes, err = wb:send_text("hello")
if not bytes then
ngx.log(ngx.ERR, "failed to send text: ", err)
return ngx.exit(444)
end
end
end
wb:send_close()

Socket Busy Errors (was: Is this a correct way to keep connection alive?)

Hi,

I got this working on my mac using latest OpenResty bundle, and websockets version of Lua nginx-module. This is really great stuff.

I have written small demos on my own, and I have got the basics working. What's the correct way to keep connection alive? Should I write while true do ... end loop on the websocket server or what's the preferred way to keep connection alive.

I.e. a small example with say this kind of client side js-code:

var connection = new WebSocket('ws://127.0.0.1/s');
connection.onopen = function () {
  console.log('connected');
  connection.send('text');
};
connection.onerror = function (error) {
  console.log('error ' + error);
};
connection.onmessage = function (e) {
  console.log('message ' + e.data);
};
connection.onclose = function () {
  console.log('closed');
};

Server code (location /s -> content_by_lua):

local server = require "resty.websocket.server"
local wb, err = server:new{
  timeout = 5000,
  max_payload_len = 65535,
}
if not wb then
  ngx.log(ngx.ERR, "failed to new websocket: ", err)
  return ngx.exit(444)
end
wb:set_timeout(10000)
while true do
  local data, typ, err = wb:recv_frame()
  if typ == "close" then
    wb:send_close()
    return
  elseif typ == "text" then
    local bytes, err = wb:send_text(data)
    if not bytes then
      wb:send_close()
      return
    end
  end
end

[alert] 3422#0: worker process 4444 exited on signal 11 (core dumped)?

I wrote a simple API gateway, but during the test, I found that the process would suddenly exit within a certain period of time, resulting in disconnection. I thought it was the workers who did not share SSL information, but after consulting the data, I felt it was not the problem of SSL and fell into a confused state. I would like to ask what the problem was caused by?thank you

problem:
image

problem:
image

client code:
image

server code :
image

You have wrote two demo but they does not worked with each other

My English is not good,so sorry.
I was download the openresty and put it to work.Then I followed your demo,but they does not worker with each other.It make me confused for second,but I have fix it.
I think the reason is:
The client connected success,then the client blocked on method wb:recv_frame()
The server created success,then the server blocked on method wb:recv_frame()
Then I got a problem,They both will block util timeout.
I think you may want to rewrite those two demos,so that the others can avoid this problem and stop wasting time.

Got a socket init error

hi...

I follow https://medium.com/p/1778601c9e05 to try to make a demo,but when i connect to server ,it got socket init error.

nginx version: ngx_openresty/1.4.2.5

Nginx Log :
2013/09/18 00:32:13 [error] 6245#0: *3 lua entry thread aborted: runtime error: /usr/local/lualib/resty/websocket/server.lua:105: expecting zero arguments, but got 1
stack traceback:
coroutine 0:
[C]: in function 'req_sock'
/usr/local/lualib/resty/websocket/server.lua:105: in function 'new'
[string "content_by_lua"]:3: in function <[string "content_by_lua"]:1>, client: 192.168.56.1, server: ko.local.freeflare.com, request: "GET /1.0/websocket HTTP/1.1", host: "ko.local.freeflare.com"

nginx conf:
worker_processes 2;

error_log logs/error.log;

events {
worker_connections 10240;
}

http {
include mime.types;

default_type  application/octet-stream;

resolver 8.8.8.8;

server_tokens off;

server_names_hash_bucket_size 128;
client_body_buffer_size 4m;
client_max_body_size 300m;
large_client_header_buffers 2 1k;

client_body_timeout   3;
client_header_timeout 3;
keepalive_timeout     5;
send_timeout          5;    

sendfile on;
tcp_nopush     on;
tcp_nodelay on;

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;

gzip on;
gzip_min_length  1k;
gzip_buffers     4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_vary on;

#close lua code cache, if is product please open .
lua_code_cache off;

gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

lua_shared_dict haddit_shared_dict 300m;
#add websocket lib 
lua_package_path "/usr/local/lualib/resty/websocket/?.lua;;";

# add firewall
init_by_lua_file conf/waf/init.lua;
access_by_lua_file conf/waf/waf.lua;    

include vhosts/*.conf;

}

vhosts/yagamiko.conf
log_format yagamiko '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_cookie" $http_x_forwarded_for';

server {
listen 80 so_keepalive=2s:2s:8;
server_name ko.local.freeflare.com;

    encrypted_session_key       "asdfghjklqasdfghjklqasdfghjklqwe";
    encrypted_session_iv        "12345678123456";
    encrypted_session_expires   30d;


    #static file directory
    location ~ ^/(static|media)/ {
        root    '__YAGAMI_APP_PATH_VALUE__/static';
        expires 30d;
    }

    location /1.0/websocket {
          lua_socket_log_errors off;
          lua_check_client_abort on;
          content_by_lua '
            local server = require "resty.websocket.server"
            local wb, err = server:new{
                timeout = 5000,  -- in milliseconds
                max_payload_len = 65535,
            }
            if not wb then
              ngx.log(ngx.ERR, "failed to new websocket: ", err)
              return ngx.exit(444)
            end
            while true do
              local data, typ, err = wb:recv_frame()
              if wb.fatal then
                ngx.log(ngx.ERR, "failed to receive frame: ", err)
                return ngx.exit(444)
              end
              if not data then
                local bytes, err = wb:send_ping()
                if not bytes then
                  ngx.log(ngx.ERR, "failed to send ping: ", err)
                  return ngx.exit(444)
                end
              elseif typ == "close" then break
              elseif typ == "ping" then
                local bytes, err = wb:send_pong()
                if not bytes then
                  ngx.log(ngx.ERR, "failed to send pong: ", err)
                  return ngx.exit(444)
                end
              elseif typ == "pong" then
                ngx.log(ngx.INFO, "client ponged")
              elseif typ == "text" then
                local bytes, err = wb:send_text(data)
                if not bytes then
                  ngx.log(ngx.ERR, "failed to send text: ", err)
                  return ngx.exit(444)
                end
              end
            end
            wb:send_close()
          ';
    }

    #lua_code_cache off;
    location / {
        #default_type text/html;
        set $YAGAMI_HOME      '__YAGAMI_HOME_VALUE__';
        set $YAGAMI_APP_NAME  '__YAGAMI_APPNAME_VALUE__';
        set $YAGAMI_APP_PATH  '__YAGAMI_APP_PATH_VALUE__';

        #set $wdfsproxy $uri;
        #load yagami
        content_by_lua_file     '$YAGAMI_HOME/luasrc/yagami.lua';
    }

    #location /weedfsproxy {
        #proxy_pass http://127.0.0.1:9331/$wdfsproxy;
        #proxy_pass http://127.0.0.1:9331/6,75735795edd1;
    #}

    #set error
    #error_page   500 502 503 504  /50x.html;
    #location = /50x.html {
    #    root   html;
    #}

    access_log  /freeflare/trunk/foundation/server/lua/yagamiko/nginx_runtime/logs/__YAGAMI_APPNAME_VALUE__.log  yagamiko;
    error_log  /freeflare/trunk/foundation/server/lua/yagamiko/nginx_runtime/logs/__YAGAMI_APPNAME_VALUE___err.log  debug;
}

Compilation errors while running sample programs https://github.com/openresty/lua-resty-websocket

Hi,

I am new to Openresty and Lua programming.

I have installed openresty-1.15.8.3 and dependent libraries pcre-8.40, openssl-1.0.2k, zlib-1.2.11 successfully in Centos7.

I am trying to run server and client programs in the link https://github.com/openresty/lua-resty-websocket but I am getting compilation errors. Could you please let me know what I am missing here.

   PFA the programs ida_client.lua and ida_server.lua.

Errors::

[root@IDA openresty-1.15.8.3]# resty ida_client.lua
ERROR: ida_client.lua:3: API disabled in the current context
stack traceback:
/usr/local/openresty/lualib/resty/core/var.lua:73: in function '__index'
ida_client.lua:3: in function 'file_gen'
init_worker_by_lua:45: in function <init_worker_by_lua:43>
[C]: in function 'xpcall'
init_worker_by_lua:52: in function <init_worker_by_lua:50>
[root@IDA openresty-1.15.8.3]#
[root@IDA openresty-1.15.8.3]#
[root@IDA openresty-1.15.8.3]#
[root@IDA openresty-1.15.8.3]# resty ida_server.lua
ERROR: /usr/local/openresty/lualib/resty/websocket/server.lua:36: API disabled in the current context
stack traceback:
/usr/local/openresty/lualib/resty/core/misc.lua:166: in function '__index'
/usr/local/openresty/lualib/resty/websocket/server.lua:36: in function 'new'
ida_server.lua:3: in function 'file_gen'
init_worker_by_lua:45: in function <init_worker_by_lua:43>
[C]: in function 'xpcall'
init_worker_by_lua:52: in function <init_worker_by_lua:50>
[root@IDA openresty-1.15.8.3]#

Thanks,
Rajasekhar

ida_client.txt
ida_server.txt

为什么会报错"lua tcp socket read timed out"

--config.session.timeout等于 60秒
local wb, err = server:new{ timeout = config.session.timeout, -- in milliseconds
max_payload_len = 65535,
}
if not wb then
ngx.log(ngx.ERR, "failed to new websocket: ", err)
return ngx.exit(444)
end

wb:set_timeout(config.session.timeout)
while true do
local data, typ, err = wb:recv_frame()
if wb.fatal then
--ngx.log(ngx.ERR, "failed to receive frame: ", err)
break
end
if not data and not typ then
ngx.log(ngx.INFO,"------------------------"..tostring(data)..","..tostring(typ)..","..tostring(err))
break
end
if not data then
local bytes, err = wb:send_ping()
if not bytes then
ngx.log(ngx.ERR, "failed to send ping: ", err)
end
elseif typ == "close" then
break
elseif typ == "ping" then
ngx.log(ngx.INFO,"------------rec ping:send pong")
local bytes, err = wb:send_pong()
if not bytes then
ngx.log(ngx.ERR, "failed to send pong: ", err)
break
end
elseif typ == "pong" then
ngx.log(ngx.INFO,"------------rec pong")
elseif typ == "text" then
ngx.log(ngx.INFO,"receive: "..tostring(data))
local res = resolve.doresolve(M,data)
if res then
--log.err("----------response:"..tostring(res)..",req:"..tostring(data))
if dosend(res)==0 then
break
end
end
end
end

Run Autobahn Testsuite

The Autobahn WebSocket testsuite has become the de-facto standard for testing WebSocket libraries for correctness: https://github.com/crossbario/autobahn-testsuite

Feature Request: Add a script that runs the Autobahn tests against the Lua client and server.

Ideally also add a GitHub workflow that can run the test in an automated manner.

Support for custom headers

I need to pass a Cookie in the websocket request, however the library does not support custom headers yet

sending messages to already created websocket objects

I have a list of websocket server objects that get created when client(s) call in on port A.

Another port, B listens for incoming http requests(no websockets here) on same server. The requirement is to send messages to websocket clients via already created websockets connections (on port A) based on requests on port B.

My initial hunch was just to test the created websocket object in different request contexts.
To start with, I saved the websocket server object in a global table variable. Requests on port B seem to have access to earlier saved websocket object. Tried sending text using this object through it resulted in error:

lua entry thread aborted: runtime error: ...r/openresty/1.13.6.1/lualib/resty/websocket/protocol.lua:320: bad request
stack traceback:
coroutine 0:
	[C]: in function 'send'
	...r/openresty/1.13.6.1/lualib/resty/websocket/protocol.lua:320: in function '_send_frame'
	...lar/openresty/1.13.6.1/lualib/resty/websocket/server.lua:167: in function 'send_text'``

Any insights? I was going to try the ngx.shared.DICT next but wanted to check with you all. I am new to openresty and Lua

"send_text" got no error meesage after browser closed

my lua code is just like this:

local file = io.popen("tail -f /var/log/ping.log")
for line in file:lines() do
local bytes, err = wb:send_text(line)
ngx.log(ngx.INFO, "LINE SENDED:",line,":",bytes,":",err)

if not bytes then
     ngx.log(ngx.ERR, "failed to send a text frame: ", err)
    return ngx.exit(444)
end

end
file:close()

after my browser(chrome/edge) closed,the "send_text" still return bytes and no error,which I hope a zero bytes and error msage like "the client connection is closed"

need help

ssl session repeated sslhandshake

branch : master

ok, err = sock:sslhandshake(false, server_name, ssl_verify)

 if scheme == "wss" then
        if not ssl_support then
            return nil, "ngx_lua 0.9.11+ required for SSL sockets"
        end
        if client_cert then
            ok, err = sock:setclientcert(client_cert, client_priv_key)
            if not ok then
                return nil, "failed to set TLS client certificate: " .. err
            end
        end
        ok, err = sock:sslhandshake(false, server_name, ssl_verify)
        if not ok then
            return nil, "ssl handshake failed: " .. err
        end
    end

According to the api manual https://www.kancloud.cn/qq13867685/openresty-api-cn/159103
session, err = tcpsock:sslhandshake(reused_session?, server_name?, ssl_verify?)

I think it is nesseary to change the code:

 if scheme == "wss" then
        if not ssl_support then
            return nil, "ngx_lua 0.9.11+ required for SSL sockets"
        end
        if client_cert then
            ok, err = sock:setclientcert(client_cert, client_priv_key)
            if not ok then
                return nil, "failed to set TLS client certificate: " .. err
            end
        end
    end

    -- check for connections from pool:

    local count, err = sock:getreusedtimes()
    if not count then
        return nil, "failed to get reused times: " .. err
    end
    if count > 0 then
        -- being a reused connection (must have done handshake)
        return 1
   else
       local  ok, err = sock:sslhandshake(false, server_name, ssl_verify)
        if not ok then
            return nil, "ssl handshake failed: " .. err
        end
    end

Added: Determine if the sslhandshake is necessary by 'sock:getreusedtimes()' .It do need to call sslhandshake when the reused time of connection is zero.

refer to https://github.com/doujiang24/lua-resty-kafka/blob/3fbed91d81d4fb32d4dda4316f5f2cba04622633/lib/resty/kafka/broker.lua#L144

unexpected connection behavior

When I connect to the websocket server using an unauthorized websocket url, the connect function does not return an error.
I expect the connection to fail because the server will return a 401 status code.
The corresponding code is resty/websocket/client.lua(line 197)
m, err = re_match(header, [[^\s*HTTP/1\.1\s+]], "jo")
why not change this line to
m, err = re_match(header, [[^\s*HTTP/1\.1\s+101]], "jo")

REQ: full-duplex support

As far as I can tell there is currently no way to act upon events and send packets from the server to the clients? - Is this a planned feature?

maybe it is websocket client issue or wrong way to use

the lua code :

local ngx = ngx
local client = require "resty.websocket.client"

local function action_get()
    ngx.req.discard_body()
    local t = ngx.time()
    -- ngx.say(ngx.http_time(t))
    local wc, err = client.new({timeout = 5000, max_payload_len = 65535})
    if not wc then
        ngx.log(ngx.ERR, "w client init failed: ", err)
        ngx.exit(500)
    end
    local ok, err = wc.connect("ws://127.0.0.1:8091")
    if not ok then
        ngx.log(ngx.ERR, "failed to connect: ", err)
        ngx.exit(500)
    end
    wc.send_binary(ngx.http_time(t))
    wc.close()
    ngx.say(ngx.http_time(t))
end

the nginx conf:

http {
    server {
        listen 8090 reuseport;
        server_name localhost;

        location / {
            default_type 'text/html';
            lua_code_cache off;
            rewrite_by_lua_file 'service/rewrite.lua';
            access_by_lua_file 'service/access.lua';
            content_by_lua_file 'service/content.lua';
            # body_filter_by_lua_file 'service/body_filter.lua';
        }
    }
}

shell test command:

  curl http://127.0.0.1:8090

error output

*26 [lua] content.lua:16: failed to connect: not initialized, blabla...

I tested wc.sock, it is ok, but always report this error, who can help, thanks?

can not use resty redis

when i try to connect to the ws server(ws://ip:8081/ws), it raise error

2021/03/25 00:20:34 [info] 16392#16392: *1 client 113.92.35.59 closed keepalive connection

my nginx.conf content

worker_processes 2;
user root;

events {
    worker_connections 1024;
}

error_log logs/error.log debug;

http {
    server {
        listen 8081 reuseport;
        location /ws {
                        access_by_lua_block {
                                local ngx = ngx
                                local redis = require("resty.redis")
                                ngx.log(ngx.INFO, "access stage")
                                local red = redis:new()
                                local ok, err = red:connect("127.0.0.1", 6379)
                                if not ok then
                                ngx.exit(ngx.HTTP_UNAUTHORIZED)
                                end
                        }
        }

    }
}

RFC 8441 support: WebSockets over h2, h2c

Feature Request: Introduce support for WebSockets over HTTP/2 (h2 and h2c) for the server and client.

The use-case is mainly reducing the TCP connection count by leveraging HTTP/2 multiplexing. For example, a WebSocket reverse proxy could multiplex many incoming WebSockets to a single outgoing HTTP/2 connection.

Specification: RFC 8441: Bootstrapping WebSockets with HTTP/2

For the WebSocket server this requires support in ngx.req.connect.

For the WebSocket client, it's much more complicated. I think without core modifications, the only way to multiplex is by having an NGINX light thread that runs a pure-Lua HTTP/2 implementation over cosockets, and then doing cross-coroutine IPC with this thread to create WebSockets and send/receive messages. lua-resty-http2 looks like a great candidate.

bad RSV1, RSV2, or RSV3 bits

Hello,

I'm implementing a websocket server using lua-resty-websocket. When I send small frames everything is okay. But when the frame is getting bigger, approx 32kB I start receiving this message:

bad RSV1, RSV2, or RSV3 bits
I also can avoid this message by using a bigger Timeout:

local wb, err = server:new { max_payload_len = 65000, timeout = 1500}
but the drawback of this is that the messages are processed in a way slower manner: 1.5seconds is a huge time for a near real time application.

Do someone encountred this issue before ? Any idea of how to solve it please ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.