/** 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; }
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; }
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; }