3 Copyright (C) 2016 ZTE, Inc. and others. All rights reserved. (ZTE)
\r
5 Licensed under the Apache License, Version 2.0 (the "License");
\r
6 you may not use this file except in compliance with the License.
\r
7 You may obtain a copy of the License at
\r
9 http://www.apache.org/licenses/LICENSE-2.0
\r
11 Unless required by applicable law or agreed to in writing, software
\r
12 distributed under the License is distributed on an "AS IS" BASIS,
\r
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
14 See the License for the specific language governing permissions and
\r
15 limitations under the License.
\r
19 local msbConf = require('conf.msbinit')
\r
20 local dbclient = require('dao.db_access')
\r
21 local tbl_util = require('lib.utils.table_util')
\r
22 local svc_util = require('lib.utils.svc_util')
\r
23 local log_util = require('lib.utils.log_util')
\r
24 local error_handler = require('lib.utils.error_handler')
\r
26 local tbl_concat = table.concat
\r
27 local tbl_isempty = tbl_util.isempty
\r
28 local svc_isactive = svc_util.isactive
\r
29 local svc_get_url = svc_util.get_url
\r
30 local svc_get_backend_protocol = svc_util.get_backend_protocol
\r
31 local svc_use_own_upstream = svc_util.use_own_upstream
\r
32 local svc_get_key_prefix = svc_util.get_key_prefix
\r
33 local str_low = string.lower
\r
34 local ngx_var = ngx.var
\r
35 local ngx_ctx = ngx.ctx
\r
36 local log = log_util.log
\r
37 local error_svc_not_found = error_handler.svc_not_found
\r
38 local error_upstream_not_found = error_handler.upstream_not_found
\r
40 local enablerefercheck = msbConf.systemConf.enablerefercheck
\r
41 local useconsultemplate = msbConf.systemConf.useconsultemplate
\r
43 ---------------------------------------------------------------
\r
45 -- determine whether it is websocket request
\r
46 -- and do internal redirect
\r
47 ---------------------------------------------------------------
\r
48 if ngx.var.uri == "/" then
\r
49 local m, err = ngx.re.match(ngx.var.host, "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$","o")
\r
51 return ngx.exec("@defaultpage")
\r
55 local http_upgrade = ngx_var.http_upgrade
\r
56 if(ngx_var.websocket_internal_redirect == "on") and http_upgrade and str_low(http_upgrade)== "websocket" then
\r
57 --ngx.log(ngx.ERR, "Websocket request and redirect to @customwebsocket")
\r
58 return ngx.exec("@customwebsocket")
\r
61 ---------------------------------------------------------------
\r
63 -- svcnames:service names registered under this port
\r
64 ---------------------------------------------------------------
\r
65 local req_res = ngx_var.uri
\r
66 local svc_type = ngx_var.svc_type
\r
67 local key_prefix = svc_get_key_prefix()
\r
69 local custom_svc_keypattern = tbl_concat({key_prefix,"custom","*"},":")
\r
71 local get_svckey_custom = function(svcname)
\r
72 return tbl_concat({key_prefix,"custom",svcname},":")
\r
75 local svcnames,err = dbclient.load_customsvcnames(custom_svc_keypattern)
\r
76 if not svcnames then
\r
77 error_svc_not_found("Failed to load the route table!","keypattern--"..custom_svc_keypattern)
\r
80 ---------------------------------------------------------------
\r
81 --step1:run the match process(check whether the request
\r
82 -- match the name in the svcnames one by one)
\r
83 -- and return the matched serice info
\r
84 ---------------------------------------------------------------
\r
85 local matchedsvcname
\r
88 --add by wangyg:20160418 special handler for refer
\r
89 local matched_usingrefer = false
\r
90 --end of add by wangyg:20160418 special handler for refer
\r
91 for _, svcname in ipairs(svcnames) do
\r
92 if (svcname == "/") then
\r
93 svc_key = get_svckey_custom(svcname)
\r
94 local svc_info,err = dbclient.load_serviceinfo(svc_key)
\r
95 if svc_info and svc_isactive(svc_info)then
\r
96 matchedsvcname = svcname
\r
101 local from, to, err = ngx.re.find(req_res, "^"..svcname.."(/(.*))?$", "jo")
\r
102 --check whether svcname is the prefix of the req uri
\r
104 svc_key = get_svckey_custom(svcname)
\r
105 local svc_info,err = dbclient.load_serviceinfo(svc_key)
\r
106 if svc_info and svc_isactive(svc_info) then
\r
107 matchedsvcname = svcname
\r
115 ---------------------------------------------------------------
\r
116 --step1.1:additional process,test against the refer
\r
117 -- similar to step1
\r
118 ---------------------------------------------------------------
\r
119 --add by wangyg:20160418 special handler for refer
\r
120 if not matchedsvcname and enablerefercheck then
\r
121 local refer = ngx_var.http_referer
\r
122 if(refer and refer~="") then
\r
123 for _, svcname in ipairs(svcnames) do
\r
124 local urlreg ="^(https://|http://|)(([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5])))\\.)(([0-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5])))\\.){2}([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5])))(:\\d{1,5})?"..svcname.."(/(.*))?$";
\r
125 local from, to, err = ngx.re.find(refer, urlreg, "jo")
\r
126 ----check whether svcname is the prefix of the req refer
\r
128 svc_key = get_svckey_custom(svcname)
\r
129 local svc_info,err = dbclient.load_serviceinfo(svc_key)
\r
130 if svc_info and svc_isactive(svc_info) then
\r
131 matchedsvcname = svcname
\r
133 matched_usingrefer = true
\r
140 --end of add by wangyg:20160418 special handler for refer
\r
142 if not matchedsvcname or tbl_isempty(svcinfo) then
\r
143 error_svc_not_found("No route found for this request!","custom not match")
\r
146 local svc_url = svc_get_url(svcinfo,svc_type)
\r
148 ---------------------------------------------------------------
\r
149 --step2:rewrite the request uri using the svcinfo
\r
150 ---------------------------------------------------------------
\r
151 local rewrited_uri =""
\r
152 if (matchedsvcname == "/") then
\r
153 --special handling: if "/" matched, contact directly
\r
154 rewrited_uri = svc_url..req_res
\r
156 --rewrited_uri = ngx.re.sub(req_res, "^"..matchedsvcname.."(.*)", svc_url.."$1", "o")
\r
157 local newuri,n,err = ngx.re.sub(req_res, "^"..matchedsvcname.."(/.*)?", svc_url.."$1", "o")
\r
158 --add by wangyg:20160418 special handler for refer
\r
159 if(n==0 and matched_usingrefer) then newuri = svc_url..req_res end --special handling if matched using refer
\r
160 --end of add by wangyg:20160418 special handler for refer
\r
161 rewrited_uri = newuri
\r
163 --if (rewrited_uri == "") then rewrited_uri = "/" end --avoid throws internal error when it is empty
\r
164 if (rewrited_uri == "") then return ngx.redirect(ngx.var.uri.."/") end
\r
165 ngx.req.set_uri(rewrited_uri)
\r
167 --set the matched service info,used in the proxy_redirect directive
\r
168 ngx_var.svc_name = matchedsvcname
\r
169 ngx_var.svc_url = svc_url
\r
171 --log the route info
\r
172 log("matched",matchedsvcname)
\r
173 if(matched_usingrefer) then log("matched_usingrefer",true) end
\r
174 --log("rewrited_uri",rewrited_uri)
\r
176 ---------------------------------------------------------------
\r
177 --step2.1:store the svcinfo in the context, plugins may use it
\r
178 ---------------------------------------------------------------
\r
179 ngx_ctx.svcinfo = svcinfo
\r
181 ---------------------------------------------------------------
\r
182 --step3:process the proxy upstream part
\r
183 -- con1-using consul template:set the upstream name
\r
184 -- con2-using msb balancer:query the backserver list and store in the ctx
\r
185 ---------------------------------------------------------------
\r
186 --set the http_protocol used by proxy_pass directive
\r
187 ngx_var.http_protocol = svc_get_backend_protocol(svcinfo)
\r
189 if svc_use_own_upstream(svcinfo) then
\r
190 local consul_servicename = svcinfo.spec["consulServiceName"]
\r
191 if not consul_servicename or consul_servicename == "" then
\r
192 error_upstream_not_found()
\r
194 ngx_var.backend = consul_servicename
\r
195 ngx.ctx.use_ownupstream = true
\r
197 local backservers = svcinfo.spec.nodes
\r
198 if tbl_isempty(backservers) then
\r
199 error_svc_not_found("No active backend server found!","key--"..svc_key)
\r
201 ngx_ctx.backservers = backservers
\r
202 ngx_ctx.svc_key = svc_key
\r