static int rest_test_check_err(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_http_response *res = mtev_http_session_response(restc->http_ctx); mtev_skiplist_remove(&in_progress, restc, (mtev_freefunc_t)rest_test_check_result); if(mtev_http_response_complete(res) != mtev_true) { mtev_http_response_standard(restc->http_ctx, 500, "ERROR", "text/html"); mtev_http_response_end(restc->http_ctx); } return 0; }
static int rest_test_check(mtev_http_rest_closure_t *restc, int npats, char **pats) { noit_check_t *tcheck; mtev_http_session_ctx *ctx = restc->http_ctx; int mask, complete = 0; int error_code = 500; const char *error = "internal error"; xmlDocPtr indoc, doc = NULL; xmlNodePtr attr, config, root; indoc = rest_get_xml_upload(restc, &mask, &complete); if(!complete) return mask; if(indoc == NULL) { error = "xml parse error"; goto error; } if(!noit_validate_check_rest_post(indoc, &attr, &config, &error)) goto error; tcheck = noit_fire_check(attr, config, &error); if(tcheck) { /* push the check and the context into a queue to complete on */ struct check_test_closure *cl; cl = calloc(1, sizeof(*cl)); if(npats == 1 && !strcmp(pats[0], ".json")) cl->output = WANTS_JSON; cl->check = tcheck; cl->restc = restc; mtev_skiplist_insert(&in_progress, cl); check_test_schedule_sweeper(); if(restc->call_closure_free) restc->call_closure_free(restc->call_closure); restc->call_closure_free = NULL; restc->call_closure = NULL; restc->fastpath = rest_test_check_err; goto cleanup; } error: mtev_http_response_standard(ctx, error_code, "ERROR", "text/xml"); doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(doc, NULL, (xmlChar *)"error", NULL); xmlDocSetRootElement(doc, root); xmlNodeAddContent(root, (xmlChar *)error); mtev_http_response_xml(ctx, doc); mtev_http_response_end(ctx); goto cleanup; cleanup: if(doc) xmlFreeDoc(doc); return 0; }
static int rest_delete_feed(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_http_session_ctx *ctx = restc->http_ctx; const char *err = "unknown error"; const char *jpath_with_sub; char jlogpath[PATH_MAX], *cp; int rv; mtev_log_stream_t feed; jlog_ctx *jctx; feed = mtev_log_stream_find("feed"); if(!feed) { err = "cannot find feed"; goto error; } jpath_with_sub = mtev_log_stream_get_path(feed); strlcpy(jlogpath, jpath_with_sub, sizeof(jlogpath)); cp = strchr(jlogpath, '('); if(cp) *cp = '\0'; jctx = jlog_new(jlogpath); rv = jlog_ctx_remove_subscriber(jctx, pats[0]); jlog_ctx_close(jctx); if(rv < 0) { err = jlog_ctx_err_string(jctx); goto error; } /* removed or note, we should do a sweeping cleanup */ jlog_clean(jlogpath); if(rv == 0) { mtev_http_response_not_found(ctx, "text/plain"); mtev_http_response_end(ctx); return 0; } mtev_http_response_standard(ctx, 204, "OK", "text/plain"); mtev_http_response_end(ctx); return 0; error: mtev_http_response_server_error(ctx, "text/plain"); mtev_http_response_append(ctx, err, strlen(err)); mtev_http_response_end(ctx); return 0; }
static int lua_web_restc_fastpath(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_lua_resume_info_t *ri = restc->call_closure; mtev_http_response *res = mtev_http_session_response(restc->http_ctx); mtev_lua_resume_rest_info_t *ctx = ri->context_data; if(mtev_http_response_complete(res) != mtev_true) { mtev_http_response_standard(restc->http_ctx, (ctx && ctx->httpcode) ? ctx->httpcode : 500, "ERROR", "text/html"); if(ctx->err) mtev_http_response_append(restc->http_ctx, ctx->err, strlen(ctx->err)); mtev_http_response_end(restc->http_ctx); } mtev_http_rest_clean_request(restc); return 0; }
static int rest_show_filter(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_http_session_ctx *ctx = restc->http_ctx; xmlDocPtr doc = NULL; xmlNodePtr node, root; char xpath[1024]; int error_code = 500; if(npats != 2) goto error; snprintf(xpath, sizeof(xpath), "//filtersets%sfilterset[@name=\"%s\"]", pats[0], pats[1]); node = mtev_conf_get_section(NULL, xpath); if(!node) goto not_found; doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlCopyNode(node, 1); xmlDocSetRootElement(doc, root); mtev_http_response_ok(ctx, "text/xml"); mtev_http_response_xml(ctx, doc); mtev_http_response_end(ctx); goto cleanup; not_found: mtev_http_response_not_found(ctx, "text/html"); mtev_http_response_end(ctx); goto cleanup; error: mtev_http_response_standard(ctx, error_code, "ERROR", "text/html"); mtev_http_response_end(ctx); goto cleanup; cleanup: if(doc) xmlFreeDoc(doc); return 0; }
static int rest_delete_filter(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_http_session_ctx *ctx = restc->http_ctx; xmlNodePtr node; char xpath[1024]; int error_code = 500; if(npats != 2) goto error; snprintf(xpath, sizeof(xpath), "//filtersets%sfilterset[@name=\"%s\"]", pats[0], pats[1]); node = mtev_conf_get_section(NULL, xpath); if(!node) goto not_found; if(noit_filter_remove(node) == 0) goto not_found; CONF_REMOVE(node); xmlUnlinkNode(node); xmlFreeNode(node); if(mtev_conf_write_file(NULL) != 0) mtevL(noit_error, "local config write failed\n"); mtev_conf_mark_changed(); mtev_http_response_ok(ctx, "text/html"); mtev_http_response_end(ctx); goto cleanup; not_found: mtev_http_response_not_found(ctx, "text/html"); mtev_http_response_end(ctx); goto cleanup; error: mtev_http_response_standard(ctx, error_code, "ERROR", "text/html"); mtev_http_response_end(ctx); goto cleanup; cleanup: return 0; }
static int lua_web_handler(mtev_http_rest_closure_t *restc, int npats, char **pats) { int status, base, rv, mask = 0; int complete = 0; lua_web_conf_t *conf = the_one_conf; lua_module_closure_t *lmc = &conf->lmc; mtev_lua_resume_info_t *ri; mtev_lua_resume_rest_info_t *ctx = NULL; lua_State *L; eventer_t conne; mtev_http_request *req = mtev_http_session_request(restc->http_ctx); mtev_http_response *res = mtev_http_session_response(restc->http_ctx); if(!lmc || !conf || !conf->dispatch) { goto boom; } if(mtev_http_request_get_upload(req, NULL) == NULL && mtev_http_request_has_payload(req)) { const void *payload = NULL; int payload_len = 0; payload = rest_get_raw_upload(restc, &mask, &complete, &payload_len); if(!complete) return mask; mtev_http_request_set_upload(req, (char *)payload, (int64_t)payload_len, req_payload_free, NULL); restc->call_closure_free(restc->call_closure); restc->call_closure = NULL; } if(restc->call_closure == NULL) { ri = calloc(1, sizeof(*ri)); ri->bound_thread = pthread_self(); ri->context_magic = LUA_REST_INFO_MAGIC; ctx = ri->context_data = calloc(1, sizeof(mtev_lua_resume_rest_info_t)); ctx->restc = restc; ri->lmc = lmc; lua_getglobal(lmc->lua_state, "mtev_coros"); ri->coro_state = lua_newthread(lmc->lua_state); ri->coro_state_ref = luaL_ref(lmc->lua_state, -2); mtev_lua_set_resume_info(lmc->lua_state, ri); lua_pop(lmc->lua_state, 1); /* pops mtev_coros */ restc->call_closure = ri; restc->call_closure_free = rest_lua_ctx_free; } ri = restc->call_closure; ctx = ri->context_data; ctx->httpcode = 404; L = ri->coro_state; lua_getglobal(L, "require"); lua_pushstring(L, conf->dispatch); rv = lua_pcall(L, 1, 1, 0); if(rv) { int i; mtevL(mtev_error, "lua: require %s failed\n", conf->dispatch); i = lua_gettop(L); if(i>0) { if(lua_isstring(L, i)) { const char *err; size_t len; err = lua_tolstring(L, i, &len); mtevL(mtev_error, "lua: %s\n", err); } } lua_pop(L,i); goto boom; } lua_pop(L, lua_gettop(L)); mtev_lua_pushmodule(L, conf->dispatch); if(lua_isnil(L, -1)) { lua_pop(L, 1); ctx->err = strdup("no such module"); goto boom; } lua_getfield(L, -1, "handler"); lua_remove(L, -2); if(!lua_isfunction(L, -1)) { lua_pop(L, 1); ctx->err = strdup("no 'handler' function in module"); goto boom; } mtev_lua_setup_restc(L, restc); mtev_lua_hash_to_table(L, restc->ac->config); conne = mtev_http_connection_event(mtev_http_session_connection(restc->http_ctx)); eventer_remove(conne); restc->fastpath = lua_web_restc_fastpath; status = lmc->resume(ri, 2); if(status == 0) return 0; if(mtev_http_response_complete(res) != mtev_true) { boom: mtev_http_response_standard(restc->http_ctx, (ctx && ctx->httpcode) ? ctx->httpcode : 500, "ERROR", "text/plain"); if(ctx && ctx->err) mtev_http_response_append(restc->http_ctx, ctx->err, strlen(ctx->err)); mtev_http_response_end(restc->http_ctx); } return 0; }
static int rest_set_filter(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_http_session_ctx *ctx = restc->http_ctx; xmlDocPtr doc = NULL, indoc = NULL; xmlNodePtr node, parent, root, newfilter; char xpath[1024]; int error_code = 500, complete = 0, mask = 0; const char *error = "internal error"; if(npats != 2) goto error; indoc = rest_get_xml_upload(restc, &mask, &complete); if(!complete) return mask; if(indoc == NULL) FAIL("xml parse error"); snprintf(xpath, sizeof(xpath), "//filtersets%sfilterset[@name=\"%s\"]", pats[0], pats[1]); node = mtev_conf_get_section(NULL, xpath); if(!node && noit_filter_exists(pats[1])) { /* It's someone else's */ error_code = 403; goto error; } if((newfilter = validate_filter_post(indoc)) == NULL) goto error; xmlSetProp(newfilter, (xmlChar *)"name", (xmlChar *)pats[1]); parent = make_conf_path(pats[0]); if(!parent) FAIL("invalid path"); if(node) { xmlUnlinkNode(node); xmlFreeNode(node); } xmlUnlinkNode(newfilter); xmlAddChild(parent, newfilter); CONF_DIRTY(newfilter); mtev_conf_mark_changed(); if(mtev_conf_write_file(NULL) != 0) mtevL(noit_error, "local config write failed\n"); noit_filter_compile_add(newfilter); if(restc->call_closure_free) restc->call_closure_free(restc->call_closure); restc->call_closure_free = NULL; restc->call_closure = NULL; restc->fastpath = rest_show_filter; return restc->fastpath(restc, restc->nparams, restc->params); error: mtev_http_response_standard(ctx, error_code, "ERROR", "text/html"); doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(doc, NULL, (xmlChar *)"error", NULL); xmlDocSetRootElement(doc, root); xmlNodeAddContent(root, (xmlChar *)error); mtev_http_response_xml(ctx, doc); mtev_http_response_end(ctx); goto cleanup; cleanup: if(doc) xmlFreeDoc(doc); return 0; }
static int rest_add_feed(mtev_http_rest_closure_t *restc, int npats, char **pats) { mtev_http_session_ctx *ctx = restc->http_ctx; xmlXPathObjectPtr pobj = NULL; xmlDocPtr doc = NULL, indoc = NULL; xmlNodePtr node, root; acceptor_closure_t *ac = restc->ac; int error_code = 500, complete = 0, mask = 0, rv; const char *error = "internal error", *logname; char *name, *copy_from; mtev_log_stream_t feed; const char *jpath_with_sub; char jlogpath[PATH_MAX], *cp; jlog_ctx *jctx = NULL; jlog_id chkpt; if(npats != 0) goto error; indoc = rest_get_xml_upload(restc, &mask, &complete); if(!complete) return mask; if(indoc == NULL) { error = "xml parse error"; goto error; } if(!mtev_hash_retr_str(ac->config, "log_transit_feed_name", strlen("log_transit_feed_name"), &logname)) { goto error; } feed = mtev_log_stream_find("feed"); if(!feed) { error = "couldn't find feed"; goto error; } jpath_with_sub = mtev_log_stream_get_path(feed); strlcpy(jlogpath, jpath_with_sub, sizeof(jlogpath)); cp = strchr(jlogpath, '('); if(cp) *cp = '\0'; node = xmlDocGetRootElement(indoc); name = (char*)xmlGetProp(node, (xmlChar*)"name"); copy_from = (char*)xmlGetProp(node, (xmlChar*)"checkpoint_copy"); jctx = jlog_new(jlogpath); if (!jctx) { error = "couldn't open logpath"; goto error; } if (!jlog_get_checkpoint(jctx, name, &chkpt)) { error = "subscriber already exists, can't add"; goto error; } if (copy_from) { rv = jlog_ctx_add_subscriber_copy_checkpoint(jctx, name, copy_from); } else { rv = jlog_ctx_add_subscriber(jctx, name, JLOG_END); } if (rv == -1) { error = "couldn't add subscriber"; goto error; } mtev_http_response_ok(restc->http_ctx, "text/xml"); mtev_http_response_end(restc->http_ctx); goto cleanup; error: mtev_http_response_standard(ctx, error_code, "ERROR", "text/xml"); doc = xmlNewDoc((xmlChar *)"1.0"); root = xmlNewDocNode(doc, NULL, (xmlChar *)"error", NULL); xmlDocSetRootElement(doc, root); xmlNodeAddContent(root, (xmlChar *)error); mtev_http_response_xml(ctx, doc); mtev_http_response_end(ctx); cleanup: if (jctx) { jlog_ctx_close(jctx); } if(pobj) xmlXPathFreeObject(pobj); if(doc) xmlFreeDoc(doc); return 0; }