root/src/noit_rest.c

Revision 74680031f0fd1b7d90765cfb65a788edb15d7d74, 21.6 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 months ago)

strlen of the subject would be useful here (how'd this ever work?)

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
16  *       of its contributors may be used to endorse or promote products
17  *       derived from this software without specific prior written
18  *       permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "noit_defines.h"
34 #include "noit_listener.h"
35 #include "noit_http.h"
36 #include "noit_rest.h"
37 #include "noit_conf.h"
38
39 #include <pcre.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <sys/mman.h>
43 #include <errno.h>
44
45 struct rest_xml_payload {
46   char *buffer;
47   xmlDocPtr indoc;
48   int len;
49   int allocd;
50   int complete;
51 };
52
53 struct rest_raw_payload {
54   char *buffer;
55   int len;
56   int allocd;
57   int complete;
58 };
59
60 struct rest_url_dispatcher {
61   char *method;
62   pcre *expression;
63   pcre_extra *extra;
64   rest_request_handler handler;
65   rest_authorize_func_t auth;
66   /* Chain to the next one */
67   struct rest_url_dispatcher *next;
68 };
69
70 struct rule_container {
71   char *base;
72   struct rest_url_dispatcher *rules;
73   struct rest_url_dispatcher *rules_endptr;
74 };
75 noit_hash_table dispatch_points = NOIT_HASH_EMPTY;
76
77 struct noit_rest_acl_rule {
78   noit_boolean allow;
79   pcre *url;
80   pcre *cn;
81   struct noit_rest_acl_rule *next;
82 };
83 struct noit_rest_acl {
84   noit_boolean allow;
85   pcre *url;
86   pcre *cn;
87   struct noit_rest_acl_rule *rules;
88   struct noit_rest_acl *next;
89 };
90
91 static noit_hash_table mime_type_defaults = NOIT_HASH_EMPTY;
92
93 static struct noit_rest_acl *global_rest_acls = NULL;
94
95 static int
96 noit_http_rest_permission_denied(noit_http_rest_closure_t *restc,
97                                  int npats, char **pats) {
98   noit_http_session_ctx *ctx = restc->http_ctx;
99   noit_http_response_standard(ctx, 403, "DENIED", "text/xml");
100   noit_http_response_end(ctx);
101   return 0;
102 }
103 static rest_request_handler
104 noit_http_get_handler(noit_http_rest_closure_t *restc) {
105   struct rule_container *cont = NULL;
106   struct rest_url_dispatcher *rule;
107   noit_http_request *req = noit_http_session_request(restc->http_ctx);
108   const char *uri_str;
109   const char *eoq, *eob;
110   uri_str = noit_http_request_uri_str(req);
111   eoq = uri_str + strlen(uri_str);
112   eob = eoq - 1;
113
114   /* find the right base */
115   while(1) {
116     void *vcont;
117     while(eob >= uri_str && *eob != '/') eob--;
118     if(eob < uri_str) break; /* off the front */
119     if(noit_hash_retrieve(&dispatch_points, uri_str,
120                           eob - uri_str + 1, &vcont)) {
121       cont = vcont;
122       eob++; /* move past the determined base */
123       break;
124     }
125     eob--;
126   }
127   if(!cont) return NULL;
128   for(rule = cont->rules; rule; rule = rule->next) {
129     int ovector[30];
130     int cnt;
131     if(strcmp(rule->method, noit_http_request_method_str(req))) continue;
132     if((cnt = pcre_exec(rule->expression, rule->extra, eob, eoq - eob, 0, 0,
133                         ovector, sizeof(ovector)/sizeof(*ovector))) > 0) {
134       /* We match, set 'er up */
135       restc->fastpath = rule->handler;
136       restc->nparams = cnt - 1;
137       if(restc->nparams) {
138         restc->params = calloc(restc->nparams, sizeof(*restc->params));
139         for(cnt = 0; cnt < restc->nparams; cnt++) {
140           int start = ovector[(cnt+1)*2];
141           int end = ovector[(cnt+1)*2+1];
142           restc->params[cnt] = malloc(end - start + 1);
143           memcpy(restc->params[cnt], eob + start, end - start);
144           restc->params[cnt][end - start] = '\0';
145         }
146       }
147       if(rule->auth && !rule->auth(restc, restc->nparams, restc->params))
148         return noit_http_rest_permission_denied;
149       return restc->fastpath;
150     }
151   }
152   return NULL;
153 }
154 noit_boolean
155 noit_http_rest_client_cert_auth(noit_http_rest_closure_t *restc,
156                                int npats, char **pats) {
157   struct noit_rest_acl *acl;
158   struct noit_rest_acl_rule *rule;
159   noit_http_request *req = noit_http_session_request(restc->http_ctx);
160   const char *uri_str;
161   const char *remote_cn = "";
162   int ovector[30];
163
164   if(restc->remote_cn) remote_cn = restc->remote_cn;
165   uri_str = noit_http_request_uri_str(req);
166   for(acl = global_rest_acls; acl; acl = acl->next) {
167     if(acl->cn && pcre_exec(acl->cn, NULL, remote_cn, strlen(remote_cn), 0, 0,
168                             ovector, sizeof(ovector)/sizeof(*ovector)) <= 0)
169       continue;
170     if(acl->url && pcre_exec(acl->url, NULL, uri_str, strlen(uri_str), 0, 0,
171                              ovector, sizeof(ovector)/sizeof(*ovector)) <= 0)
172       continue;
173     for(rule = acl->rules; rule; rule = rule->next) {
174       if(rule->cn && pcre_exec(rule->cn, NULL, remote_cn, strlen(remote_cn), 0, 0,
175                                ovector, sizeof(ovector)/sizeof(*ovector)) <= 0)
176         continue;
177       if(rule->url && pcre_exec(rule->url, NULL, uri_str, strlen(uri_str), 0, 0,
178                                 ovector, sizeof(ovector)/sizeof(*ovector)) <= 0)
179         continue;
180       return rule->allow;
181     }
182     return acl->allow;
183   }
184   return noit_false;
185 }
186 int
187 noit_http_rest_register(const char *method, const char *base,
188                         const char *expr, rest_request_handler f) {
189   return noit_http_rest_register_auth(method, base, expr, f, NULL);
190 }
191 int
192 noit_http_rest_register_auth(const char *method, const char *base,
193                              const char *expr, rest_request_handler f,
194                              rest_authorize_func_t auth) {
195   void *vcont;
196   struct rule_container *cont;
197   struct rest_url_dispatcher *rule;
198   const char *error;
199   int erroffset;
200   pcre *pcre_expr;
201   int blen = strlen(base);
202   /* base must end in a /, 'cause I said so */
203   if(blen == 0 || base[blen-1] != '/') return -1;
204   pcre_expr = pcre_compile(expr, 0, &error, &erroffset, NULL);
205   if(!pcre_expr) {
206     noitL(noit_error, "Error in rest expr(%s) '%s'@%d: %s\n",
207           base, expr, erroffset, error);
208     return -1;
209   }
210   rule = calloc(1, sizeof(*rule));
211   rule->method = strdup(method);
212   rule->expression = pcre_expr;
213   rule->extra = pcre_study(rule->expression, 0, &error);
214   rule->handler = f;
215   rule->auth = auth;
216
217   /* Make sure we have a container */
218   if(!noit_hash_retrieve(&dispatch_points, base, strlen(base), &vcont)) {
219     cont = calloc(1, sizeof(*cont));
220     cont->base = strdup(base);
221     noit_hash_store(&dispatch_points, cont->base, strlen(cont->base), cont);
222   }
223   else cont = vcont;
224
225   /* Append the rule */
226   if(cont->rules_endptr) {
227     cont->rules_endptr->next = rule;
228     cont->rules_endptr = cont->rules_endptr->next;
229   }
230   else
231     cont->rules = cont->rules_endptr = rule;
232   return 0;
233 }
234
235 static noit_http_rest_closure_t *
236 noit_http_rest_closure_alloc() {
237   noit_http_rest_closure_t *restc;
238   restc = calloc(1, sizeof(*restc));
239   return restc;
240 }
241 void
242 noit_http_rest_clean_request(noit_http_rest_closure_t *restc) {
243   int i;
244   if(restc->nparams) {
245     for(i=0;i<restc->nparams;i++) free(restc->params[i]);
246     free(restc->params);
247   }
248   if(restc->call_closure_free) restc->call_closure_free(restc->call_closure);
249   restc->call_closure_free = NULL;
250   restc->call_closure = NULL;
251   restc->nparams = 0;
252   restc->params = NULL;
253   restc->fastpath = NULL;
254 }
255 void
256 noit_http_rest_closure_free(void *v) {
257   noit_http_rest_closure_t *restc = v;
258   free(restc->remote_cn);
259   noit_http_rest_clean_request(restc);
260   free(restc);
261 }
262
263 int
264 noit_rest_request_dispatcher(noit_http_session_ctx *ctx) {
265   noit_http_rest_closure_t *restc = noit_http_session_dispatcher_closure(ctx);
266   rest_request_handler handler = restc->fastpath;
267   if(!handler) handler = noit_http_get_handler(restc);
268   if(handler) {
269     void *old_closure = restc, *new_closure;
270     noit_http_response *res = noit_http_session_response(ctx);
271     int rv;
272     rv = handler(restc, restc->nparams, restc->params);
273     /* If the request is closed, we need to cleanup.  However
274      * if the dispatch closure has changed, the callee has done
275      * something (presumably freeing the restc in the process)
276      * and it would be unsafe for us to free it as well.
277      */
278     new_closure = noit_http_session_dispatcher_closure(ctx);
279     if(old_closure == new_closure &&
280        noit_http_response_closed(res)) noit_http_rest_clean_request(restc);
281     return rv;
282   }
283   noit_http_response_status_set(ctx, 404, "NOT FOUND");
284   noit_http_response_option_set(ctx, NOIT_HTTP_CHUNKED);
285   noit_http_rest_clean_request(restc);
286   noit_http_response_end(ctx);
287   return 0;
288 }
289
290 int
291 noit_http_rest_handler(eventer_t e, int mask, void *closure,
292                        struct timeval *now) {
293   int newmask = EVENTER_READ | EVENTER_EXCEPTION, rv, done = 0;
294   acceptor_closure_t *ac = closure;
295   noit_http_rest_closure_t *restc = ac->service_ctx;
296
297   if(mask & EVENTER_EXCEPTION || (restc && restc->wants_shutdown)) {
298 socket_error:
299     /* Exceptions cause us to simply snip the connection */
300     eventer_remove_fd(e->fd);
301     e->opset->close(e->fd, &newmask, e);
302     acceptor_closure_free(ac);
303     return 0;
304   }
305
306   if(!ac->service_ctx) {
307     const char *primer = "";
308     ac->service_ctx = restc = noit_http_rest_closure_alloc();
309     ac->service_ctx_free = noit_http_rest_closure_free;
310     restc->ac = ac;
311     restc->remote_cn = strdup(ac->remote_cn ? ac->remote_cn : "");
312     restc->http_ctx =
313         noit_http_session_ctx_new(noit_rest_request_dispatcher,
314                                   restc, e, ac);
315    
316     switch(ac->cmd) {
317       case NOIT_CONTROL_DELETE:
318         primer = "DELE";
319         break;
320       case NOIT_CONTROL_GET:
321         primer = "GET ";
322         break;
323       case NOIT_CONTROL_HEAD:
324         primer = "HEAD";
325         break;
326       case NOIT_CONTROL_POST:
327         primer = "POST";
328         break;
329       case NOIT_CONTROL_PUT:
330         primer = "PUT ";
331         break;
332       case NOIT_CONTROL_MERGE:
333         primer = "MERG";
334         break;
335       default:
336         goto socket_error;
337     }
338     noit_http_session_prime_input(restc->http_ctx, primer, 4);
339   }
340   rv = noit_http_session_drive(e, mask, restc->http_ctx, now, &done);
341   if(done) {
342     acceptor_closure_free(ac);
343   }
344   return rv;
345 }
346
347 int
348 noit_http_rest_raw_handler(eventer_t e, int mask, void *closure,
349                            struct timeval *now) {
350   int newmask = EVENTER_READ | EVENTER_EXCEPTION, rv, done = 0;
351   acceptor_closure_t *ac = closure;
352   noit_http_rest_closure_t *restc = ac->service_ctx;
353
354   if(mask & EVENTER_EXCEPTION || (restc && restc->wants_shutdown)) {
355     /* Exceptions cause us to simply snip the connection */
356     eventer_remove_fd(e->fd);
357     e->opset->close(e->fd, &newmask, e);
358     acceptor_closure_free(ac);
359     return 0;
360   }
361   if(!ac->service_ctx) {
362     ac->service_ctx = restc = noit_http_rest_closure_alloc();
363     ac->service_ctx_free = noit_http_rest_closure_free;
364     restc->ac = ac;
365     restc->http_ctx =
366         noit_http_session_ctx_new(noit_rest_request_dispatcher,
367                                   restc, e, ac);
368   }
369   rv = noit_http_session_drive(e, mask, restc->http_ctx, now, &done);
370   if(done) {
371     acceptor_closure_free(ac);
372   }
373   return rv;
374 }
375
376 static void
377 rest_xml_payload_free(void *f) {
378   struct rest_xml_payload *xmlin = f;
379   if(xmlin->buffer) free(xmlin->buffer);
380   if(xmlin->indoc) xmlFreeDoc(xmlin->indoc);
381 }
382
383 xmlDocPtr
384 rest_get_xml_upload(noit_http_rest_closure_t *restc,
385                     int *mask, int *complete) {
386   struct rest_xml_payload *rxc;
387   noit_http_request *req = noit_http_session_request(restc->http_ctx);
388
389   if(restc->call_closure == NULL) {
390     restc->call_closure = calloc(1, sizeof(*rxc));
391     restc->call_closure_free = rest_xml_payload_free;
392   }
393   rxc = restc->call_closure;
394   while(!rxc->complete) {
395     int len;
396     if(rxc->len == rxc->allocd) {
397       char *b;
398       rxc->allocd += 32768;
399       b = rxc->buffer ? realloc(rxc->buffer, rxc->allocd) :
400                         malloc(rxc->allocd);
401       if(!b) {
402         *complete = 1;
403         return NULL;
404       }
405       rxc->buffer = b;
406     }
407     len = noit_http_session_req_consume(restc->http_ctx,
408                                         rxc->buffer + rxc->len,
409                                         rxc->allocd - rxc->len,
410                                         rxc->allocd - rxc->len,
411                                         mask);
412     if(len > 0) rxc->len += len;
413     if(len < 0 && errno == EAGAIN) return NULL;
414     else if(len < 0) {
415       *complete = 1;
416       return NULL;
417     }
418     if(rxc->len == noit_http_request_content_length(req)) {
419       rxc->indoc = xmlParseMemory(rxc->buffer, rxc->len);
420       rxc->complete = 1;
421     }
422   }
423
424   *complete = 1;
425   return rxc->indoc;
426 }
427
428 static void
429 rest_raw_payload_free(void *f) {
430   free(f);
431 }
432
433 void *
434 rest_get_raw_upload(noit_http_rest_closure_t *restc,
435                     int *mask, int *complete, int *size) {
436   struct rest_raw_payload *rxc;
437   noit_http_request *req = noit_http_session_request(restc->http_ctx);
438
439   *size = 0;
440   if(restc->call_closure == NULL) {
441     restc->call_closure = calloc(1, sizeof(*rxc));
442     restc->call_closure_free = rest_raw_payload_free;
443   }
444   rxc = restc->call_closure;
445   while(!rxc->complete) {
446     int len;
447     if(rxc->len == rxc->allocd) {
448       char *b;
449       rxc->allocd += 32768;
450       b = rxc->buffer ? realloc(rxc->buffer, rxc->allocd) :
451                         malloc(rxc->allocd);
452       if(!b) {
453         *complete = 1;
454         return NULL;
455       }
456       rxc->buffer = b;
457     }
458     len = noit_http_session_req_consume(restc->http_ctx,
459                                         rxc->buffer + rxc->len,
460                                         rxc->allocd - rxc->len,
461                                         rxc->allocd - rxc->len,
462                                         mask);
463     if(len > 0) rxc->len += len;
464     if(len < 0 && errno == EAGAIN) return NULL;
465     else if(len < 0) {
466       *complete = 1;
467       return NULL;
468     }
469     if(rxc->len == noit_http_request_content_length(req)) {
470       *size = rxc->len;
471       rxc->complete = 1;
472     }
473   }
474
475   *complete = 1;
476   return rxc->buffer;
477 }
478
479 int
480 noit_rest_simple_file_handler(noit_http_rest_closure_t *restc,
481                               int npats, char **pats) {
482   int drlen = 0;
483   const char *document_root = NULL;
484   const char *index_file = NULL;
485   noit_http_session_ctx *ctx = restc->http_ctx;
486   char file[PATH_MAX], rfile[PATH_MAX];
487   struct stat st;
488   int fd;
489   void *contents = MAP_FAILED;
490   const char *dot = NULL, *slash;
491   const char *content_type = "application/octet-stream";
492
493   if(npats != 1 ||
494      !noit_hash_retr_str(restc->ac->config,
495                          "document_root", strlen("document_root"),
496                          &document_root)) {
497     goto not_found;
498   }
499   if(!noit_hash_retr_str(restc->ac->config,
500                          "index_file", strlen("index_file"),
501                          &index_file)) {
502     index_file = "index.html";
503   }
504   drlen = strlen(document_root);
505   snprintf(file, sizeof(file), "%s/%s", document_root, pats[0]);
506   if(file[strlen(file) - 1] == '/') {
507     snprintf(file + strlen(file), sizeof(file) - strlen(file),
508              "%s", index_file);
509   }
510   /* resolve */
511   if(realpath(file, rfile) == NULL) goto not_found;
512   /* restrict */
513   if(strncmp(rfile, document_root, drlen)) goto denied;
514   if(rfile[drlen] != '/' && rfile[drlen + 1] != '/') goto denied;
515   /* stat */
516   /* coverity[fs_check_call] */
517   if(stat(rfile, &st) != 0) {
518     switch (errno) {
519       case EACCES: goto denied;
520       default: goto not_found;
521     }
522   }
523   /* open */
524   if(st.st_size > 0) {
525     /* coverity[toctou] */
526     fd = open(rfile, O_RDONLY);
527     if(fd < 0) goto not_found;
528     contents = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
529     close(fd);
530     if(contents == MAP_FAILED) goto not_found;
531   }
532   /* set content type */
533   slash = strchr(rfile, '/');
534   while(slash) {
535     const char *nslash = strchr(slash+1, '/');
536     if(!nslash) break;
537     slash = nslash;
538   }
539   if(slash) dot = strchr(slash+1, '.');
540   while(dot) {
541     const char *ndot = strchr(dot+1, '.');
542     if(!ndot) break;
543     dot = ndot;
544   }
545   /* If there is no extention, just use the filename */
546   if(!dot) dot = slash+1;
547   if(dot) {
548     char ext[PATH_MAX];
549     strlcpy(ext, "mime_type_", sizeof(ext));
550     strlcpy(ext+strlen(ext), dot+1, sizeof(ext)-strlen(ext));
551     if(!noit_hash_retr_str(restc->ac->config,
552                            ext, strlen(ext),
553                            &content_type)) {
554       if(!noit_hash_retr_str(&mime_type_defaults, dot+1, strlen(dot+1),
555                              &content_type)) {
556         content_type = "application/octet-stream";
557       }
558     }
559   }
560  
561   noit_http_response_ok(ctx, content_type);
562   if(st.st_size > 0) {
563     noit_http_response_append(ctx, contents, st.st_size);
564     munmap(contents, st.st_size);
565   }
566   noit_http_response_end(ctx);
567   return 0;
568
569  denied:
570   noit_http_response_denied(ctx, "text/html");
571   noit_http_response_end(ctx);
572   return 0;
573  not_found:
574   noit_http_response_not_found(ctx, "text/html");
575   noit_http_response_end(ctx);
576   return 0;
577 }
578
579 void noit_http_rest_load_rules() {
580   int ai, cnt = 0;
581   noit_conf_section_t *acls;
582   char path[256];
583   struct noit_rest_acl *newhead = NULL, *oldacls, *remove_acl;
584   struct noit_rest_acl_rule *remove_rule;
585
586   snprintf(path, sizeof(path), "//rest//acl");
587   acls = noit_conf_get_sections(NULL, path, &cnt);
588   noitL(noit_debug, "Found %d acl stanzas\n", cnt);
589   for(ai = cnt-1; ai>=0; ai--) {
590     char tbuff[32];
591     struct noit_rest_acl *newacl;
592     int ri, rcnt = 0;
593     noit_boolean default_allow = noit_false;
594     noit_conf_section_t *rules;
595
596     newacl = calloc(1, sizeof(*newacl));
597     newacl->next = newhead;
598     newhead = newacl;
599     if(noit_conf_get_stringbuf(acls[ai], "@type", tbuff, sizeof(tbuff)) &&
600        !strcmp(tbuff, "allow"))
601       newacl->allow = noit_true;
602
603 #define compile_re(node, cont, name) do { \
604   char buff[256]; \
605   if(noit_conf_get_stringbuf(node, "@" #name, buff, sizeof(buff))) { \
606     const char *error; \
607     int erroffset; \
608     cont->name = pcre_compile(buff, 0, &error, &erroffset, NULL); \
609   } \
610 } while(0)
611
612     newacl->allow = default_allow;
613     compile_re(acls[ai], newacl, cn);
614     compile_re(acls[ai], newacl, url);
615     rules = noit_conf_get_sections(acls[ai], "rule", &rcnt);
616     for(ri = rcnt - 1; ri >= 0; ri--) {
617       struct noit_rest_acl_rule *newacl_rule;
618       newacl_rule = calloc(1, sizeof(*newacl_rule));
619       newacl_rule->next = newacl->rules;
620       newacl->rules = newacl_rule;
621       if(noit_conf_get_stringbuf(rules[ri], "@type", tbuff, sizeof(tbuff)) &&
622          !strcmp(tbuff, "allow"))
623         newacl_rule->allow = noit_true;
624       compile_re(rules[ri], newacl_rule, cn);
625       compile_re(rules[ri], newacl_rule, url);
626     }
627     free(rules);
628   }
629   free(acls);
630
631   oldacls = global_rest_acls;
632   global_rest_acls = newhead;
633
634   while(oldacls) {
635     remove_acl = oldacls->next;
636     while(oldacls->rules) {
637       remove_rule = oldacls->rules->next;
638       if(oldacls->rules->cn) pcre_free(oldacls->rules->cn);
639       if(oldacls->rules->url) pcre_free(oldacls->rules->url);
640       free(oldacls->rules);
641       oldacls->rules = remove_rule;
642     }
643     if(oldacls->cn) pcre_free(oldacls->cn);
644     if(oldacls->url) pcre_free(oldacls->url);
645     free(oldacls);
646     oldacls = remove_acl;
647   }
648 }
649 void noit_http_rest_init() {
650   noit_http_init();
651   eventer_name_callback("noit_wire_rest_api/1.0", noit_http_rest_handler);
652   eventer_name_callback("http_rest_api", noit_http_rest_raw_handler);
653
654   /* some default mime types */
655 #define ADD_MIME_TYPE(ext, type) \
656 noit_hash_store(&mime_type_defaults, strdup(ext), strlen(ext), strdup(type))
657   ADD_MIME_TYPE("html", "text/html");
658   ADD_MIME_TYPE("htm", "text/html");
659   ADD_MIME_TYPE("js", "text/javascript");
660   ADD_MIME_TYPE("css", "text/css");
661   ADD_MIME_TYPE("ico", "image/x-icon");
662   ADD_MIME_TYPE("gif", "image/gif");
663   ADD_MIME_TYPE("png", "image/png");
664   ADD_MIME_TYPE("jpg", "image/jpg");
665   ADD_MIME_TYPE("jpeg", "image/jpg");
666   ADD_MIME_TYPE("json", "application/javascript");
667
668   noit_http_rest_load_rules();
669
670   noit_control_dispatch_delegate(noit_control_dispatch,
671                                  NOIT_CONTROL_DELETE,
672                                  noit_http_rest_handler);
673   noit_control_dispatch_delegate(noit_control_dispatch,
674                                  NOIT_CONTROL_MERGE,
675                                  noit_http_rest_handler);
676   noit_control_dispatch_delegate(noit_control_dispatch,
677                                  NOIT_CONTROL_GET,
678                                  noit_http_rest_handler);
679   noit_control_dispatch_delegate(noit_control_dispatch,
680                                  NOIT_CONTROL_HEAD,
681                                  noit_http_rest_handler);
682   noit_control_dispatch_delegate(noit_control_dispatch,
683                                  NOIT_CONTROL_POST,
684                                  noit_http_rest_handler);
685   noit_control_dispatch_delegate(noit_control_dispatch,
686                                  NOIT_CONTROL_PUT,
687                                  noit_http_rest_handler);
688 }
689
Note: See TracBrowser for help on using the browser.