You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by kx...@apache.org on 2015/12/21 22:38:02 UTC

couch commit: updated refs/heads/master to f33f9fa

Repository: couchdb-couch
Updated Branches:
  refs/heads/master 57ecc0427 -> f33f9fa12


Rewrite via query server

COUCHDB-2874


Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch/commit/f33f9fa1
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch/tree/f33f9fa1
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch/diff/f33f9fa1

Branch: refs/heads/master
Commit: f33f9fa1281fd6c50a86cb9853bd2d9ec2dd007c
Parents: 57ecc04
Author: ermouth <er...@gmail.com>
Authored: Fri Oct 2 13:58:05 2015 +0300
Committer: Alexander Shorin <kx...@apache.org>
Committed: Tue Dec 22 00:05:42 2015 +0300

----------------------------------------------------------------------
 src/couch_native_process.erl |  2 +
 src/couch_query_servers.erl  | 80 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f33f9fa1/src/couch_native_process.erl
----------------------------------------------------------------------
diff --git a/src/couch_native_process.erl b/src/couch_native_process.erl
index dcd01b3..ab279cd 100644
--- a/src/couch_native_process.erl
+++ b/src/couch_native_process.erl
@@ -190,6 +190,8 @@ ddoc(State, {DDoc}, [FunPath, Args]) ->
 
 ddoc(State, {_, Fun}, [<<"validate_doc_update">>], Args) ->
     {State, (catch apply(Fun, Args))};
+ddoc(State, {_, Fun}, [<<"rewrites">>], Args) ->
+    {State, (catch apply(Fun, Args))};
 ddoc(State, {_, Fun}, [<<"filters">>|_], [Docs, Req]) ->
     FilterFunWrapper = fun(Doc) ->
         case catch Fun(Doc, Req) of

http://git-wip-us.apache.org/repos/asf/couchdb-couch/blob/f33f9fa1/src/couch_query_servers.erl
----------------------------------------------------------------------
diff --git a/src/couch_query_servers.erl b/src/couch_query_servers.erl
index 92ba3a3..a3d7a47 100644
--- a/src/couch_query_servers.erl
+++ b/src/couch_query_servers.erl
@@ -17,6 +17,7 @@
 -export([reduce/3, rereduce/3,validate_doc_update/5]).
 -export([filter_docs/5]).
 -export([filter_view/3]).
+-export([rewrite/3]).
 
 -export([with_ddoc_proc/2, proc_prompt/2, ddoc_prompt/3, ddoc_proc_prompt/3, json_doc/1]).
 
@@ -292,6 +293,85 @@ validate_doc_update(DDoc, EditDoc, DiskDoc, Ctx, SecObj) ->
             throw({unknown_error, Message})
     end.
 
+
+rewrite(Req, Db, DDoc) ->
+    Fields = [F || F <- chttpd_external:json_req_obj_fields(),
+              F =/= <<"info">>, F =/= <<"form">>,
+              F =/= <<"uuid">>, F =/= <<"id">>],
+    JsonReq = chttpd_external:json_req_obj(Req, Db, null, Fields),
+    case couch_query_servers:ddoc_prompt(DDoc, [<<"rewrites">>], [JsonReq]) of
+        {[{<<"forbidden">>, Message}]} ->
+            throw({forbidden, Message});
+        {[{<<"unauthorized">>, Message}]} ->
+            throw({unauthorized, Message});
+        [<<"no_dispatch_rule">>] ->
+            undefined;
+        [<<"ok">>, {V}=Rewrite] when is_list(V) ->
+            ok = validate_rewrite_response(Rewrite),
+            Rewrite;
+        [<<"ok">>, _]  ->
+            throw_rewrite_error(<<"bad rewrite">>);
+        V ->
+            couch_log:error("bad rewrite return ~p", [V]),
+            throw({unknown_error, V})
+    end.
+
+validate_rewrite_response({Fields}) when is_list(Fields) ->
+    validate_rewrite_response_fields(Fields).
+
+validate_rewrite_response_fields([{Key, Value} | Rest]) ->
+    validate_rewrite_response_field(Key, Value),
+    validate_rewrite_response_fields(Rest);
+validate_rewrite_response_fields([]) ->
+    ok.
+
+validate_rewrite_response_field(<<"method">>, Method) when is_binary(Method) ->
+    ok;
+validate_rewrite_response_field(<<"method">>, _) ->
+    throw_rewrite_error(<<"bad method">>);
+validate_rewrite_response_field(<<"path">>, Path) when is_binary(Path) ->
+    ok;
+validate_rewrite_response_field(<<"path">>, _) ->
+    throw_rewrite_error(<<"bad path">>);
+validate_rewrite_response_field(<<"body">>, Body) when is_binary(Body) ->
+    ok;
+validate_rewrite_response_field(<<"body">>, _) ->
+    throw_rewrite_error(<<"bad body">>);
+validate_rewrite_response_field(<<"headers">>, {Props}=Headers) when is_list(Props) ->
+    validate_object_fields(Headers);
+validate_rewrite_response_field(<<"headers">>, _) ->
+    throw_rewrite_error(<<"bad headers">>);
+validate_rewrite_response_field(<<"query">>, {Props}=Query) when is_list(Props) ->
+    validate_object_fields(Query);
+validate_rewrite_response_field(<<"query">>, _) ->
+    throw_rewrite_error(<<"bad query">>);
+validate_rewrite_response_field(<<"code">>, Code) when is_integer(Code) andalso Code >= 200 andalso Code < 600 ->
+    ok;
+validate_rewrite_response_field(<<"code">>, _) ->
+    throw_rewrite_error(<<"bad code">>);
+validate_rewrite_response_field(K, V) ->
+    couch_log:debug("unknown rewrite field ~p=~p", [K, V]),
+    ok.
+
+validate_object_fields({Props}) when is_list(Props) ->
+    lists:foreach(fun
+        ({Key, Value}) when is_binary(Key) andalso is_binary(Value) ->
+            ok;
+        ({Key, Value}) ->
+            Reason = io_lib:format(
+                "object key/value must be strings ~p=~p", [Key, Value]),
+            throw_rewrite_error(Reason);
+        (Value) ->
+            throw_rewrite_error(io_lib:format("bad value ~p", [Value]))
+    end, Props).
+
+
+throw_rewrite_error(Reason) when is_list(Reason)->
+    throw_rewrite_error(iolist_to_binary(Reason));
+throw_rewrite_error(Reason) when is_binary(Reason) ->
+    throw({rewrite_error, Reason}).
+
+
 json_doc_options() ->
     json_doc_options([]).