You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by sp...@apache.org on 2020/11/10 08:56:46 UTC

[apisix] branch master updated: chore(core): enabled websocket in route and service (#2593)

This is an automated email from the ASF dual-hosted git repository.

spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new 70453ae   chore(core): enabled websocket in route and service (#2593)
70453ae is described below

commit 70453aece306d9fafba6effb746860fe89357703
Author: dabue <53...@users.noreply.github.com>
AuthorDate: Tue Nov 10 16:56:38 2020 +0800

     chore(core): enabled websocket in route and service (#2593)
---
 apisix/init.lua                  |  8 +++-
 apisix/schema_def.lua            | 17 ++++---
 doc/admin-api.md                 |  7 ++-
 doc/architecture-design.md       |  2 -
 doc/zh-cn/admin-api.md           |  7 ++-
 doc/zh-cn/architecture-design.md |  2 -
 t/node/merge-route.t             | 97 ++++++++++++++++++++++++++++++++++++++++
 t/node/upstream-websocket.t      | 41 ++++++++---------
 8 files changed, 145 insertions(+), 36 deletions(-)

diff --git a/apisix/init.lua b/apisix/init.lua
index 05a708f..769de3c 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -393,6 +393,7 @@ function _M.http_access_phase()
         return ngx.exec("@grpc_pass")
     end
 
+    local enable_websocket = route.value.enable_websocket
     if route.value.service_id then
         local service = service_fetch(route.value.service_id)
         if not service then
@@ -407,6 +408,11 @@ function _M.http_access_phase()
         api_ctx.conf_version = route.modifiedIndex .. "&" .. service.modifiedIndex
         api_ctx.conf_id = route.value.id .. "&" .. service.value.id
         api_ctx.service_id = service.value.id
+
+        if enable_websocket == nil then
+            enable_websocket = service.value.enable_websocket
+        end
+
     else
         api_ctx.conf_type = "route"
         api_ctx.conf_version = route.modifiedIndex
@@ -414,7 +420,6 @@ function _M.http_access_phase()
     end
     api_ctx.route_id = route.value.id
 
-    local enable_websocket
     local up_id = route.value.upstream_id
     if up_id then
         local upstreams = core.config.fetch_created_obj("/upstreams")
@@ -486,6 +491,7 @@ function _M.http_access_phase()
     if enable_websocket then
         api_ctx.var.upstream_upgrade    = api_ctx.var.http_upgrade
         api_ctx.var.upstream_connection = api_ctx.var.http_connection
+        core.log.info("enabled websocket for route: ", route.value.id)
     end
 
     if route.value.script then
diff --git a/apisix/schema_def.lua b/apisix/schema_def.lua
index f61feb7..b74d8a3 100644
--- a/apisix/schema_def.lua
+++ b/apisix/schema_def.lua
@@ -341,10 +341,6 @@ local upstream_schema = {
             description = "the key of chash for dynamic load balancing",
             type = "string",
         },
-        enable_websocket = {
-            description = "enable websocket for request",
-            type        = "boolean"
-        },
         labels = {
             description = "key/value pairs to specify attributes",
             type = "object",
@@ -475,6 +471,12 @@ _M.route = {
         service_protocol = {
             enum = {"grpc", "http"}
         },
+
+        enable_websocket = {
+            description = "enable websocket for request",
+            type        = "boolean",
+        },
+
         id = id_schema,
     },
     anyOf = {
@@ -517,7 +519,12 @@ _M.service = {
             maxProperties = 16
         },
         create_time = timestamp_def,
-        update_time = timestamp_def
+        update_time = timestamp_def,
+        enable_websocket = {
+            description = "enable websocket for request",
+            type        = "boolean",
+        },
+
     },
     additionalProperties = false,
 }
diff --git a/doc/admin-api.md b/doc/admin-api.md
index eb6e0e3..0e8e17c 100644
--- a/doc/admin-api.md
+++ b/doc/admin-api.md
@@ -71,6 +71,7 @@
 |service_id|False |Service|Binded Service configuration, see [Service](architecture-design.md#service) for more ||
 |service_protocol|False|Upstream protocol type|only `grpc` and `http` are supported|`http` is the default value; Must set `grpc` if using `gRPC proxy` or `gRPC transcode`|
 |labels   |False |Match Rules|Key/value pairs to specify attributes|{"version":"v2","build":"16","env":"production"}|
+|enable_websocket|False|Auxiliary| enable `websocket`(boolean), default `false`.||
 
 For the same type of parameters, such as `host` and `hosts`, `remote_addr` and `remote_addrs` cannot exist at the same time, only one of them can be selected. If enabled at the same time, the API will response an error.
 
@@ -107,6 +108,7 @@ $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f
     "hosts": ["foo.com", "*.bar.com"],
     "remote_addrs": ["127.0.0.0/8"],
     "methods": ["PUT", "GET"],
+    "enable_websocket": true,
     "upstream": {
         "type": "roundrobin",
         "nodes": {
@@ -290,6 +292,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13
 |name     |False |Auxiliary   |Identifies service names.|customer-xxxx|
 |desc     |False |Auxiliary   |service usage scenarios, and more.|customer xxxx|
 |labels   |False |Match Rules|Key/value pairs to specify attributes|{"version":"v2","build":"16","env":"production"}|
+|enable_websocket|False|Auxiliary| enable `websocket`(boolean), default `false`.||
 
 Config Example:
 
@@ -301,6 +304,7 @@ Config Example:
     "upstream": {},     # upstream, not recommended
     "name": "service-test",
     "desc": "hello world",
+    "enable_websocket": true,
 }
 ```
 
@@ -317,6 +321,7 @@ $ curl http://127.0.0.1:9080/apisix/admin/services/201  -H 'X-API-KEY: edd1c9f03
             "key": "remote_addr"
         }
     },
+    "enable_websocket": true,
     "upstream": {
         "type": "roundrobin",
         "nodes": {
@@ -503,7 +508,6 @@ In addition to the basic complex equalization algorithm selection, APISIX's Upst
 |key             |optional|This option is only valid if the `type` is `chash`. Find the corresponding node `id` according to `hash_on` and `key`. When `hash_on` is set as `vars`, `key` is the required parameter, for now, it support nginx built-in variables like `uri, server_name, server_addr, request_uri, remote_port, remote_addr, query_string, host, hostname, arg_***`, `arg_***` is arguments in the request line, [Nginx variables list](http://nginx.org/en/docs/varindex.html). When `hash_ [...]
 |checks          |optional|Configure the parameters of the health check. For details, refer to [health-check](health-check.md).|
 |retries         |optional|Pass the request to the next upstream using the underlying Nginx retry mechanism, the retry mechanism is enabled by default and set the number of retries according to the number of backend nodes. If `retries` option is explicitly set, it will override the default value. `0` means disable retry mechanism.|
-|enable_websocket|optional| enable `websocket`(boolean), default `false`.|
 |timeout|optional| Set the timeout for connection, sending and receiving messages. |
 |name     |optional|Identifies upstream names|
 |desc     |optional|upstream usage scenarios, and more.|
@@ -523,7 +527,6 @@ Config Example:
         "send":15,
         "read":15,
     },
-    "enable_websocket": true,
     "nodes": {"host:80": 100},  # Upstream machine address list, the format is `Address + Port`
     "k8s_deployment_info": {    # kubernetes deployment info
         "namespace": "test-namespace",
diff --git a/doc/architecture-design.md b/doc/architecture-design.md
index 6274f61..4a6ef9b 100644
--- a/doc/architecture-design.md
+++ b/doc/architecture-design.md
@@ -272,7 +272,6 @@ In addition to the basic complex equalization algorithm selection, APISIX's Upst
 |key             |required|This option is only valid if the `type` is `chash`. Find the corresponding node `id` according to `hash_on` and `key`. When `hash_on` is set as `vars`, `key` is the required parameter, for now, it support nginx built-in variables like `uri, server_name, server_addr, request_uri, remote_port, remote_addr, query_string, host, hostname, arg_***`, `arg_***` is arguments in the request line, [Nginx variables list](http://nginx.org/en/docs/varindex.html). When `hash_ [...]
 |checks          |optional|Configure the parameters of the health check. For details, refer to [health-check](health-check.md).|
 |retries         |optional|Pass the request to the next upstream using the underlying Nginx retry mechanism, the retry mechanism is enabled by default and set the number of retries according to the number of backend nodes. If `retries` option is explicitly set, it will override the default value.|
-|enable_websocket|optional| enable `websocket`(boolean), default `false`.|
 |timeout|optional| Set the timeout for connection, sending and receiving messages. |
 |desc     |optional|Identifies route names, usage scenarios, and more.|
 |labels   |optional|The key/value pairs to specify attributes. |
@@ -298,7 +297,6 @@ curl http://127.0.0.1:9080/apisix/admin/upstreams/2 -H 'X-API-KEY: edd1c9f034335
 {
     "type": "chash",
     "key": "remote_addr",
-    "enable_websocket": true,
     "nodes": {
         "127.0.0.1:80": 1,
         "foo.com:80": 2
diff --git a/doc/zh-cn/admin-api.md b/doc/zh-cn/admin-api.md
index f971446..f5ed411 100644
--- a/doc/zh-cn/admin-api.md
+++ b/doc/zh-cn/admin-api.md
@@ -75,6 +75,7 @@
 |vars       |可选  |匹配规则|由一个或多个`{var, operator, val}`元素组成的列表,类似这样:`{{var, operator, val}, {var, operator, val}, ...}}`。例如:`{"arg_name", "==", "json"}`,表示当前请求参数 `name` 是 `json`。这里的 `var` 与 Nginx 内部自身变量命名是保持一致,所以也可以使用 `request_uri`、`host` 等;对于 `operator` 部分,目前已支持的运算符有 `==`、`~=`、`>`、`<` 和 `~~`。对于`>`和`<`两个运算符,会把结果先转换成 number 然后再做比较。查看支持的[运算符列表](#运算符列表)|{{"arg_name", "==", "json"}, {"arg_age", ">", 18}}|
 |filter_func|可选|匹配规则|用户自定义的过滤函数。可以使用它来实现特殊场景的匹配要求实现。该函数默认接受一个名为 vars 的输入参数,可以用它来获取 Nginx 变量。|function(vars) return vars["arg_name"] == "json" end|
 |labels   |可选 |匹配规则|标识附加属性的键值对|{"version":"v2","build":"16","env":"production"}|
+|enable_websocket|可选 |辅助| 是否启用 `websocket`(boolean), 缺省 `false`.||
 
 有两点需要特别注意:
 
@@ -114,6 +115,7 @@ $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f
     "hosts": ["foo.com", "*.bar.com"],
     "remote_addrs": ["127.0.0.0/8"],
     "methods": ["PUT", "GET"],
+    "enable_websocket": true,
     "upstream": {
         "type": "roundrobin",
         "nodes": {
@@ -300,6 +302,7 @@ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f13
 |name     |可选 |辅助   |标识服务名称。||
 |desc     |可选 |辅助   |服务描述、使用场景等。||
 |labels   |可选 |匹配规则|标识附加属性的键值对|{"version":"v2","build":"16","env":"production"}|
+|enable_websocket|可选 |辅助| 是否启用 `websocket`(boolean), 缺省 `false`.||
 
 serivce 对象 json 配置内容:
 
@@ -311,6 +314,7 @@ serivce 对象 json 配置内容:
     "upstream": {},         # upstream 信息对象,不建议使用
     "name": "测试svc",  # service 名称
     "desc": "hello world",  # service 描述
+    "enable_websocket": true, #启动 websocket 功能
 }
 ```
 
@@ -328,6 +332,7 @@ $ curl http://127.0.0.1:9080/apisix/admin/services/201  -H 'X-API-KEY: edd1c9f03
             "key": "remote_addr"
         }
     },
+    "enable_websocket": true,
     "upstream": {
         "type": "roundrobin",
         "nodes": {
@@ -517,7 +522,6 @@ APISIX 的 Upstream 除了基本的复杂均衡算法选择外,还支持对上
 |checks          |可选|health_checker|配置健康检查的参数,详细可参考[health-check](../health-check.md)||
 |retries         |可选|整型|使用底层的 Nginx 重试机制将请求传递给下一个上游,默认启用重试且次数为后端 node 数量。如果指定了具体重试次数,它将覆盖默认值。`0` 代表不启用重试机制||
 |timeout         |可选|超时时间对象|设置连接、发送消息、接收消息的超时时间||
-|enable_websocket     |可选 |辅助|是否允许启用 websocket 能力||
 |hash_on     |可选 |辅助|该参数作为一致性 hash 的入参||
 |name     |可选 |辅助|标识上游服务名称、使用场景等。||
 |desc     |可选 |辅助|上游服务描述、使用场景等。||
@@ -536,7 +540,6 @@ upstream 对象 json 配置内容:
         "send":15,
         "read":15,
     },
-    "enable_websocket": true,
     "nodes": {"host:80": 100},  # 上游机器地址列表,格式为`地址 + Port`
     "k8s_deployment_info": {    # k8s deployment 信息
         "namespace": "test-namespace",
diff --git a/doc/zh-cn/architecture-design.md b/doc/zh-cn/architecture-design.md
index abcdbc9..1f4a553 100644
--- a/doc/zh-cn/architecture-design.md
+++ b/doc/zh-cn/architecture-design.md
@@ -282,7 +282,6 @@ APISIX 的 Upstream 除了基本的复杂均衡算法选择外,还支持对上
 |hash_on         |可选|`hash_on` 支持的类型有 `vars`(Nginx内置变量),`header`(自定义header),`cookie`,`consumer`,默认值为 `vars`|
 |checks          |可选|配置健康检查的参数,详细可参考[health-check](../health-check.md)|
 |retries         |可选|使用底层的 Nginx 重试机制将请求传递给下一个上游,默认 APISIX 会启用重试机制,根据配置的后端节点个数设置重试次数,如果此参数显式被设置将会覆盖系统默认设置的重试次数。|
-|enable_websocket|可选| 是否启用 `websocket`(布尔值),默认不启用|
 |labels          |可选| 用于标识属性的键值对。 |
 |pass_host            |可选|`pass` 透传客户端请求的 host, `node` 不透传客户端请求的 host, 使用 upstream node 配置的 host, `rewrite` 使用 `upstream_host` 配置的值重写 host 。|
 |upstream_host    |可选|只在 `pass_host` 配置为 `rewrite` 时有效。|
@@ -314,7 +313,6 @@ curl http://127.0.0.1:9080/apisix/admin/upstreams/2 -H 'X-API-KEY: edd1c9f034335
 {
     "type": "chash",
     "key": "remote_addr",
-    "enable_websocket": true,
     "nodes": {
         "127.0.0.1:80": 1,
         "foo.com:80": 2
diff --git a/t/node/merge-route.t b/t/node/merge-route.t
index 939bc50..0ce1faa 100644
--- a/t/node/merge-route.t
+++ b/t/node/merge-route.t
@@ -327,3 +327,100 @@ host: httpbin.orgxxx
 --- error_code: 404
 --- no_error_log
 [error]
+
+
+
+=== TEST 14: enabled websocket in service
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/services/1',
+                ngx.HTTP_PUT,
+                [[{
+                    "enable_websocket": true,
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    }
+                }]]
+            )
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 15: set route(bind service 1)
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/routes/33',
+                ngx.HTTP_PUT,
+                [[{
+                    "uri": "/uri",
+                    "service_id": "1"
+                }]]
+            )
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
+
+
+
+=== TEST 16: hit route
+--- request
+GET /uri
+--- response_body
+uri: /uri
+host: localhost
+connection: close
+x-real-ip: 127.0.0.1
+--- no_error_log
+[error]
+--- error_log
+enabled websocket for route: 33
+
+
+
+=== TEST 17: delete rout
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/routes/33',
+                ngx.HTTP_DELETE
+            )
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- request
+GET /t
+--- response_body
+passed
+--- no_error_log
+[error]
diff --git a/t/node/upstream-websocket.t b/t/node/upstream-websocket.t
index 99d9461..c3b69ed 100644
--- a/t/node/upstream-websocket.t
+++ b/t/node/upstream-websocket.t
@@ -33,17 +33,17 @@ __DATA__
             local t = require("lib.test_admin").test
             local code, body = t('/apisix/admin/routes/1',
                  ngx.HTTP_PUT,
-                 [[{
-                        "upstream": {
-                            "nodes": {
-                                "127.0.0.1:1980": 1
-                            },
-                            "enable_websocket": true,
-                            "type": "roundrobin"
+                [[{
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
                         },
-                        "uri": "/websocket_handshake"
+                        "type": "roundrobin"
+                    },
+                    "enable_websocket": true,
+                    "uri": "/websocket_handshake"
                 }]]
-                )
+            )
 
             if code >= 300 then
                 ngx.status = code
@@ -98,7 +98,6 @@ Sec-WebSocket-Protocol: chat
                         "127.0.0.1:1981": 1
                     },
                     "type": "roundrobin",
-                    "enable_websocket": true,
                     "desc": "new upstream"
                 }]]
                 )
@@ -124,10 +123,11 @@ passed
         content_by_lua_block {
             local t = require("lib.test_admin").test
             local code, body = t('/apisix/admin/routes/6',
-                 ngx.HTTP_PUT,
-                 [[{
-                        "uri": "/websocket_handshake/route",
-                        "upstream_id": "6"
+                ngx.HTTP_PUT,
+                [[{
+                    "uri": "/websocket_handshake/route",
+                    "enable_websocket": true,
+                    "upstream_id": "6"
                 }]]
                 )
 
@@ -177,15 +177,12 @@ Sec-WebSocket-Protocol: chat
     location /t {
         content_by_lua_block {
             local t = require("lib.test_admin").test
-            local code, body = t('/apisix/admin/upstreams/6',
-                 ngx.HTTP_PUT,
-                 [[{
-                    "nodes": {
-                        "127.0.0.1:1981": 1
-                    },
-                    "type": "roundrobin",
+            local code, body = t('/apisix/admin/routes/6',
+                ngx.HTTP_PUT,
+                [[{
+                    "uri": "/websocket_handshake/route",
                     "enable_websocket": false,
-                    "desc": "new upstream"
+                    "upstream_id": "6"
                 }]]
                 )