{"error":"bad_request","reason":"attachments not supported in Couchbase"}


#1

hi,
i try to use lcb_make_http_request to get data from view, it return LCB_SUCCESS but the response is :
{“error”:“bad_request”,“reason”:“attachments not supported in Couchbase”}
what this mean?
I run the uri in web browser, i can get result
host:8092/bucketname/_design/dev_prod/_view/view_name?startkey=“123456789”&limit=10

similar question has been asked, but no answer yet:

thanks!


#2

I get the same thing following the REST API to a T to create a new view. Even though the documentation says to use an attachment. My guess is the documentation is wrong.

Here is an example of my restful call that fails

curl -X PUT -H ‘Content-Type: application/json’ http://user:password@localhost:8092/bucket/_design/name/newView -d @newView.ddoc

And the response:
{“error”:“bad_request”,“reason”:“attachments not supported in Couchbase”}

I’ve found a lot of the REST API documentation to be completely inaccurate or just doesn’t work, which makes it rather difficult to extend and incorporate couchbase into any environment.


#3

looks like I’m not the only one get this error. is it a bug?


#4

Could you post a snippet of code you are using to make a query?


#5

You are doing something wrong. I’ve just checked and it works:

$ curl -v -X PUT -H 'Content-Type: application/json' http://node.avsej.net:8092/default/_design/blog -d'{"_id":"_design/blog","language":"javascript","views":{"recent_posts":{"map":"function(doc){if(doc.date&&doc.title){emit(doc.date,doc.title);}}"}}}'
* About to connect() to node.avsej.net port 8092 (#0)
*   Trying 50.116.6.84...
* Adding handle: conn: 0xa51e10
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0xa51e10) send_pipe: 1, recv_pipe: 0
* Connected to node.avsej.net (50.116.6.84) port 8092 (#0)
> PUT /default/_design/blog HTTP/1.1
> User-Agent: curl/7.31.0
> Host: node.avsej.net:8092
> Accept: */*
> Content-Type: application/json
> Content-Length: 147
> 
* upload completely sent off: 147 out of 147 bytes
< HTTP/1.1 201 Created
* Server MochiWeb/1.0 (Any of you quaids got a smint?) is not blacklisted
< Server: MochiWeb/1.0 (Any of you quaids got a smint?)
< Location: http://node.avsej.net:8092/default/_design/blog
< Date: Thu, 25 Jul 2013 05:40:42 GMT
< Content-Type: text/plain;charset=utf-8
< Content-Length: 32
< Cache-Control: must-revalidate
< 
{"ok":true,"id":"_design/blog"}
* Connection #0 to host node.avsej.net left intact

Also example, based on lcb_make_http_request manpage works well too:

#include 
#include 
#include 
#include 

static void error_callback(lcb_t instance, lcb_error_t error, const char *errinfo)
{
    fprintf(stderr, "ERROR: %s (0x%x), %s\n", lcb_strerror(instance, error), error, errinfo);
    exit(EXIT_FAILURE);
}

static void complete_callback(lcb_http_request_t req, lcb_t instance,
                              const void *cookie, lcb_error_t error,
                              const lcb_http_resp_t *resp)
{
    size_t ii;

    if (resp->v.v0.headers) {
        const char *const *headers = resp->v.v0.headers;
        for (ii = 1; *headers != NULL; ++ii, ++headers) {
            fprintf(stderr, "%s%s", *headers, (ii % 2 == 0) ? "\n" : ": ");
        }
    }
    fprintf(stderr, "\"");
    fwrite(resp->v.v0.path, sizeof(char), resp->v.v0.npath, stderr);
    fprintf(stderr, "\": ");
    if (error == LCB_SUCCESS) {
        fprintf(stderr, "OK Size: %d", (int)resp->v.v0.nbytes);
        fwrite(resp->v.v0.bytes, sizeof(char), resp->v.v0.nbytes, stdout);
    } else {
        fprintf(stderr, "FAIL(%d) %s Status:%d Size:%d\n",
                error, lcb_strerror(instance, error),
                resp->v.v0.status, (int)resp->v.v0.nbytes);
    }
    fwrite(resp->v.v0.bytes, sizeof(char), resp->v.v0.nbytes, stdout);
    fprintf(stderr, "\n");
    (void)req;
    (void)cookie;
}

int main(int argc, char *argv[])
{
    lcb_error_t err;
    lcb_t instance;
    struct lcb_create_st create_options;

    memset(&create_options, 0, sizeof(create_options));

    create_options.v.v0.host = "node.avsej.net:8091";
    create_options.v.v0.bucket = "default";
    create_options.v.v0.user = NULL;
    create_options.v.v0.passwd = NULL;
    err = lcb_create(&instance, &create_options);
    if (err != LCB_SUCCESS) {
        fprintf(stderr, "Failed to create libcouchbase instance: %s\n", lcb_strerror(NULL, err));
        return 1;
    }
    (void)lcb_set_error_callback(instance, error_callback);
    /* Initiate the connect sequence in libcouchbase */
    if ((err = lcb_connect(instance)) != LCB_SUCCESS) {
        fprintf(stderr, "Failed to initiate connect: %s\n", lcb_strerror(NULL, err));
        lcb_destroy(instance);
        return 1;
    }
    (void)lcb_set_http_complete_callback(instance, complete_callback);
    /* Run the event loop and wait until we've connected */
    lcb_wait(instance);

    {
        const char docid[] = "_design/test2";
        const char doc[] = "{\"views\":{\"all\":{\"map\":\"function (doc, meta) { emit(meta.id, null); }\"}}}";
        lcb_http_cmd_t cmd;
        lcb_http_request_t req;
	lcb_error_t err;

        cmd.version = 0;
        cmd.v.v0.path = docid;
        cmd.v.v0.npath = strlen(docid);
        cmd.v.v0.body = doc;
        cmd.v.v0.nbody = strlen(doc);
        cmd.v.v0.method = LCB_HTTP_METHOD_PUT;
        cmd.v.v0.content_type = "application/json";
        err = lcb_make_http_request(instance, NULL, LCB_HTTP_TYPE_VIEW, &cmd, &req);
        if (err != LCB_SUCCESS) {
            fprintf(stderr, "Failed to schedule HTTP request: %s\n", lcb_strerror(instance, err));
            lcb_destroy(instance);
            return 1;
        }
        lcb_wait(instance);
    }
    lcb_destroy(instance);

    return 0;
}

#6

Thanks for the detailed comment. I was definitely doing it wrong, and missing the appropriate views, and map definition in my json. Not to mention having unescaped carriage returns (which produces a different , but accurate error).


#7

hi, avsej:
couple questions regarding the c code:

  1. i use data_callback instead of complete_callback

  2. i use LCB_HTTP_METHOD_GET not POST or PUT, because i intend to get something from view
    so cmd.v.v0.body is empty, cmd.v.v0.nbody == 0,

  3. should we assign full path to cmd.v.v0.path ? like:
    string uri = host + “:” + VIEW_PORT + “/” + _bucketname + “/_design/”+_designdocname + “/_view/” + _viewname +"?key="+ “”" + _key +""";

my code:

lcb_error_t err;
lcb_http_cmd_t cmd;
string uri;
uri = host + “:” + VIEW_PORT + “/” + _bucketname + “/_design/”+_designdocname + “/_view/” + _viewname +"?startkey="+ “”" + _key +""";

if(_pageId > 1)
{
uri += “&startkey_docid=” + _lastDocID;
uri += “&skip=1”;
}
if(_limit > 0)
{
stringstream ss;
ss << _limit;
uri += “&limit=” + ss.str();
}
std::cout<<“uri:”<<uri<<std::endl;
size_t nbytes = 0;
const char * bytes = _postData.c_str();
if (bytes) {
nbytes = strlen(bytes);
}
cmd.version = 0;
cmd.v.v0.path = uri.c_str();
cmd.v.v0.npath = strlen(uri.c_str());
cmd.v.v0.body = bytes;
cmd.v.v0.nbody = nbytes;
cmd.v.v0.method = bytes ? LCB_HTTP_METHOD_POST : LCB_HTTP_METHOD_GET;
cmd.v.v0.chunked = true;
cmd.v.v0.content_type = “application/json”;
err = lcb_make_http_request(instance, (void *)this, LCB_HTTP_TYPE_VIEW, &cmd, NULL);
if (err != LCB_SUCCESS) {
fprintf(stderr, “Failed to get view by key: %s\n”,
lcb_strerror(NULL, err));
return false;
}
lcb_wait(instance);
_response = outResponse;
return true;

static void data_callback(lcb_http_request_t request, lcb_t instance, const void *cookie, lcb_error_t error, const lcb_http_resp_t *resp) { if (error != LCB_SUCCESS) { return; } CouchbaseHandler *couchbaseHandler; couchbaseHandler = const_cast(reinterpret_cast(cookie));
string response;
if(resp->v.v0.bytes)
{
	response.assign((const char*)resp->v.v0.bytes,resp->v.v0.nbytes);
	couchbaseHandler->setOutResponse(response);
}

}

note that i assigned outResponse with response from view in data_callback.

thanks!


#8

It should be

"/_design/"+_designdocname + "/_view/" + _viewname +"?startkey="+ "\"" + _key +"\""