Initial code import
[msb/apigateway.git] / openresty-ext / src / assembly / resources / openresty / nginx / luaext / rewrite / commonrewrite.lua
1 --[[\r
2 \r
3     Copyright (C) 2016 ZTE, Inc. and others. All rights reserved. (ZTE)\r
4 \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
8 \r
9             http://www.apache.org/licenses/LICENSE-2.0\r
10 \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
16 \r
17 --]]\r
18 \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
25 \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 \r
32 local str_sub = string.sub\r
33 local str_len = string.len\r
34 local str_low = string.lower\r
35 local ngx_var = ngx.var\r
36 local ngx_ctx = ngx.ctx\r
37 local log = log_util.log\r
38 \r
39 local defaultport = msbConf.systemConf.defaultport\r
40 local defaultprefix = msbConf.systemConf.defaultprefix\r
41 local enablefullsearch = msbConf.systemConf.enablefullsearch\r
42 local useconsultemplate = msbConf.systemConf.useconsultemplate\r
43 local apiRelatedTypes = svcConf.apiRelatedTypes\r
44 local urlfieldMap = svcConf.urlfieldMap\r
45 \r
46 local donotfound = function()\r
47         if enablefullsearch then\r
48                 -- test against the custom services after the commonrewrite phase\r
49                 ngx.status = ngx.HTTP_GONE\r
50         else\r
51                 ngx.status = ngx.HTTP_NOT_FOUND\r
52                 ngx.say("service info not found!")\r
53         end\r
54         return ngx.exit(ngx.status)\r
55 end\r
56 \r
57 ---------------------------------------------------------------\r
58 --preCheck:\r
59 --     determine whether it is websocket request \r
60 --     and do internal redirect\r
61 ---------------------------------------------------------------\r
62 local http_upgrade = ngx_var.http_upgrade\r
63 if(ngx_var.websocket_internal_redirect == "on") and http_upgrade and str_low(http_upgrade) == "websocket" then\r
64         ngx.log(ngx.ERR, "Websocket request and redirect to @commonwebsocket")\r
65         return ngx.exec("@commonwebsocket");\r
66 end\r
67 \r
68 ---------------------------------------------------------------\r
69 --step0:Preparation\r
70 --      svc_info_key\r
71 --      svc_server_keypattern\r
72 ---------------------------------------------------------------\r
73 local svc_name = ngx_var.svc_name\r
74 local req_res  = ngx_var.req_res\r
75 local svc_type = ngx_var.svc_type\r
76 \r
77 local sys_prefix = ""\r
78 local server_port = ngx_var.server_port\r
79 if(server_port == defaultport) then\r
80         sys_prefix = defaultprefix\r
81 else\r
82         sys_prefix = server_port\r
83 end\r
84 \r
85 local svc_info_key = ""\r
86 local svc_server_keypattern = ""\r
87 local upstream_name_consultemplate = ""\r
88 if(apiRelatedTypes[svc_type]) then\r
89         -- process version info first\r
90         local version1 = ngx_var.svc_version1\r
91         local version2 = ngx_var.svc_version2\r
92         local version = ""\r
93         -- check version info appearing befor or after\r
94         if(not version2) then version2 = "" end --convert nil to empty sting avoiding throw error\r
95         if(not version1 or version1 == "") then\r
96                 version = version2\r
97         else\r
98                 version = version1\r
99                 req_res = version2..req_res\r
100         end\r
101         -- remove the slash in front of the version (e.g. /V1.0)\r
102         local svc_version=str_sub(version,2,str_len(version))\r
103         svc_info_key = tbl_concat({sys_prefix,"api",svc_name,svc_version,"info"},":")\r
104         svc_server_keypattern = tbl_concat({sys_prefix,"api",svc_name,svc_version,"lb:server*"},":")\r
105         upstream_name_consultemplate = svc_name\r
106 else\r
107         svc_info_key = tbl_concat({sys_prefix,"iui",svc_name,"info"},":")\r
108         svc_server_keypattern = tbl_concat({sys_prefix,"iui",svc_name,"lb:server*"},":")\r
109         upstream_name_consultemplate = "IUI_"..svc_name\r
110 end\r
111 \r
112 ---------------------------------------------------------------\r
113 --step1:query the service info from share memory or back db\r
114 --      svcinfo: the requested service information\r
115 ---------------------------------------------------------------\r
116 local svcinfo = dbclient.load_serviceinfo(svc_info_key)\r
117 if not svc_isactive(svcinfo) then \r
118         donotfound()\r
119 end\r
120 \r
121 local svc_url = svcinfo[urlfieldMap[svc_type]]\r
122 if not svc_url then \r
123         donotfound()\r
124 end\r
125 \r
126 ---------------------------------------------------------------\r
127 --step2:rewrite the request uri using the svcinfo\r
128 ---------------------------------------------------------------\r
129 local rewrited_uri = svc_url..req_res\r
130 --special handling: avoid throws internal error when it is empty\r
131 if (rewrited_uri == "") then rewrited_uri = "/" end \r
132 ngx.req.set_uri(rewrited_uri)\r
133 \r
134 log("matchedservice",svc_name)\r
135 log("rewrited_uri",rewrited_uri)\r
136 ---------------------------------------------------------------\r
137 --step2.1:if this service is inter-system,add custom http header\r
138 ---------------------------------------------------------------\r
139 svc_setauthheader(svcinfo)\r
140 \r
141 ---------------------------------------------------------------\r
142 --step3:process the proxy upstream part\r
143 -- con1-using consul template:set the upstream name\r
144 -- con2-using msb balancer:query the server list and store in the ctx\r
145 ---------------------------------------------------------------\r
146 if useconsultemplate and svc_isautodiscover(svcinfo) then \r
147         ngx_var.backend = upstream_name_consultemplate\r
148 else\r
149         local backservers = dbclient.load_backservers(svc_server_keypattern) \r
150         if tbl_isempty(backservers) then\r
151                 donotfound()\r
152         end\r
153         ngx_ctx.backservers = backservers\r
154         ngx_ctx.svcserverpattern = svc_server_keypattern\r
155 end