Пример #1
0
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);
}
Пример #2
0
  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);
    }
    
  }
Пример #3
0
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;
}
Пример #4
0
/**
 * 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(), &params);

		// 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(&params);

		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;
}
Пример #5
0
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;
}