static unsigned int vstat_reply(struct http_request *request, const char *arg, void *data) { struct vstat_priv_t *vstat; struct agent_core_t *core = data; struct http_response *resp; (void)arg; GET_PRIV(core, vstat); if (check_reopen(&vstat->http)) { http_reply(request->connection, 500, "Couldn't open shmlog"); return 0; } do_json(vstat->http.vd, vstat->http.vsb); resp = http_mkresp(request->connection, 200, NULL); resp->data = VSB_data(vstat->http.vsb); resp->ndata = VSB_len(vstat->http.vsb); http_add_header(resp,"Content-Type","application/json"); send_response(resp); http_free_resp(resp); VSB_clear(vstat->http.vsb); return 0; }
static int send_response(struct MHD_Connection *connection, int status, const char *data, unsigned int ndata) { struct http_response *resp = http_mkresp(connection, status, NULL); int ret; resp->data = data; resp->ndata = ndata; ret = send_response2(resp); http_free_resp(resp); return ret; }
static int send_auth_response(struct MHD_Connection *connection) { struct http_response *resp = http_mkresp(connection, 401, "Authorize, please.\n\n" \ "If Varnish Agent was installed from packages, the /etc/varnish/agent_secret " \ "file contains generated credentials."); http_add_header(resp, "WWW-Authenticate", "Basic realm=varnish-agent"); send_response2(resp); http_free_resp(resp); return 1; }
static unsigned int html_reply(struct http_request *request, void *data) { int ret, fd=-1; char *path = NULL; char *buffer = NULL; struct stat sbuf; struct agent_core_t *core = data; struct http_response *resp; struct html_priv_t *html; GET_PRIV(data, html); const char *url_stub = (strlen(request->url) > strlen("/html/")) ? request->url + strlen("/html/") : "index.html"; if (url_stub[0] == '/' || strstr(url_stub,"/../") || !strncmp(url_stub,"../",strlen("../"))) { send_response_fail(request->connection, "Invalid URL"); return 0; } ret = asprintf(&path, "%s/%s", core->config->H_arg, url_stub); assert(ret>0); ret = stat(path, &sbuf); if (ret < 0) { warnlog(html->logger, "Stat failed for %s. Errnno %d: %s.", path,errno,strerror(errno)); send_response_fail(request->connection, "stat() was not happy"); goto out; } fd = open(path, O_RDONLY); if (fd < 0) { warnlog(html->logger, "open() failed for %s: %s", path, strerror(errno)); send_response_fail(request->connection, "open() was not happy"); goto out; } if (!S_ISREG(sbuf.st_mode)) { warnlog(html->logger, "%s isn't a regular file.", path); send_response_fail(request->connection, "not a file"); goto out; } buffer = malloc(sbuf.st_size); assert(buffer); ret = read(fd, buffer, sbuf.st_size); assert(ret>0); assert(ret==sbuf.st_size); resp = http_mkresp(request->connection, 200, NULL); resp->data = buffer; resp->ndata = ret; send_response2(resp); http_free_resp(resp); out: if (fd >= 0) close(fd); if (buffer) free(buffer); if (path) free(path); return 0; }
static unsigned int echo_reply(struct http_request *request, void *data) { struct echo_priv_t *echo = data; struct http_response *resp = http_mkresp(request->connection, 200, NULL); resp->data = request->data; resp->ndata = request->ndata; if (request->method == M_PUT || request->method == M_POST) { if (((char *)request->data)[request->ndata] == '\0' && strlen((char *)request->data) == request->ndata) debuglog(echo->logger, "Data being printed: \n%s", (char *)request->data); } logger(echo->logger, "Responding to request"); send_response2(resp); http_free_resp(resp); return 0; }
static void param_json(struct http_request *request, struct vparams_priv_t *vparams) { struct ipc_ret_t vret; char *tmp; ipc_run(vparams->vadmin, &vret, "param.show -l"); if (vret.status == 200) { tmp = vparams_show_json(vret.answer); struct http_response *resp = http_mkresp(request->connection, 200, tmp); http_add_header(resp,"Content-Type","application/json"); send_response(resp); free(tmp); http_free_resp(resp); } else { http_reply(request->connection, 500, vret.answer); } free(vret.answer); }
static void backends_json(struct http_request *request, struct vbackends_priv_t *vbackends) { struct vsb *json; struct ipc_ret_t vret; ipc_run(vbackends->vadmin, &vret, "backend.list"); if (vret.status == 200) { json = VSB_new_auto(); assert(json); vbackends_show_json(json, vret.answer); AZ(VSB_finish(json)); struct http_response *resp = http_mkresp(request->connection, 200, VSB_data(json)); http_add_header(resp,"Content-Type","application/json"); send_response(resp); VSB_delete(json); http_free_resp(resp); } else http_reply(request->connection, 500, vret.answer); free(vret.answer); }
static unsigned int vcl_json(struct http_request *request, const char *arg, void *data) { struct agent_core_t *core = data; struct vcl_priv_t *vcl; struct ipc_ret_t vret; struct vsb *json; struct http_response *resp; GET_PRIV(core, vcl); assert(STARTS_WITH(request->url, "/vcljson")); assert(request->method == M_GET); if (arg) { http_reply(request->connection, 404, "/vcljson takes no argument"); return (0); } ipc_run(vcl->vadmin, &vret, "vcl.list"); if (vret.status == 400) http_reply(request->connection, 500, vret.answer); else { json = vcl_list_json(vret.answer); assert(VSB_finish(json) == 0); resp = http_mkresp(request->connection, 200, NULL); resp->data = VSB_data(json); resp->ndata = VSB_len(json); http_add_header(resp, "Content-Type", "application/json"); send_response(resp); http_free_resp(resp); VSB_clear(json); VSB_delete(json); } free(vret.answer); return (0); }
static unsigned int vlog_reply(struct http_request *request, void *data) { struct vlog_req_priv vrp = { .limit = 10 }; int disp_status; char *p; char *tag = NULL; char *tag_re = NULL; struct VSL_data *vsl = NULL; struct VSLQ *vslq = NULL; struct VSL_cursor *c = NULL; enum VSL_grouping_e grouping = VSL_g_request; struct agent_core_t *core = data; p = next_slash(request->url + 1); if (p) { char *lim = strdup(p); assert(lim); char *tmp2 = strchr(lim, '/'); if (tmp2 && *tmp2) *tmp2 = '\0'; int j = sscanf(lim, "%u", &vrp.limit); if(j != 1) { free(lim); http_reply(request->connection, 500, "Not a number"); return 0; } free(lim); p = next_slash(p); } if (p) { tag = strdup(p); char *tmp2 = strchr(tag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } if (p) { tag_re = strdup(p); char *tmp2 = strchr(tag_re, '/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } vrp.answer = VSB_new_auto(); assert(vrp.answer != NULL); vrp.vsm = VSM_New(); assert(vrp.vsm); if (!VSM_n_Arg(vrp.vsm, core->config->n_arg)) { VSB_printf(vrp.answer, "Error in creating shmlog: %s", VSM_Error(vrp.vsm)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } if (VSM_Open(vrp.vsm) != 0) { VSB_printf(vrp.answer, "Error in opening shmlog: %s", VSM_Error(vrp.vsm)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } vsl = VSL_New(); assert(vsl); if (tag) { grouping = VSL_g_raw; if (VSL_Arg(vsl, 'i', tag) < 0) { VSB_printf(vrp.answer, "Unable to specify tag '%s': %s", tag, VSL_Error(vsl)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } if (tag_re) { VSL_Arg(vsl,'I', tag_re); } } c = VSL_CursorVSM(vsl, vrp.vsm, VSL_COPT_BATCH | VSL_COPT_TAILSTOP); if (c == NULL) { VSB_printf(vrp.answer, "Can't open log (%s)", VSL_Error(vsl)); VSB_finish(vrp.answer); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } vslq = VSLQ_New(vsl, &c, grouping, NULL); if (vslq == NULL) { VSB_clear(vrp.answer); VSB_printf(vrp.answer, "Error in creating query: %s", VSL_Error(vsl)); http_reply(request->connection, 500, VSB_data(vrp.answer)); goto cleanup; } VSB_printf(vrp.answer, "{ \"log\": ["); do { disp_status = VSLQ_Dispatch(vslq, vlog_cb_func, &vrp); } while (disp_status == 1 && vrp.entries < vrp.limit); VSB_printf(vrp.answer, "\n] }\n"); assert(VSB_finish(vrp.answer) == 0); if (VSB_len(vrp.answer) > 1) { struct http_response *resp = http_mkresp(request->connection, 200, NULL); resp->data = VSB_data(vrp.answer); resp->ndata = VSB_len(vrp.answer); http_add_header(resp,"Content-Type","application/json"); send_response(resp); http_free_resp(resp); } else { http_reply(request->connection, 500, "FAIL"); } cleanup: free(tag); free(tag_re); VSB_delete(vrp.answer); if (vslq) VSLQ_Delete(&vslq); if (vsl) VSL_Delete(vsl); if (vrp.vsm) VSM_Delete(vrp.vsm); vrp.answer = NULL; return 0; } void vlog_init(struct agent_core_t *core) { struct agent_plugin_t *plug; struct vlog_priv_t *priv; ALLOC_OBJ(priv); plug = plugin_find(core,"vlog"); plug->data = priv; http_register_url(core, "/log", M_GET, vlog_reply, core); }
static unsigned int vcl_reply(struct http_request *request, void *data) { struct agent_core_t *core = data; struct vcl_priv_t *vcl; struct http_response *resp; struct ipc_ret_t vret; char id[ID_LEN + 1]; int ret; int status; GET_PRIV(core, vcl); if (request->method == M_GET) { if (!strcmp(request->url, "/vclactive") || !strcmp(request->url,"/vclactive/")) { /* * vcl.list output: * * V3/4 : (active|available|discarded) (refcnt) (name) * V4.1 : (active|available|discarded) (state) \ * (busycnt|) (name) */ ipc_run(vcl->vadmin,&vret,"vcl.list"); if (vret.status == 400) { http_reply(request->connection, 500, vret.answer); } else { char **tp, *tok[5]; char *p, *last; char *line; memset(tok, '\0', sizeof(tok)); for (p = vret.answer, last = NULL; (line = strtok_r(p, "\n", &last)); p = NULL) { if (strncmp("active", line, 6)) continue; last = NULL; for (p = line, tp = tok; tp < &tok[4] && (*tp = strtok_r(p, " ", &last)); p = NULL) { if (**tp != '\0') tp++; } } if (!tok[2] || !tok[3]) { http_reply(request->connection, 500, "No active VCL"); } else { strcpy(vret.answer, tok[3] ? tok[3] : tok[2]); http_reply(request->connection, 200, vret.answer); } } free(vret.answer); return 0; } else if (!strcmp(request->url, "/vcl") || !strcmp(request->url,"/vcl/")) { ipc_run(vcl->vadmin, &vret, "vcl.list"); if (vret.status == 400) { http_reply(request->connection, 500, vret.answer); } else { http_reply(request->connection, 200, vret.answer); } free(vret.answer); return 0; } else if (!strncmp(request->url,"/vcl/",strlen("/vcl/"))) { ipc_run(vcl->vadmin, &vret, "vcl.show %s", request->url + strlen("/vcl/")); if (vret.status == 400) { http_reply(request->connection, 500, vret.answer); } else { http_reply(request->connection, 200, vret.answer); } free(vret.answer); return 0; } else if(!strcmp(request->url, "/vcljson/")) { struct vsb *json; ipc_run(vcl->vadmin, &vret, "vcl.list"); if (vret.status == 400) { http_reply(request->connection, 500, vret.answer); } else { json = vcl_list_json(vret.answer); assert(VSB_finish(json) == 0); resp = http_mkresp(request->connection, 200, NULL); resp->data = VSB_data(json); resp->ndata = VSB_len(json); http_add_header(resp, "Content-Type", "application/json"); send_response(resp); http_free_resp(resp); VSB_clear(json); VSB_delete(json); } free(vret.answer); return 0; } else { http_reply(request->connection, 500, "Invalid VCL-url."); return 0; } } else if (request->method == M_POST) { snprintf(id, sizeof(id), "%ju", (uintmax_t) time(NULL)); status = vcl_store(request, vcl, &vret, core, id); http_reply(request->connection, status, vret.answer); free(vret.answer); return 0; } else if (request->method == M_PUT) { if (!strncmp(request->url,"/vcl/",strlen("/vcl/"))) { if (strlen(request->url) >= 6) { status = vcl_store(request, vcl, &vret, core, request->url + strlen("/vcl/")); http_reply(request->connection, status, vret.answer); free(vret.answer); return 0; } else { http_reply(request->connection, 400, "Bad URL?"); return 0; } } else if (!strncmp(request->url, "/vcldeploy/",strlen("/vcldeploy/"))) { ipc_run(vcl->vadmin, &vret, "vcl.use %s", request->url + strlen("/vcldeploy/")); if (vret.status == 200) { ret = vcl_persist_active(vcl->logger, request->url + strlen("/vcldeploy/"), core); } if (vret.status == 200 && ret) http_reply(request->connection, 500, "Deployed ok, but NOT PERSISTED."); else if (vret.status == 200 && ret == 0) http_reply(request->connection, 200, vret.answer); else http_reply(request->connection, 500, vret.answer); free(vret.answer); return 0; } } else if (request->method == M_DELETE) { if (!strncmp(request->url, "/vcl/", strlen("/vcl/"))) { ipc_run(vcl->vadmin, &vret, "vcl.discard %s", request->url + strlen("/vcl/")); if (vret.status == 400 || vret.status == 106) { http_reply(request->connection, 500, vret.answer); } else { http_reply(request->connection, 200, vret.answer); } free(vret.answer); return 0; } } else { return http_reply(request->connection, 500, "Unknown request?"); } assert("Shouldn't get here" == NULL); return 0; }
static unsigned int vlog_reply(struct http_request *request, void *data) { struct vlog_priv_t *vlog; int ret; char *limit = NULL; char *p; char *tag = NULL; char *itag = NULL; struct agent_core_t *core = data; GET_PRIV(data,vlog); p = next_slash(request->url + 1); assert(vlog->tag==NULL); assert(vlog->answer == NULL); if (p) { limit = strdup(p); assert(limit); char *tmp2 = index(limit,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; if(!(atoi(limit) > 0)) { free(limit); send_response_fail(request->connection,"Not a number"); return 0; } p = next_slash(p); } if (p) { tag = strdup(p); char *tmp2 = index(tag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } if (p) { itag = strdup(p); char *tmp2 = index(itag,'/'); if (tmp2 && *tmp2) *tmp2 = '\0'; p = next_slash(p); } vlog->answer = VSB_new_auto(); assert(vlog->answer != NULL); vlog->vd = VSM_New(); assert(VSL_Arg(vlog->vd, 'n', core->config->n_arg)); VSL_Setup(vlog->vd); VSL_Arg(vlog->vd, 'd', ""); if (tag) { VSL_Arg(vlog->vd, 'i', tag); if (itag) VSL_Arg(vlog->vd,'I',itag); } else { VSL_Arg(vlog->vd, 'k', limit ? limit : "10"); } if (limit) free(limit); VSB_printf(vlog->answer, "{ \"log\": ["); ret = VSL_Open(vlog->vd, 1); if (ret) { send_response_fail(request->connection, "Error in opening shmlog"); goto cleanup; } if (tag == NULL) { do_order(vlog); } else { do_unorder(vlog); } VSB_printf(vlog->answer, "\n] }\n"); assert(VSB_finish(vlog->answer) == 0); if (VSB_len(vlog->answer) > 1) { struct http_response *resp = http_mkresp(request->connection, 200, NULL); resp->data = VSB_data(vlog->answer); resp->ndata = VSB_len(vlog->answer); http_add_header(resp,"Content-Type","application/json"); send_response2(resp); http_free_resp(resp); } else { send_response_fail(request->connection, "FAIL"); } cleanup: free(tag); free(itag); VSB_clear(vlog->answer); VSB_delete(vlog->answer); VSM_Delete(vlog->vd); vlog->answer = NULL; vlog->entries = 0; return 0; }