benoitc / couchbeam

Apache CouchDB client in Erlang
Other
242 stars 114 forks source link

Attachment with ID contains "/" is not working #19

Closed sendtopms closed 14 years ago

sendtopms commented 15 years ago

couchbeam_db is encoding incoming Id (please look at the issue "couchbeam with url encoded "_id" is not working" - issue18) but it is not enoding the document "Id" which is retrieved from couchdb to do attachment an it is breaking when "Id" contains "/".

sendtopms commented 15 years ago

Exact method which has "hot" code is

handle_call({put_attachment, Doc, Content, AName, Length, ContentType}, _From, 
            #db{couchdb=C, base=Base}=State) ->
    {DocId, Rev, IsJson} = case Doc of
        {Id, Rev1} -> {Id, Rev1, false};
        _ ->
            DocId1 = couchbeam_doc:get_value(<<"_id">>, Doc),
            Rev2 = couchbeam_doc:get_value(<<"_rev">>, Doc),
            {DocId1, Rev2, true}
    end,
    Headers = [{"Content-Length", couchbeam_util:val(Length)}, {"Content-Type", ContentType}],
    Path = io_lib:format("~s/~s/~s", [Base, DocId, AName]),
    Resp = case couchbeam_resource:put(C, Path, Headers, [{"rev", Rev}], Content, []) of
        {error, Reason} -> Reason;
        {ok, R} when (IsJson =:= true) ->
             {Props} = R,
             NewRev = proplists:get_value(<<"rev">>, Props),
             DocId2 = proplists:get_value(<<"id">>, Props),
             Doc1 = couchbeam_doc:set_value(<<"_id">>, DocId2, Doc),
             Doc2 = couchbeam_doc:set_value(<<"_rev">>, NewRev, Doc1),
             Doc2;
        {ok, R} ->  R
    end,
    {reply, Resp, State};

----------------------------------------------- Fixed version ------------------

handle_call({put_attachment, Doc, Content, AName, Length, ContentType}, _From, 
            #db{couchdb=C, base=Base}=State) ->
    {DocId0, Rev, IsJson} = case Doc of
        {Id, Rev1} -> {Id, Rev1, false};
        _ ->
            DocId1 = couchbeam_doc:get_value(<<"_id">>, Doc),
            Rev2 = couchbeam_doc:get_value(<<"_rev">>, Doc),
            {DocId1, Rev2, true}
    end,
    DocId1 = case is_list(DocId0) of 
                true->
                    couchbeam_util:url_encode(DocId0);
                false->
                    couchbeam_util:url_encode(binary_to_list(DocId0))
            end,
    DocId = couchbeam_util:url_encode(DocId1),

    Headers = [{"Content-Length", couchbeam_util:val(Length)}, {"Content-Type", ContentType}],
    Path = io_lib:format("~s/~s/~s", [Base, DocId, AName]),
    Resp = case couchbeam_resource:put(C, Path, Headers, [{"rev", Rev}], Content, []) of
        {error, Reason} -> Reason;
        {ok, R} when (IsJson =:= true) ->
             {Props} = R,
             NewRev = proplists:get_value(<<"rev">>, Props),
             DocId2 = proplists:get_value(<<"id">>, Props),
             Doc1 = couchbeam_doc:set_value(<<"_id">>, DocId2, Doc),
             Doc2 = couchbeam_doc:set_value(<<"_rev">>, NewRev, Doc1),
             Doc2;
        {ok, R} ->  R
    end,
    {reply, Resp, State};
sendtopms commented 15 years ago

Sorry for the bad formatting

benoitc commented 14 years ago

so am not sure to understand this report. Actually what couchbeam do is :

which should be the correct behavior. Am I missed something ?

benoitc commented 14 years ago

mmm sry previous comment wasn't concerning this bug

benoitc commented 14 years ago

fixed in latest head. thanks