| 140 EventHandler *ev = sn->ev; |
142 EventHandler *ev = sn->ev; |
| 141 const char *method = pblock_findkeyval(pb_key_method, rq->reqpb); |
143 const char *method = pblock_findkeyval(pb_key_method, rq->reqpb); |
| 142 const char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); |
144 const char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); |
| 143 const char *query = pblock_findkeyval(pb_key_query, rq->reqpb); |
145 const char *query = pblock_findkeyval(pb_key_query, rq->reqpb); |
| 144 |
146 |
| |
147 const char *location = pblock_findval("location", param); |
| |
148 if(location) { |
| |
149 cxstring loc = cx_str(location); |
| |
150 if(cx_strprefix(uri, loc)) { |
| |
151 if(loc.length > 0 && loc.ptr[loc.length-1] == '/') { |
| |
152 uri += loc.length - 1; |
| |
153 } else { |
| |
154 uri += loc.length; |
| |
155 } |
| |
156 if(uri[0] == '\0') { |
| |
157 uri = "/"; |
| |
158 } |
| |
159 } else { |
| |
160 // location does not match |
| |
161 return REQ_NOACTION; |
| |
162 } |
| |
163 } |
| |
164 |
| |
165 const char *server_url = pblock_findval("proxy-url", rq->vars); |
| |
166 if(!server_url) { |
| |
167 server_url = pblock_findval("url", param); |
| |
168 if(!server_url) { |
| |
169 log_ereport(LOG_MISCONFIG, "reverse-proxy: missing server url"); |
| |
170 return REQ_ABORTED; |
| |
171 } |
| |
172 } |
| |
173 WSUri srv_url; |
| |
174 if(!util_parse_uri(server_url, &srv_url)) { |
| |
175 log_ereport(LOG_MISCONFIG, "reverse-proxy: invalid server url: %s", server_url); |
| |
176 return REQ_ABORTED; |
| |
177 } |
| |
178 |
| |
179 char srvport[16]; |
| |
180 snprintf(srvport, 16, "%d", (int)srv_url.port); |
| |
181 |
| |
182 char srvhost_static[256]; |
| |
183 char *srvhost; |
| |
184 if(srv_url.hostlen < 255) { |
| |
185 memcpy(srvhost_static, srv_url.host, srv_url.hostlen); |
| |
186 srvhost_static[srv_url.hostlen] = 0; |
| |
187 srvhost = srvhost_static; |
| |
188 } else { |
| |
189 srvhost = pool_malloc(sn->pool, srv_url.hostlen + 1); |
| |
190 if(!srvhost) { |
| |
191 return REQ_ABORTED; |
| |
192 } |
| |
193 memcpy(srvhost, srv_url.host, srv_url.hostlen); |
| |
194 srvhost[srv_url.hostlen] = 0; |
| |
195 } |
| |
196 |
| |
197 // build the new uri using <srv_url.path><uri>?<query> |
| |
198 if(srv_url.pathlen > 0 && srv_url.path[srv_url.pathlen-1] == '/') { |
| |
199 srv_url.pathlen--; |
| |
200 } |
| |
201 |
| 145 cxmutstr new_uri = CX_NULLSTR; |
202 cxmutstr new_uri = CX_NULLSTR; |
| 146 size_t uri_len = strlen(uri); |
203 size_t uri_len = strlen(uri); |
| 147 size_t query_len = query ? strlen(query) : 0; |
204 size_t query_len = query ? strlen(query) : 0; |
| 148 size_t new_uri_alloc = ((uri_len + query_len) * 3) + 2; |
205 size_t new_uri_alloc = ((uri_len + query_len) * 3) + 2 + srv_url.pathlen; |
| 149 new_uri.ptr = pool_malloc(sn->pool, new_uri_alloc); |
206 new_uri.ptr = pool_malloc(sn->pool, new_uri_alloc); |
| 150 new_uri.length = util_uri_escape_s(new_uri.ptr, new_uri_alloc, uri); |
207 if(!new_uri.ptr) { |
| |
208 return REQ_ABORTED; |
| |
209 } |
| |
210 |
| |
211 char *s = new_uri.ptr; |
| |
212 size_t s_len = new_uri_alloc; |
| |
213 if(srv_url.pathlen > 0) { |
| |
214 memcpy(s, srv_url.path, srv_url.pathlen); |
| |
215 s += srv_url.pathlen; |
| |
216 new_uri.length = srv_url.pathlen; |
| |
217 s_len -= srv_url.pathlen; |
| |
218 } |
| |
219 |
| |
220 new_uri.length += util_uri_escape_s(s, s_len, uri); |
| 151 if(new_uri.length > 0 && query_len > 0) { |
221 if(new_uri.length > 0 && query_len > 0) { |
| 152 new_uri.ptr[new_uri.length] = '?'; |
222 new_uri.ptr[new_uri.length] = '?'; |
| 153 memcpy(new_uri.ptr + new_uri.length + 1, query, query_len + 1); |
223 memcpy(new_uri.ptr + new_uri.length + 1, query, query_len + 1); |
| 154 new_uri.length = new_uri.length + 1 + query_len; |
224 new_uri.length += query_len + 1; |
| 155 } |
225 } |
| 156 |
226 |
| 157 // remove some response headers, that were previously set by ObjectType |
227 // remove some response headers, that were previously set by ObjectType |
| 158 // or other SAFs |
228 // or other SAFs |
| 159 pblock_removekey(pb_key_content_type, rq->srvhdrs); |
229 pblock_removekey(pb_key_content_type, rq->srvhdrs); |
| 184 http_client_free(client); |
254 http_client_free(client); |
| 185 return REQ_ABORTED; |
255 return REQ_ABORTED; |
| 186 } |
256 } |
| 187 |
257 |
| 188 if(http_client_set_uri_len(client, new_uri.ptr, new_uri.length)) { |
258 if(http_client_set_uri_len(client, new_uri.ptr, new_uri.length)) { |
| |
259 http_client_free(client); |
| |
260 return REQ_ABORTED; |
| |
261 } |
| |
262 |
| |
263 // set server address |
| |
264 struct addrinfo hints = { 0 }; |
| |
265 hints.ai_family = AF_UNSPEC; |
| |
266 hints.ai_socktype = SOCK_STREAM; |
| |
267 struct addrinfo *srv_addr; |
| |
268 if(getaddrinfo(srvhost, srvport, &hints, &srv_addr)) { |
| |
269 http_client_free(client); |
| |
270 log_ereport(LOG_FAILURE, "reverse-proxy: getaddr failed for address %s: %s", srvhost, strerror(errno)); |
| |
271 return REQ_ABORTED; |
| |
272 } |
| |
273 |
| |
274 int ret = http_client_set_addr(client, srv_addr->ai_addr, srv_addr->ai_addrlen); |
| |
275 freeaddrinfo(srv_addr); |
| |
276 if(ret) { |
| 189 http_client_free(client); |
277 http_client_free(client); |
| 190 return REQ_ABORTED; |
278 return REQ_ABORTED; |
| 191 } |
279 } |
| 192 |
280 |
| 193 // test address |
281 // test address |