/** Query a Couchbase design document view
 *
 * Setup and execute a Couchbase view request and wait for the result.
 *
 * @param  instance Couchbase connection instance.
 * @param  cookie   Couchbase cookie for returning information from callbacks.
 * @param  path     The fully qualified view path including the design document and view name.
 * @param  post     The post payload (NULL for none).
 * @return          Couchbase error object.
 */
lcb_error_t couchbase_query_view(lcb_t instance, const void *cookie, const char *path, const char *post) {
	lcb_error_t error;                   /* couchbase command return */
	lcb_http_cmd_t cmd;                  /* http command struct */
	const lcb_http_cmd_t *commands;      /* http commands array */

	commands = &cmd;
	memset(&cmd, 0, sizeof(cmd));

	/* populate command struct */
	cmd.v.v0.path = path;
	cmd.v.v0.npath = strlen(cmd.v.v0.path);
	cmd.v.v0.body = post;
	cmd.v.v0.nbody = post ? strlen(post) : 0;
	cmd.v.v0.method = post ? LCB_HTTP_METHOD_POST : LCB_HTTP_METHOD_GET;
	cmd.v.v0.chunked = 1;
	cmd.v.v0.content_type = "application/json";

	/* query the view */
	if ((error = lcb_make_http_request(instance, cookie, LCB_HTTP_TYPE_VIEW, commands, NULL)) == LCB_SUCCESS) {
		/* enter event loop on success */
		lcb_wait(instance);
	}

	/* return error */
	return error;
}
Exemple #2
0
ERL_NIF_TERM cb_http(ErlNifEnv* env, handle_t* handle, void* obj)
{
    http_args_t* args = (http_args_t*)obj;

    struct libcouchbase_callback cb;
    lcb_error_t ret;
    lcb_http_request_t req;

    lcb_http_cmd_t cmd;
    cmd.version = 0;
    cmd.v.v0.path = args->path;
    cmd.v.v0.npath = strlen(args->path);
    cmd.v.v0.body = args->body;
    cmd.v.v0.nbody = strlen(args->body);
    cmd.v.v0.method = args->method;
    cmd.v.v0.chunked = 0; // no support for chunking
    cmd.v.v0.content_type = args->content_type;

    ret = lcb_make_http_request(handle->instance, &cb, args->type, &cmd, &req);

    if (ret != LCB_SUCCESS) {
        return return_lcb_error(env, ret);
    }

    lcb_wait(handle->instance);

    if(cb.error != LCB_SUCCESS) {
        return return_lcb_error(env, cb.error);
    }

    ErlNifBinary value_binary;
    enif_alloc_binary(cb.size, &value_binary);
    memcpy(value_binary.data, cb.data, cb.size);
    return enif_make_tuple2(env, A_OK(env), enif_make_binary(env, &value_binary));
}
/*
 * Execute {Bucket::CouchRequest}
 *
 * @since 1.2.0
 */
    VALUE
cb_http_request_perform(VALUE self)
{
    struct http_request_st *req = DATA_PTR(self);
    struct context_st *ctx;
    VALUE rv, exc;
    lcb_error_t err;
    struct bucket_st *bucket;

    ctx = xcalloc(1, sizeof(struct context_st));
    if (ctx == NULL) {
        rb_raise(eClientNoMemoryError, "failed to allocate memory");
    }
    rv = Qnil;
    ctx->rv = &rv;
    ctx->bucket = bucket = req->bucket;
    ctx->proc = rb_block_given_p() ? rb_block_proc() : req->on_body_callback;
    ctx->extended = req->extended;
    ctx->request = req;
    ctx->headers_val = cb_gc_protect(bucket, rb_hash_new());

    err = lcb_make_http_request(bucket->handle, (const void *)ctx,
            req->type, &req->cmd, &req->request);
    exc = cb_check_error(err, "failed to schedule document request",
            STR_NEW(req->cmd.v.v0.path, req->cmd.v.v0.npath));
    if (exc != Qnil) {
        xfree(ctx);
        rb_exc_raise(exc);
    }
    req->running = 1;
    req->ctx = ctx;
    if (bucket->async) {
        return Qnil;
    } else {
        lcb_wait(bucket->handle);
        if (req->completed) {
            exc = ctx->exception;
            xfree(ctx);
            if (exc != Qnil) {
                cb_gc_unprotect(bucket, exc);
                rb_exc_raise(exc);
            }
            return rv;
        } else {
            return Qnil;
        }
    }
    return Qnil;
}
/*
 * Execute {Bucket::CouchRequest}
 *
 * @since 1.2.0
 */
VALUE
cb_http_request_perform(VALUE self)
{
    struct cb_http_request_st *req = DATA_PTR(self);
    struct cb_context_st *ctx;
    VALUE rv, exc;
    lcb_error_t err;
    struct cb_bucket_st *bucket = req->bucket;

    if (bucket->handle == NULL) {
        rb_raise(cb_eConnectError, "closed connection");
    }

    ctx = cb_context_alloc(bucket);
    ctx->rv = Qnil;
    ctx->proc = rb_block_given_p() ? rb_block_proc() : req->on_body_callback;
    ctx->extended = req->extended;
    ctx->request = req;
    ctx->headers_val = rb_hash_new();

    err = lcb_make_http_request(bucket->handle, (const void *)ctx,
                                req->type, &req->cmd, &req->request);
    exc = cb_check_error(err, "failed to schedule document request",
                         STR_NEW(req->cmd.v.v0.path, req->cmd.v.v0.npath));
    if (exc != Qnil) {
        lcb_cancel_http_request(bucket->handle, req->request);
        rb_exc_raise(exc);
    }
    req->running = 1;
    req->ctx = ctx;
    if (bucket->async) {
        return Qnil;
    } else {
        lcb_wait(bucket->handle);
        if (req->completed) {
            rv = ctx->rv;
            exc = ctx->exception;
            cb_context_free(ctx);
            if (exc != Qnil) {
                rb_exc_raise(exc);
            }
            return rv;
        } else {
            return Qnil;
        }
    }
    return Qnil;
}
/** Query a Couchbase design document view
 *
 * Setup and execute a Couchbase view request and wait for the result.
 *
 * @param  instance Couchbase connection instance.
 * @param  cookie   Couchbase cookie for returning information from callbacks.
 * @param  path     The fully qualified view path including the design document and view name.
 * @param  post     The post payload (NULL for none).
 * @return          Couchbase error object.
 */
lcb_error_t couchbase_query_view(lcb_t instance, const void *cookie, const char *path, const char *post)
{
	cookie_u cu;                         /* union of const and non const pointers */
	cu.cdata = cookie;                   /* set const union member to cookie passed from couchbase */
	cookie_t *c = (cookie_t *) cu.data;  /* set our cookie struct using non-const member */
	lcb_error_t error;                   /* couchbase command return */
	lcb_http_cmd_t cmd;                  /* http command struct */
	const lcb_http_cmd_t *commands;      /* http commands array */

	commands = &cmd;
	memset(&cmd, 0, sizeof(cmd));

	/* populate command struct */
	cmd.v.v0.path = path;
	cmd.v.v0.npath = strlen(cmd.v.v0.path);
	cmd.v.v0.body = post;
	cmd.v.v0.nbody = post ? strlen(post) : 0;
	cmd.v.v0.method = post ? LCB_HTTP_METHOD_POST : LCB_HTTP_METHOD_GET;
	cmd.v.v0.chunked = 1;
	cmd.v.v0.content_type = "application/json";

	/* clear cookie */
	memset(c, 0, sizeof(cookie_t));

	/* init tokener error */
	c->jerr = json_tokener_success;

	/* create token */
	c->jtok = json_tokener_new();

	/* debugging */
	DEBUG3("rlm_couchbase: fetching view %s", path);

	/* query the view */
	if ((error = lcb_make_http_request(instance, c, LCB_HTTP_TYPE_VIEW, commands, NULL)) == LCB_SUCCESS) {
		/* enter event loop on success */
		lcb_wait(instance);
	}

	/* free token */
	json_tokener_free(c->jtok);

	/* return error */
	return error;
}
Exemple #6
0
static void do_rest_flush(INTERNAL_FUNCTION_PARAMETERS,
						  int oo,
						  php_couchbase_res *res)
{
	struct flush_ctx ctx;
	lcb_error_t rc;
	lcb_http_cmd_t cmd;
	lcb_t instance;
	char *path;
	lcb_http_complete_callback old;

	instance = res->handle;
	path = ecalloc(strlen(res->bucket) + 80, 1);
	sprintf(path, "/pools/default/buckets/%s/controller/doFlush",
			res->bucket);

	memset(&ctx, 0, sizeof(ctx));
	memset(&cmd, 0, sizeof(cmd));
	cmd.v.v0.path = path;
	cmd.v.v0.npath = strlen(path);
	cmd.v.v0.method = LCB_HTTP_METHOD_POST;
	cmd.v.v0.content_type = "application/x-www-form-urlencoded";

	old = lcb_set_http_complete_callback(instance, rest_flush_callback);
	rc = lcb_make_http_request(instance, &ctx, LCB_HTTP_TYPE_MANAGEMENT,
							   &cmd, NULL);
	old = lcb_set_http_complete_callback(instance, old);

	efree(path);
	if (rc == LCB_SUCCESS) {
		rc = ctx.error;
	}
	res->rc = rc;

	if (rc != LCB_SUCCESS) {
		/* An error occured occurred on libcouchbase level */
		if (ctx.payload) {
			efree(ctx.payload);
		}

		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_lcb_exception, "Failed to flush bucket: %s",
							   lcb_strerror(instance, rc));
		return;
	}

	switch (ctx.status)  {
	case LCB_HTTP_STATUS_OK:
	case LCB_HTTP_STATUS_ACCEPTED:
		efree(ctx.payload);
		RETURN_TRUE;

	case LCB_HTTP_STATUS_UNAUTHORIZED:
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_auth_exception, "Incorrect credentials");
		break;

	default:
		if (ctx.payload == NULL) {
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
								   cb_server_exception,
								   "{\"errors\":{\"http response\": %d }}",
								   (int)ctx.status);
		} else {
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
								   cb_server_exception,
								   ctx.payload);
		}
	}

	if (ctx.payload != NULL) {
		efree(ctx.payload);
	}
}
PHP_COUCHBASE_LOCAL
void php_couchbase_delget_design_doc_impl(INTERNAL_FUNCTION_PARAMETERS, int oo, int rem)
{
	char *path;
	char *name = NULL;
	long nname = 0;
	php_couchbase_res *couchbase_res;
	int argflags;
	lcb_t instance;
	lcb_error_t rc;
	struct http_ctx ctx;
	lcb_http_cmd_t cmd;
	lcb_http_complete_callback old;
	int len;

	if (oo) {
		argflags = PHP_COUCHBASE_ARG_F_OO;
	} else {
		argflags = PHP_COUCHBASE_ARG_F_FUNCTIONAL;
	}

	PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "s", &name, &nname);

	if (!nname) {
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_illegal_key_exception,
							   "You have to specify the name of the design doc");
		return;
	}

	memset(&ctx, 0, sizeof(ctx));
	memset(&cmd, 0, sizeof(cmd));
	instance = couchbase_res->handle;
	path = ecalloc(1, 80 + nname);
	len = sprintf(path, "/_design/%*s", (int)nname, name);
	cmd.v.v0.path = path;
	cmd.v.v0.npath = len;
	if (rem) {
		cmd.v.v0.method = LCB_HTTP_METHOD_DELETE;
	} else {
		cmd.v.v0.method = LCB_HTTP_METHOD_GET;
	}
	cmd.v.v0.content_type = "application/json";

	old = lcb_set_http_complete_callback(instance, http_callback);
	lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS);
	rc = lcb_make_http_request(instance, &ctx, LCB_HTTP_TYPE_VIEW, &cmd, NULL);
	lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS);
	old = lcb_set_http_complete_callback(instance, old);

	efree(path);
	if (rc == LCB_SUCCESS) {
		rc = ctx.error;
	}
	couchbase_res->rc = rc;

	if (rc != LCB_SUCCESS) {
		/* An error occured occurred on libcouchbase level */
		efree(ctx.payload);
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_lcb_exception,
							   "Failed to retrieve design doc: %s",
							   lcb_strerror(instance, rc));
		return;
	}

	switch (ctx.status)  {
	case LCB_HTTP_STATUS_OK:
		if (rem) {
			efree(ctx.payload);
			RETURN_TRUE;
		} else {
			RETURN_STRING(ctx.payload, 0);
		}
		/* not reached */

	case LCB_HTTP_STATUS_NOT_FOUND:
		efree(ctx.payload);
		RETURN_FALSE;

	case LCB_HTTP_STATUS_UNAUTHORIZED:
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_auth_exception, "Incorrect credentials");
		break;

	default:
		if (ctx.payload == NULL) {
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
								   cb_server_exception,
								   "{\"errors\":{\"http response\": %d }}",
								   (int)ctx.status);
		} else {
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
								   cb_server_exception,
								   ctx.payload);
		}
	}

	efree(ctx.payload);
}
PHP_COUCHBASE_LOCAL
void php_couchbase_list_design_docs_impl(INTERNAL_FUNCTION_PARAMETERS, int oo)
{
	php_couchbase_res *couchbase_res;
	int argflags;
	lcb_t instance;
	lcb_error_t rc;
	struct http_ctx ctx;
	lcb_http_cmd_t cmd;
	lcb_http_complete_callback old;
	int len;
	char *path;

	if (oo) {
		argflags = PHP_COUCHBASE_ARG_F_OO;
	} else {
		argflags = PHP_COUCHBASE_ARG_F_FUNCTIONAL;
	}

	PHP_COUCHBASE_GET_PARAMS(couchbase_res, argflags, "");
	instance = couchbase_res->handle;

	memset(&ctx, 0, sizeof(ctx));
	memset(&cmd, 0, sizeof(cmd));

	path = ecalloc(strlen(couchbase_res->bucket) + 80, 1);
	len = sprintf(path, "/pools/default/buckets/%s/ddocs",
				  couchbase_res->bucket);
	cmd.v.v0.path = path;
	cmd.v.v0.npath = len;
	cmd.v.v0.method = LCB_HTTP_METHOD_GET;
	cmd.v.v0.content_type = "application/json";

	old = lcb_set_http_complete_callback(instance, http_callback);
	lcb_behavior_set_syncmode(instance, LCB_SYNCHRONOUS);
	rc = lcb_make_http_request(instance, &ctx, LCB_HTTP_TYPE_MANAGEMENT,
							   &cmd, NULL);
	lcb_behavior_set_syncmode(instance, LCB_ASYNCHRONOUS);
	old = lcb_set_http_complete_callback(instance, old);
	efree(path);

	if (rc == LCB_SUCCESS) {
		rc = ctx.error;
	}
	couchbase_res->rc = rc;

	if (rc != LCB_SUCCESS) {
		/* An error occured occurred on libcouchbase level */
		efree(ctx.payload);
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_lcb_exception,
							   "Failed to retrieve design doc: %s",
							   lcb_strerror(instance, rc));
		return;
	}

	switch (ctx.status)  {
	case LCB_HTTP_STATUS_OK:
		RETURN_STRING(ctx.payload, 0);

	case LCB_HTTP_STATUS_UNAUTHORIZED:
		couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
							   cb_auth_exception, "Incorrect credentials");
		break;

	default:
		if (ctx.payload == NULL) {
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
								   cb_server_exception,
								   "{\"errors\":{\"http response\": %d }}",
								   (int)ctx.status);
		} else {
			couchbase_report_error(INTERNAL_FUNCTION_PARAM_PASSTHRU, oo,
								   cb_server_exception,
								   ctx.payload);
		}
	}

	efree(ctx.payload);
}
PyObject *
pycbc_Connection__http_request(pycbc_Connection *self,
                               PyObject *args,
                               PyObject *kwargs)
{
    int rv;
    int method;
    int reqtype;
    int quiet = 0;
    unsigned short value_format = 0;
    lcb_error_t err;

    const char *body = NULL;
    PyObject *ret = NULL;
    PyObject *quiet_O = NULL;
    PyObject *fetch_headers_O = Py_False;
    pycbc_strlen_t nbody = 0;
    const char *path = NULL;
    const char *content_type = NULL;
    pycbc_HttpResult *htres;

    lcb_http_request_t htreq = NULL;
    lcb_http_cmd_t htcmd = { 0 };

    static char *kwlist[] = {
            "type", "method", "path", "content_type", "post_data",
            "response_format", "quiet", "fetch_headers", NULL
    };

    rv = PyArg_ParseTupleAndKeywords(args, kwargs,
                                     "iis|zz#HOO", kwlist,
                                     &reqtype,
                                     &method,
                                     &path,
                                     &content_type,
                                     &body,
                                     &nbody,
                                     &value_format,
                                     &quiet_O,
                                     &fetch_headers_O);
    if (!rv) {
        PYCBC_EXCTHROW_ARGS();
        return NULL;
    }
    if (quiet_O != NULL) {
        if (quiet_O == Py_None) {
            quiet = 0;
        } else {
            quiet = PyObject_IsTrue(quiet_O);
        }
    }

    htres = pycbc_httpresult_new(self);
    htres->key = pycbc_SimpleStringZ(path);
    htres->format = value_format;

    if (fetch_headers_O && PyObject_IsTrue(fetch_headers_O)) {
        htres->headers = PyDict_New();
    }

    htcmd.v.v1.body = body;
    htcmd.v.v1.nbody = nbody;
    htcmd.v.v1.content_type = content_type;
    htcmd.v.v1.path = path;
    htcmd.v.v1.npath = strlen(path);
    htcmd.v.v1.method = method;


    err = lcb_make_http_request(self->instance,
                                htres,
                                reqtype,
                                &htcmd,
                                &htreq);

    if (err != LCB_SUCCESS) {
        PYCBC_EXCTHROW_SCHED(err);
        goto GT_DONE;
    }

    err = pycbc_oputil_wait_common(self);

    if (err != LCB_SUCCESS) {
        PYCBC_EXCTHROW_WAIT(err);
        goto GT_DONE;
    }

    if (quiet == 0 && pycbc_httpresult_ok(htres) == 0) {
        PYCBC_EXC_WRAP_EX(htres->rc ? PYCBC_EXC_LCBERR : PYCBC_EXC_HTTP,
                          htres->rc,
                          "HTTP Request failed. Examine 'objextra' for "
                          "full result",
                          htres->key,
                          (PyObject*)htres);
        goto GT_DONE;
    }

    ret = (PyObject*)htres;
    htres = NULL;

    GT_DONE:
    Py_XDECREF(htres);
    return ret;
}
PyObject *
pycbc_Connection__http_request(pycbc_Connection *self,
                               PyObject *args,
                               PyObject *kwargs)
{
    int rv;
    int method;
    int reqtype;
    unsigned short value_format = 0;
    lcb_error_t err;

    const char *body = NULL;
    PyObject *ret = NULL;
    PyObject *quiet_O = NULL;
    PyObject *chunked_O = NULL;
    PyObject *fetch_headers_O = Py_False;
    pycbc_strlen_t nbody = 0;
    const char *path = NULL;
    const char *content_type = NULL;
    pycbc_HttpResult *htres;
    lcb_http_request_t l_htreq;

    lcb_http_cmd_t htcmd = { 0 };

    static char *kwlist[] = {
            "type", "method", "path", "content_type", "post_data",
            "response_format", "quiet", "fetch_headers",
            "chunked", NULL
    };

    rv = PyArg_ParseTupleAndKeywords(args, kwargs,
                                     "iis|zz#HOOO", kwlist,
                                     &reqtype,
                                     &method,
                                     &path,
                                     &content_type,
                                     &body,
                                     &nbody,
                                     &value_format,
                                     &quiet_O,
                                     &fetch_headers_O,
                                     &chunked_O);
    if (!rv) {
        PYCBC_EXCTHROW_ARGS();
        return NULL;
    }

    if (-1 == pycbc_oputil_conn_lock(self)) {
        return NULL;
    }


    htres = pycbc_httpresult_new(self);
    htres->key = pycbc_SimpleStringZ(path);
    htres->format = value_format;
    htres->htflags = 0;

    if (quiet_O != NULL && quiet_O != Py_None && PyObject_IsTrue(quiet_O)) {
        htres->htflags |= PYCBC_HTRES_F_QUIET;
    }

    if (fetch_headers_O && PyObject_IsTrue(fetch_headers_O)) {
        htres->headers = PyDict_New();
    }

    if (chunked_O && PyObject_IsTrue(chunked_O)) {
        htcmd.v.v0.chunked = 1;
        htres->rctx = lcbex_vrow_create();
        htres->rctx->callback = http_vrow_callback;
        htres->rctx->user_cookie = htres;
        htres->htflags |= PYCBC_HTRES_F_CHUNKED;
    }

    htcmd.v.v1.body = body;
    htcmd.v.v1.nbody = nbody;
    htcmd.v.v1.content_type = content_type;
    htcmd.v.v1.path = path;
    htcmd.v.v1.npath = strlen(path);
    htcmd.v.v1.method = method;


    err = lcb_make_http_request(self->instance,
                                htres,
                                reqtype,
                                &htcmd,
                                &l_htreq);

    if (err != LCB_SUCCESS) {
        PYCBC_EXCTHROW_SCHED(err);
        goto GT_DONE;
    }

    htres->htreq = l_htreq;

    if (htcmd.v.v0.chunked) {
        ret = (PyObject*)htres;
        htres = NULL;
        goto GT_DONE;
    }

    self->nremaining++;
    err = pycbc_oputil_wait_common(self);

    if (err != LCB_SUCCESS) {
        self->nremaining--;
        PYCBC_EXCTHROW_WAIT(err);
        goto GT_DONE;
    }

    if (maybe_raise(htres)) {
        goto GT_DONE;
    }

    ret = (PyObject*)htres;
    htres = NULL;

    GT_DONE:
    Py_XDECREF(htres);
    pycbc_oputil_conn_unlock(self);
    return ret;
}