| 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 |