src/server/safs/proxy.c

changeset 672
226bfd584075
parent 671
879005903b2b
equal deleted inserted replaced
671:879005903b2b 672:226bfd584075
28 28
29 #include "proxy.h" 29 #include "proxy.h"
30 30
31 #include <sys/socket.h> 31 #include <sys/socket.h>
32 #include <arpa/inet.h> 32 #include <arpa/inet.h>
33 #include <ctype.h>
34 #include <string.h>
33 35
34 #include "../util/pblock.h" 36 #include "../util/pblock.h"
35 #include "../proxy/httpclient.h" 37 #include "../proxy/httpclient.h"
36 38
37 // Gets the uri part from an http request line 39 // Gets the uri part from an http request line
72 74
73 return uri; 75 return uri;
74 76
75 } 77 }
76 78
77 typedef struct ProxyData { 79 typedef struct ProxyRequest {
78 Session *sn; 80 Session *sn;
79 Request *rq; 81 Request *rq;
80 } ProxyData; 82
83 /*
84 * request header rewrite map
85 * name: header name
86 * value: header value or an empty string, if the header should be removed
87 */
88 pblock *request_header_rewrite;
89
90 /*
91 * response header rewrite map
92 * name: header name
93 * value: header value or an empty string, if the header should be removed
94 */
95 pblock *response_header_rewrite;
96
97 /*
98 * Has the response started (proxy_response_start called)
99 */
100 int response_started;
101 } ProxyRequest;
81 102
82 static int proxy_response_start(HttpClient *client, int status, char *message, void *userdata) { 103 static int proxy_response_start(HttpClient *client, int status, char *message, void *userdata) {
83 ProxyData *proxy = userdata; 104 ProxyRequest *proxy = userdata;
105
106 HeaderArray *headers = client->response_headers;
107 while(headers) {
108 for(int i=0;i<headers->len;i++) {
109 cxmutstr name = headers->headers[i].name;
110 cxmutstr value = headers->headers[i].value;
111 // NSAPI uses lower case header names internally
112 for(int c=0;c<name.length;c++) {
113 name.ptr[c] = tolower(name.ptr[c]);
114 }
115 // HttpClient does not 0-terminate strings
116 name.ptr[name.length] = 0;
117 // check if this header should be modified
118 char *rewrite = pblock_findval(name.ptr, proxy->response_header_rewrite);
119 if(rewrite) {
120 value = cx_mutstr(rewrite);
121 if(value.length == 0) {
122 // empty header value -> skip
123 continue;
124 }
125 }
126
127 // add header to response
128 pblock_nvlinsert(name.ptr, name.length, value.ptr, value.length, proxy->rq->srvhdrs);
129 }
130 headers = headers->next;
131 }
84 132
85 protocol_status(proxy->sn, proxy->rq, status, message); 133 protocol_status(proxy->sn, proxy->rq, status, message);
86 protocol_start_response(proxy->sn, proxy->rq); 134 protocol_start_response(proxy->sn, proxy->rq);
135 proxy->response_started = 1;
87 136
88 return 0; 137 return 0;
89 } 138 }
90 139
140 static void proxy_response_finished(HttpClient *client, void *userdata) {
141 ProxyRequest *proxy = userdata;
142
143 int ret = REQ_PROCEED;
144 if(!proxy->response_started) {
145 protocol_status(proxy->sn, proxy->rq, 502, NULL);
146 ret = REQ_ABORTED;
147 }
148
149 http_client_free(client);
150
151 nsapi_function_return(proxy->sn, proxy->rq, ret);
152 }
153
91 static ssize_t proxy_response_write(HttpClient *client, void *buf, size_t nbytes, void *userdata) { 154 static ssize_t proxy_response_write(HttpClient *client, void *buf, size_t nbytes, void *userdata) {
92 ProxyData *proxy = userdata; 155 ProxyRequest *proxy = userdata;
93 ssize_t ret = net_write(proxy->sn->csd, buf, nbytes); 156 ssize_t ret = net_write(proxy->sn->csd, buf, nbytes);
94 // TODO: handle errors 157 // TODO: handle errors
95 return ret; 158 return ret;
96 } 159 }
97 160
102 165
103 cxstring uri = get_uri_from_clfreq(clfreq); 166 cxstring uri = get_uri_from_clfreq(clfreq);
104 if(uri.length == 0) { 167 if(uri.length == 0) {
105 return REQ_ABORTED; 168 return REQ_ABORTED;
106 } 169 }
170
171 // remove some response headers, that were previously set by ObjectType
172 // or other SAFs
173 pblock_removekey(pb_key_content_type, rq->srvhdrs);
174
175 ProxyRequest *proxy = pool_malloc(sn->pool, sizeof(ProxyRequest));
176 proxy->sn = sn;
177 proxy->rq = rq;
178 proxy->request_header_rewrite = pblock_create_pool(sn->pool, 16);
179 proxy->response_header_rewrite = pblock_create_pool(sn->pool, 16);
180 proxy->response_started = 0;
181
182 // some request/response headers should be removed or altered
183 // an empty string means, the header should be removed
184 pblock_nvinsert("host", "", proxy->request_header_rewrite);
185 pblock_nvinsert("connection", "", proxy->request_header_rewrite);
186 pblock_nvinsert("server", "", proxy->response_header_rewrite);
187 pblock_nvinsert("connection", "", proxy->response_header_rewrite);
107 188
108 // setup HttpClient 189 // setup HttpClient
109 HttpClient *client = http_client_new(ev); 190 HttpClient *client = http_client_new(ev);
110 if(!client) { 191 if(!client) {
111 return REQ_ABORTED; 192 return REQ_ABORTED;
125 struct sockaddr_in address; 206 struct sockaddr_in address;
126 inet_pton(AF_INET, "127.0.0.1", &address.sin_addr); 207 inet_pton(AF_INET, "127.0.0.1", &address.sin_addr);
127 address.sin_family = AF_INET; 208 address.sin_family = AF_INET;
128 address.sin_port = htons(8080); 209 address.sin_port = htons(8080);
129 http_client_set_addr(client, (struct sockaddr*)&address, sizeof(address)); 210 http_client_set_addr(client, (struct sockaddr*)&address, sizeof(address));
211 http_client_add_request_header(client, cx_mutstr("host"), cx_mutstr("localhost:8080"));
130 212
131 // add request headers to the client 213 // add request headers to the client
132 CxIterator i = pblock_iterator(rq->headers); 214 CxIterator i = pblock_iterator(rq->headers);
133 cx_foreach(pb_entry*, entry, i) { 215 cx_foreach(pb_entry*, entry, i) {
134 // TODO: don't pass all headers 216 cxmutstr header_value;
135 if(http_client_add_request_header(client, cx_mutstr(entry->param->name), cx_mutstr(entry->param->value))) { 217 char *rewrite_header = pblock_findval(entry->param->name, proxy->request_header_rewrite);
218 if(rewrite_header) {
219 header_value = cx_mutstr(rewrite_header);
220 if(header_value.length == 0) {
221 continue;
222 }
223 } else {
224 header_value = cx_mutstr(entry->param->value);
225 }
226
227 if(http_client_add_request_header(client, cx_mutstr(entry->param->name), header_value)) {
136 http_client_free(client); 228 http_client_free(client);
137 return REQ_ABORTED; 229 return REQ_ABORTED;
138 } 230 }
139 } 231 }
140 232
141 ProxyData *proxy = pool_malloc(sn->pool, sizeof(ProxyData));
142 proxy->sn = sn;
143 proxy->rq = rq;
144 client->response_start = proxy_response_start; 233 client->response_start = proxy_response_start;
145 client->response_start_userdata = proxy; 234 client->response_start_userdata = proxy;
146 client->response_body_write = proxy_response_write; 235 client->response_body_write = proxy_response_write;
147 client->response_body_write_userdata = proxy; 236 client->response_body_write_userdata = proxy;
148 237
155 244
156 return REQ_PROCESSING; 245 return REQ_PROCESSING;
157 } 246 }
158 247
159 248
249
250 /* --------------------------------- Tests --------------------------------- */
160 251
161 static CX_TEST(test_safs_proxy_get_uri_from_clfreq) { 252 static CX_TEST(test_safs_proxy_get_uri_from_clfreq) {
162 CX_TEST_DO { 253 CX_TEST_DO {
163 cxstring ret; 254 cxstring ret;
164 255

mercurial