static void put_playlist_patch(sp_playlist *playlist, struct evhttp_request *request, void *userdata) { struct state *state = userdata; struct evbuffer *buf = evhttp_request_get_input_buffer(request); size_t buflen = evbuffer_get_length(buf); if (buflen == 0) { send_error(request, HTTP_BADREQUEST, "No body"); return; } // Read request body json_error_t loads_error; json_t *json = read_request_body_json(request, &loads_error); if (json == NULL) { send_error(request, HTTP_BADREQUEST, loads_error.text ? loads_error.text : "Unable to parse JSON"); return; } if (!json_is_array(json)) { json_decref(json); send_error(request, HTTP_BADREQUEST, "Not valid JSON array"); return; } // Handle empty array int num_tracks = json_array_size(json); if (num_tracks == 0) { send_reply(request, HTTP_OK, "OK", NULL); return; } sp_track **tracks = calloc(num_tracks, sizeof (sp_track *)); int num_valid_tracks = 0; for (int i = 0; i < num_tracks; i++) { json_t *item = json_array_get(json, i); if (!json_is_string(item)) { json_decref(item); continue; } char *uri = strdup(json_string_value(item)); sp_link *track_link = sp_link_create_from_string(uri); free(uri); if (track_link == NULL) continue; if (sp_link_type(track_link) != SP_LINKTYPE_TRACK) { sp_link_release(track_link); continue; } sp_track *track = sp_link_as_track(track_link); if (track == NULL) continue; tracks[num_valid_tracks++] = track; } json_decref(json); // Bail if no tracks could be read from input if (num_valid_tracks == 0) { send_error(request, HTTP_BADREQUEST, "No valid tracks"); free(tracks); return; } tracks = realloc(tracks, num_valid_tracks * sizeof (sp_track *)); // Apply diff apr_pool_t *pool = state->pool; svn_diff_t *diff; svn_error_t *diff_error = diff_playlist_tracks(&diff, playlist, tracks, num_valid_tracks, pool); if (diff_error != SVN_NO_ERROR) { free(tracks); svn_handle_error2(diff_error, stderr, false, "Diff"); send_error(request, HTTP_BADREQUEST, "Search failed"); return; } svn_error_t *apply_error = diff_playlist_tracks_apply(diff, playlist, tracks, num_valid_tracks, state->session); if (apply_error != SVN_NO_ERROR) { free(tracks); svn_handle_error2(apply_error, stderr, false, "Updating playlist"); send_error(request, HTTP_BADREQUEST, "Could not apply diff"); return; } if (!sp_playlist_has_pending_changes(playlist)) { free(tracks); get_playlist(playlist, request, NULL); return; } free(tracks); register_playlist_callbacks(playlist, request, &get_playlist, &playlist_update_in_progress_callbacks, NULL); }
virtual void httpRecvReq(struct evhttp_request *req) { std::cout << "---- received:" << std::endl; if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) return; evhttp_request_own(req); struct evkeyval *header; struct evkeyvalq *headers; headers = evhttp_request_get_input_headers(req); for (header = headers->tqh_first; header; header = header->next.tqe_next) { // std::cout << header->key << ": " << header->value << std::endl; } std::string content; struct evbuffer *buf; buf = evhttp_request_get_input_buffer(req); while (evbuffer_get_length(buf)) { int n; char cbuf[128]; n = evbuffer_remove(buf, cbuf, sizeof(buf)-1); if (n > 0) { content.append(cbuf, n); } } uscxml::Data jsonReq = uscxml::Data::fromJSON(content); std::cout << jsonReq << std::endl; // is this a load request? if (jsonReq.compound.find("load") != jsonReq.compound.end()) { std::string filename = jsonReq.compound["load"].atom; std::cout << "Starting Interpreter with " << filename << std::endl; uscxml::Interpreter* interpreter = uscxml::Interpreter::fromURI(filename); if (interpreter) { std::string token = uscxml::toStr(lastToken++); assert(_interpreters.find(token) == _interpreters.end()); interpreter->setName(token); interpreter->addMonitor(this); interpreter->start(); _interpreters[token] = std::make_pair(interpreter, req); } return; } if(jsonReq.compound.find("event") != jsonReq.compound.end()) { assert(jsonReq.compound["event"].compound.find("sessionToken") != jsonReq.compound["event"].compound.end()); std::string token = jsonReq.compound["event"].compound["sessionToken"].atom; assert(_interpreters.find(token) != _interpreters.end()); uscxml::Event event; event.type = uscxml::Event::INTERNAL; event.name = jsonReq.compound["event"].compound["name"].atom; std::cout << "Sending event " << event << std::endl; // evhttp_request_free(_interpreters[token].second); _interpreters[token].second = req; _interpreters[token].first->receive(event); } }
static void request_cb(struct evhttp_request *req, void *arg) { struct http_client_ctx *ctx; const char *response_code_line; int response_code; ctx = (struct http_client_ctx *)arg; if (ctx->headers_only) { ctx->ret = 0; event_base_loopbreak(ctx->evbase); return; } if (!req) { DPRINTF(E_WARN, L_HTTP, "Connection to %s failed: Connection timed out\n", ctx->url); goto connection_error; } response_code = evhttp_request_get_response_code(req); #ifndef HAVE_LIBEVENT2_OLD response_code_line = evhttp_request_get_response_code_line(req); #else response_code_line = "no error text"; #endif if (response_code == 0) { DPRINTF(E_WARN, L_HTTP, "Connection to %s failed: Connection refused\n", ctx->url); goto connection_error; } else if (response_code != 200) { DPRINTF(E_WARN, L_HTTP, "Connection to %s failed: %s (error %d)\n", ctx->url, response_code_line, response_code); goto connection_error; } ctx->ret = 0; if (ctx->headers) headers_save(ctx->headers, evhttp_request_get_input_headers(req)); if (ctx->body) evbuffer_add_buffer(ctx->body, evhttp_request_get_input_buffer(req)); event_base_loopbreak(ctx->evbase); return; connection_error: ctx->ret = -1; event_base_loopbreak(ctx->evbase); return; }
/** * Call back used for a POST request */ static void post_request_cb(struct evhttp_request *req, void *arg) { std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now(); /* bool isPostRequest = false; const char *cmdtype = NULL; switch (evhttp_request_get_command(req)) { case EVHTTP_REQ_GET: cmdtype = "GET"; break; case EVHTTP_REQ_POST: cmdtype = "POST"; isPostRequest = true; break; case EVHTTP_REQ_HEAD: cmdtype = "HEAD"; break; case EVHTTP_REQ_PUT: cmdtype = "PUT"; break; case EVHTTP_REQ_DELETE: cmdtype = "DELETE"; break; case EVHTTP_REQ_OPTIONS: cmdtype = "OPTIONS"; break; case EVHTTP_REQ_TRACE: cmdtype = "TRACE"; break; case EVHTTP_REQ_CONNECT: cmdtype = "CONNECT"; break; case EVHTTP_REQ_PATCH: cmdtype = "PATCH"; break; default: cmdtype = "unknown"; break; } if (!isPostRequest) { evhttp_send_error(req, HTTP_BADREQUEST, 0); } */ if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) { std::cerr << "Invalid request! Needs to be POST" << std::endl; evhttp_send_error(req, HTTP_BADREQUEST, 0); } else { struct evbuffer *evb = NULL; struct evkeyvalq *headers; struct evkeyval *header; struct evbuffer *buf; printf("Received a POST request for %s\nHeaders:\n", evhttp_request_get_uri(req)); headers = evhttp_request_get_input_headers(req); for (header = headers->tqh_first; header; header = header->next.tqe_next) { printf(" %s: %s\n", header->key, header->value); } buf = evhttp_request_get_input_buffer(req); std::string postData; while (evbuffer_get_length(buf)) { int n; char cbuf[128]; n = evbuffer_remove(buf, cbuf, sizeof(buf)-1); if (n > 0) { // (void) fwrite(cbuf, 1, n, stdout); postData.append(cbuf, n); } } // std::cout << "Post data: " << std::endl << postData << std::endl; // do not remove this struct evkeyvalq params; // create storage for your key->value pairs struct evkeyval *param; // iterator // working code to return the parameters as plain text ... /* std::string postDataDecoded; if (result == 0) { for (param = params.tqh_first; param; param = param->next.tqe_next) { printf("%s %s\n", param->key, param->value); postDataDecoded.append(param->key); postDataDecoded.append(" "); postDataDecoded.append(param->value); postDataDecoded.append("\n"); } evb = evbuffer_new(); evbuffer_add_printf(evb, postDataDecoded.c_str()); evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html"); evhttp_send_reply(req, 200, "OK", evb); } else { evhttp_send_error(req, HTTP_BADREQUEST, 0); } */ // working code to decode and index data int result = evhttp_parse_query_str(postData.c_str(), ¶ms); // if we were able to parse post data ok if (result == 0) { param = params.tqh_first; std::string key(param->key); std::string value(param->value); // std::cout << value << std::endl; evb = evbuffer_new(); // check that the first key is data if (key.compare(zsearch::server::POST_DATA_KEY) == 0) { try { std::shared_ptr<IDocument> document = std::make_shared<DocumentImpl>(value); unsigned int docId = engine->addDocument(document); std::cout << "Added document: " << docId << std::endl; evbuffer_add_printf(evb, "%d", docId); } catch (const std::string& e) { evbuffer_add_printf(evb, "Error parsing document. See documentation for more details\n"); evbuffer_add_printf(evb, e.c_str()); } catch (const std::exception& e) { evbuffer_add_printf(evb, "Error parsing document. See documentation for more details\n"); evbuffer_add_printf(evb, e.what()); } } else { evbuffer_add_printf(evb, "Invalid post data, first key must be in the form of data -> {xml}. See documentation for more details\n"); } evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/html"); evhttp_send_reply(req, 200, "OK", evb); } else { evhttp_send_error(req, HTTP_BADREQUEST, 0); } evhttp_clear_headers(¶ms); if (evb) { evbuffer_free(evb); } } std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); std::chrono::nanoseconds timeTaken = std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t0); std::cout << ZUtil::printTimeTaken(timeTaken) << std::endl; }
int handle_domain_records(struct evhttp_request * const req, HttpHandlerContext * const context, char *uri, char *opts, _Bool * const write_to_log, const _Bool fake_req) { Key *layer_name; Key *key; (void) opts; if (req->type == EVHTTP_REQ_GET) { Op op; RecordsGetOp * const get_op = &op.records_get_op; char *sep; if ((sep = strchr(uri, '/')) == NULL) { return HTTP_NOTFOUND; } *sep = 0; if ((layer_name = new_key_from_c_string(uri)) == NULL) { *sep = '/'; return HTTP_SERVUNAVAIL; } *sep++ = '/'; if (*sep == 0) { release_key(layer_name); return HTTP_NOTFOUND; } if ((key = new_key_from_c_string(sep)) == NULL) { release_key(layer_name); return HTTP_SERVUNAVAIL; } RecordsOptParseCBContext cb_context = { .with_links = 0 }; if (opts != NULL && query_parse(opts, records_opt_parse_cb, &cb_context) != 0) { release_key(layer_name); return HTTP_BADREQUEST; } *get_op = (RecordsGetOp) { .type = OP_TYPE_RECORDS_GET, .req = req, .fake_req = fake_req, .op_tid = ++context->op_tid, .layer_name = layer_name, .key = key, .with_links = cb_context.with_links }; pthread_mutex_lock(&context->mtx_cqueue); if (push_cqueue(context->cqueue, get_op) != 0) { pthread_mutex_unlock(&context->mtx_cqueue); release_key(layer_name); release_key(key); return HTTP_SERVUNAVAIL; } pthread_mutex_unlock(&context->mtx_cqueue); pthread_cond_signal(&context->cond_cqueue); return 0; } if (req->type == EVHTTP_REQ_PUT) { Op op; RecordsPutOp * const put_op = &op.records_put_op; char *sep; if ((sep = strchr(uri, '/')) == NULL) { return HTTP_NOTFOUND; } *sep = 0; if ((layer_name = new_key_from_c_string(uri)) == NULL) { return HTTP_SERVUNAVAIL; } *sep++ = '/'; if (*sep == 0) { release_key(layer_name); return HTTP_NOTFOUND; } if ((key = new_key_from_c_string(sep)) == NULL) { release_key(layer_name); return HTTP_SERVUNAVAIL; } evbuffer_add(evhttp_request_get_input_buffer(req), "", (size_t) 1U); const char *body = (char *) evbuffer_pullup(evhttp_request_get_input_buffer(req), -1); *put_op = (RecordsPutOp) { .type = OP_TYPE_RECORDS_PUT, .req = req, .fake_req = fake_req, .op_tid = ++context->op_tid, .layer_name = layer_name, .key = key, .position = { .latitude = (Dimension) -1, .longitude = (Dimension) -1 }, .position_set = 0, .properties = NULL, .special_properties = NULL, .expires_at = (time_t) 0 }; RecordsPutOptParseCBContext cb_context = { .put_op = put_op }; if (query_parse(body, records_put_opt_parse_cb, &cb_context) != 0) { free_slip_map(&put_op->properties); free_slip_map(&put_op->special_properties); release_key(layer_name); release_key(key); return HTTP_BADREQUEST; } pthread_mutex_lock(&context->mtx_cqueue); if (push_cqueue(context->cqueue, put_op) != 0) { pthread_mutex_unlock(&context->mtx_cqueue); free_slip_map(&put_op->properties); free_slip_map(&put_op->special_properties); release_key(layer_name); release_key(key); return HTTP_SERVUNAVAIL; } pthread_mutex_unlock(&context->mtx_cqueue); pthread_cond_signal(&context->cond_cqueue); *write_to_log = 1; return 0; } if (req->type == EVHTTP_REQ_DELETE) { Op op; RecordsDeleteOp * const delete_op = &op.records_delete_op; char *sep; if ((sep = strchr(uri, '/')) == NULL) { return HTTP_NOTFOUND; } *sep = 0; if ((layer_name = new_key_from_c_string(uri)) == NULL) { return HTTP_SERVUNAVAIL; } *sep++ = '/'; if (*sep == 0) { release_key(layer_name); return HTTP_NOTFOUND; } if ((key = new_key_from_c_string(sep)) == NULL) { release_key(layer_name); return HTTP_SERVUNAVAIL; } *delete_op = (RecordsDeleteOp) { .type = OP_TYPE_RECORDS_DELETE, .req = req, .fake_req = fake_req, .op_tid = ++context->op_tid, .layer_name = layer_name, .key = key }; pthread_mutex_lock(&context->mtx_cqueue); if (push_cqueue(context->cqueue, delete_op) != 0) { pthread_mutex_unlock(&context->mtx_cqueue); release_key(layer_name); release_key(key); return HTTP_SERVUNAVAIL; } pthread_mutex_unlock(&context->mtx_cqueue); pthread_cond_signal(&context->cond_cqueue); *write_to_log = 1; return 0; } return HTTP_NOTFOUND; }