Show
Ignore:
Timestamp:
09/13/09 14:43:17 (5 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1252852997 +0000
git-parent:

[57a2287f4d549439df74e04e133e5a4e40582d97]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1252852997 +0000
Message:

work on #171, getting check info works

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/noit_rest.c

    r6688159 r0256945  
    3636#include "noit_rest.h" 
    3737 
     38#include <pcre.h> 
     39 
     40struct rest_url_dispatcher { 
     41  char *method; 
     42  pcre *expression; 
     43  pcre_extra *extra; 
     44  rest_request_handler handler; 
     45  /* Chain to the next one */ 
     46  struct rest_url_dispatcher *next; 
     47}; 
     48struct rule_container { 
     49  char *base; 
     50  struct rest_url_dispatcher *rules; 
     51  struct rest_url_dispatcher *rules_endptr; 
     52}; 
     53noit_hash_table dispatch_points = NOIT_HASH_EMPTY; 
     54 
     55static rest_request_handler 
     56noit_http_get_handler(noit_http_rest_closure_t *restc) { 
     57  struct rule_container *cont = NULL; 
     58  struct rest_url_dispatcher *rule; 
     59  char *eoq, *eob; 
     60  eoq = strchr(restc->http_ctx->req.uri_str, '?'); 
     61  if(!eoq) 
     62    eoq = restc->http_ctx->req.uri_str + strlen(restc->http_ctx->req.uri_str); 
     63  eob = eoq - 1; 
     64 
     65  /* find the right base */ 
     66  while(1) { 
     67    void *vcont; 
     68    while(eob >= restc->http_ctx->req.uri_str && *eob != '/') eob--; 
     69    if(eob < restc->http_ctx->req.uri_str) break; /* off the front */ 
     70    if(noit_hash_retrieve(&dispatch_points, restc->http_ctx->req.uri_str, 
     71                          eob - restc->http_ctx->req.uri_str + 1, &vcont)) { 
     72      cont = vcont; 
     73      eob++; /* move past the determined base */ 
     74      break; 
     75    } 
     76    eob--; 
     77  } 
     78  if(!cont) return NULL; 
     79  for(rule = cont->rules; rule; rule = rule->next) { 
     80    int ovector[30]; 
     81    int cnt; 
     82    if(strcmp(rule->method, restc->http_ctx->req.method_str)) continue; 
     83    if((cnt = pcre_exec(rule->expression, rule->extra, eob, eoq - eob, 0, 0, 
     84                        ovector, sizeof(ovector)/sizeof(*ovector))) > 0) { 
     85      /* We match, set 'er up */ 
     86      restc->fastpath = rule->handler; 
     87      restc->nparams = cnt - 1; 
     88      if(restc->nparams) { 
     89        restc->params = calloc(restc->nparams, sizeof(*restc->params)); 
     90        for(cnt = 0; cnt < restc->nparams; cnt++) { 
     91          int start = ovector[(cnt+1)*2]; 
     92          int end = ovector[(cnt+1)*2+1]; 
     93          restc->params[cnt] = malloc(end - start + 1); 
     94          memcpy(restc->params[cnt], eob + start, end - start); 
     95          restc->params[cnt][end - start] = '\0'; 
     96        } 
     97      } 
     98      return restc->fastpath; 
     99    } 
     100  } 
     101  return NULL; 
     102} 
     103int 
     104noit_http_rest_register(const char *method, const char *base, 
     105                        const char *expr, rest_request_handler f) { 
     106  void *vcont; 
     107  struct rule_container *cont; 
     108  struct rest_url_dispatcher *rule; 
     109  const char *error; 
     110  int erroffset; 
     111  pcre *pcre_expr; 
     112  int blen = strlen(base); 
     113  /* base must end in a /, 'cause I said so */ 
     114  if(blen == 0 || base[blen-1] != '/') return -1; 
     115  pcre_expr = pcre_compile(expr, 0, &error, &erroffset, NULL); 
     116  if(!pcre_expr) { 
     117    noitL(noit_error, "Error in rest expr(%s) '%s'@%d: %s\n", 
     118          base, expr, erroffset, error); 
     119    return -1; 
     120  } 
     121  rule = calloc(1, sizeof(*rule)); 
     122  rule->method = strdup(method); 
     123  rule->expression = pcre_expr; 
     124  rule->extra = pcre_study(rule->expression, 0, &error); 
     125  rule->handler = f; 
     126 
     127  /* Make sure we have a container */ 
     128  if(!noit_hash_retrieve(&dispatch_points, base, strlen(base), &vcont)) { 
     129    cont = calloc(1, sizeof(*cont)); 
     130    cont->base = strdup(base); 
     131    noit_hash_store(&dispatch_points, cont->base, strlen(cont->base), cont); 
     132  } 
     133  else cont = vcont; 
     134 
     135  /* Append the rule */ 
     136  if(cont->rules_endptr) { 
     137    cont->rules_endptr->next = rule; 
     138    cont->rules_endptr = cont->rules_endptr->next; 
     139  } 
     140  else 
     141    cont->rules = cont->rules_endptr = rule; 
     142  return 0; 
     143} 
     144 
    38145static noit_http_rest_closure_t * 
    39146noit_http_rest_closure_alloc() { 
     
    43150} 
    44151static void 
     152noit_http_rest_clean_request(noit_http_rest_closure_t *restc) { 
     153  int i; 
     154  if(restc->nparams) { 
     155    for(i=0;i<restc->nparams;i++) free(restc->params[i]); 
     156    free(restc->params); 
     157  } 
     158  restc->nparams = 0; 
     159  restc->params = NULL; 
     160  restc->fastpath = NULL; 
     161} 
     162static void 
    45163noit_http_rest_closure_free(noit_http_rest_closure_t *restc) { 
     164  free(restc->remote_cn); 
     165   noit_http_rest_clean_request(restc); 
    46166  free(restc); 
    47167} 
     
    49169int 
    50170noit_rest_request_dispatcher(noit_http_session_ctx *ctx) { 
    51   noit_http_response_status_set(ctx, 200, "OK"); 
    52   noit_http_response_header_set(ctx, "Content-Type", "application/json"); 
     171  noit_http_rest_closure_t *restc = ctx->dispatcher_closure; 
     172  rest_request_handler handler = restc->fastpath; 
     173  if(!handler) handler = noit_http_get_handler(restc); 
     174  if(handler) { 
     175    int rv; 
     176    rv = handler(restc, restc->nparams, restc->params); 
     177    if(ctx->res.closed) noit_http_rest_clean_request(restc); 
     178    return rv; 
     179  } 
     180  noit_http_response_status_set(ctx, 404, "NOT FOUND"); 
    53181  noit_http_response_option_set(ctx, NOIT_HTTP_CHUNKED); 
    54   noit_http_response_option_set(ctx, NOIT_HTTP_DEFLATE); 
    55   noit_http_response_append(ctx, "{error: 'Foo'}", 14); 
    56   noit_http_response_flush(ctx, noit_false); 
     182  noit_http_rest_clean_request(restc); 
    57183  noit_http_response_end(ctx); 
    58184  return 0; 
     
    79205    const char *primer = ""; 
    80206    ac->service_ctx = restc = noit_http_rest_closure_alloc(); 
     207    restc->remote_cn = strdup(ac->remote_cn ? ac->remote_cn : ""); 
    81208    restc->http_ctx = 
    82209        noit_http_session_ctx_new(noit_rest_request_dispatcher,