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 svcConf = require('conf.svcconf')
\r
21 local dbclient = require('dao.db_access')
\r
22 local tbl_util = require('lib.utils.table_util')
\r
23 local svc_util = require('lib.utils.svc_util')
\r
24 local log_util = require('lib.utils.log_util')
\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_setauthheader = svc_util.setauthheader
\r
30 local svc_isautodiscover = svc_util.isautodiscover
\r
31 local str_sub = string.sub
\r
32 local str_len = string.len
\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
38 local defaultport = msbConf.systemConf.defaultport
\r
39 local defaultprefix = msbConf.systemConf.defaultprefix
\r
40 local enablerefercheck = msbConf.systemConf.enablerefercheck
\r
41 local useconsultemplate = msbConf.systemConf.useconsultemplate
\r
42 local urlfieldMap = svcConf.urlfieldMap
\r
44 local donotfound = function()
\r
45 ngx.status = ngx.HTTP_NOT_FOUND
\r
46 ngx.say("service info not found!")
\r
47 return ngx.exit(ngx.status)
\r
50 ---------------------------------------------------------------
\r
52 -- determine whether it is websocket request
\r
53 -- and do internal redirect
\r
54 ---------------------------------------------------------------
\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 sys_prefix = ""
\r
66 local server_port = ngx_var.server_port
\r
67 if(server_port == defaultport) then
\r
68 sys_prefix = defaultprefix
\r
70 sys_prefix = server_port
\r
73 local custom_svc_keypattern = tbl_concat({sys_prefix,"custom","*"},":")
\r
75 local get_svcinfokey_custom = function(svcname)
\r
76 return tbl_concat({sys_prefix,"custom",svcname,"info"},":")
\r
79 local get_svcserverpattern_custom = function(svcname)
\r
80 return tbl_concat({sys_prefix,"custom",svcname,"lb:server*"},":")
\r
83 local svcnames,err = dbclient.load_customsvcnames(custom_svc_keypattern)
\r
84 if not svcnames then
\r
88 ---------------------------------------------------------------
\r
89 --step1:run the match process(check whether the request
\r
90 -- match the name in the svcnames one by one)
\r
91 -- and return the matched serice info
\r
92 ---------------------------------------------------------------
\r
93 local req_res = ngx_var.uri
\r
94 local svc_type = ngx_var.svc_type
\r
95 local matchedsvcname
\r
97 --add by wangyg:20160418 special handler for refer
\r
98 local matched_usingrefer = false
\r
99 --end of add by wangyg:20160418 special handler for refer
\r
100 for _, svcname in ipairs(svcnames) do
\r
101 if (svcname == "/") then
\r
102 local svc_info_key = get_svcinfokey_custom(svcname)
\r
103 local svc_info,err = dbclient.load_serviceinfo(svc_info_key)
\r
104 if svc_info and svc_isactive(svc_info)then
\r
105 matchedsvcname = svcname
\r
110 local from, to, err = ngx.re.find(req_res, "^"..svcname.."(/(.*))?$", "jo")
\r
111 --check whether svcname is the prefix of the req uri
\r
113 local svc_info_key = get_svcinfokey_custom(svcname)
\r
114 local svc_info,err = dbclient.load_serviceinfo(svc_info_key)
\r
115 if svc_info and svc_isactive(svc_info) then
\r
116 matchedsvcname = svcname
\r
124 ---------------------------------------------------------------
\r
125 --step1.1:additional process,test against the refer
\r
126 -- similar to step1
\r
127 ---------------------------------------------------------------
\r
128 --add by wangyg:20160418 special handler for refer
\r
129 if not matchedsvcname and enablerefercheck then
\r
130 local refer = ngx_var.http_referer
\r
131 if(refer and refer~="") then
\r
132 for _, svcname in ipairs(svcnames) do
\r
133 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
134 local from, to, err = ngx.re.find(refer, urlreg, "jo")
\r
135 ----check whether svcname is the prefix of the req refer
\r
137 local svc_info_key = get_svcinfokey_custom(svcname)
\r
138 local svc_info,err = dbclient.load_serviceinfo(svc_info_key)
\r
139 if svc_info and svc_isactive(svc_info) then
\r
140 matchedsvcname = svcname
\r
142 matched_usingrefer = true
\r
149 --end of add by wangyg:20160418 special handler for refer
\r
151 if not matchedsvcname or tbl_isempty(svcinfo) then
\r
155 local svc_url = svcinfo[urlfieldMap[svc_type]]
\r
156 if not svc_url then
\r
160 ---------------------------------------------------------------
\r
161 --step2:rewrite the request uri using the svcinfo
\r
162 ---------------------------------------------------------------
\r
163 local rewrited_uri =""
\r
164 if (matchedsvcname == "/") then
\r
165 --special handling: if "/" matched, contact directly
\r
166 rewrited_uri = svc_url..req_res
\r
168 --rewrited_uri = ngx.re.sub(req_res, "^"..matchedsvcname.."(.*)", svc_url.."$1", "o")
\r
169 local newuri,n,err = ngx.re.sub(req_res, "^"..matchedsvcname.."(/.*)?", svc_url.."$1", "o")
\r
170 --add by wangyg:20160418 special handler for refer
\r
171 if(n==0 and matched_usingrefer) then newuri = svc_url..req_res end --special handling if matched using refer
\r
172 --end of add by wangyg:20160418 special handler for refer
\r
173 rewrited_uri = newuri
\r
175 if (rewrited_uri == "") then rewrited_uri = "/" end --avoid throws internal error when it is empty
\r
176 ngx.req.set_uri(rewrited_uri)
\r
178 --set the matched service info,used in the proxy_redirect directive
\r
179 ngx_var.svc_name = matchedsvcname
\r
180 ngx_var.svc_url = svc_url
\r
182 --log the route info
\r
183 log("matchedservice",matchedsvcname)
\r
184 if(matched_usingrefer) then log("matched_usingrefer",true) end
\r
185 log("rewrited_uri",rewrited_uri)
\r
187 ---------------------------------------------------------------
\r
188 --step2.1:if this service is inter-system,add custom http header
\r
189 ---------------------------------------------------------------
\r
190 svc_setauthheader(svcinfo)
\r
192 ---------------------------------------------------------------
\r
193 --step3:process the proxy upstream part
\r
194 -- con1-using consul template:set the upstream name
\r
195 -- con2-using msb balancer:query the backserver list and store in the ctx
\r
196 ---------------------------------------------------------------
\r
197 if useconsultemplate and svc_isautodiscover(svcinfo) then
\r
198 --FIX ME:if svcname contains "/", the upstream name may be illegal
\r
199 ngx_var.backend = ngx.re.sub(matchedsvcname, "^/(.*)", "$1", "o")
\r
201 local svc_server_keypattern = get_svcserverpattern_custom(matchedsvcname)
\r
202 local backservers,err = dbclient.load_backservers(svc_server_keypattern)
\r
203 if tbl_isempty(backservers) then
\r
206 ngx_ctx.backservers = backservers
\r
207 ngx_ctx.svcserverpattern = svc_server_keypattern
\r