summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@apache.org>2019-10-25 12:18:03 -0400
committerNick Vatamaniuc <nickva@users.noreply.github.com>2019-10-28 12:51:21 -0400
commit053d494e698181ae3b0b0698055f5a24e7995172 (patch)
tree759b7b69bbd18e4c2cfe8cb5024760153e4dd843
parentb99d6e09052f04bb6655829d7ab51128ea88310f (diff)
downloadcouchdb-053d494e698181ae3b0b0698055f5a24e7995172.tar.gz
Implement separate source and target replication proxies
Previously if a proxy was specified it was used for both source and target traffic. However, as mentioned in #2272, since both source and target now are URLs, instead of one being a "local" database, it makes sense to allow separate proxy settings for source and target endpoints. We are still allowing old style, single proxy setting, however if users set both the old style proxy and a per-endpoint one, an exception is raised about the settings being mutually exclusive. Fixes #2272
-rw-r--r--src/couch_replicator/src/couch_replicator_docs.erl25
-rw-r--r--src/couch_replicator/test/eunit/couch_replicator_proxy_tests.erl49
2 files changed, 70 insertions, 4 deletions
diff --git a/src/couch_replicator/src/couch_replicator_docs.erl b/src/couch_replicator/src/couch_replicator_docs.erl
index d097a16c1..619063222 100644
--- a/src/couch_replicator/src/couch_replicator_docs.erl
+++ b/src/couch_replicator/src/couch_replicator_docs.erl
@@ -241,15 +241,15 @@ parse_rep_doc(Doc, UserCtx) ->
-spec parse_rep_doc_without_id({[_]}, #user_ctx{}) -> {ok, #rep{}}.
parse_rep_doc_without_id({Props}, UserCtx) ->
- Proxy = get_value(<<"proxy">>, Props, <<>>),
+ {SrcProxy, TgtProxy} = parse_proxy_settings(Props),
Opts = make_options(Props),
case get_value(cancel, Opts, false) andalso
(get_value(id, Opts, nil) =/= nil) of
true ->
{ok, #rep{options = Opts, user_ctx = UserCtx}};
false ->
- Source = parse_rep_db(get_value(<<"source">>, Props), Proxy, Opts),
- Target = parse_rep_db(get_value(<<"target">>, Props), Proxy, Opts),
+ Source = parse_rep_db(get_value(<<"source">>, Props), SrcProxy, Opts),
+ Target = parse_rep_db(get_value(<<"target">>, Props), TgtProxy, Opts),
{Type, View} = case couch_replicator_filters:view_type(Props, Opts) of
{error, Error} ->
throw({bad_request, Error});
@@ -276,6 +276,25 @@ parse_rep_doc_without_id({Props}, UserCtx) ->
end.
+parse_proxy_settings(Props) when is_list(Props) ->
+ Proxy = get_value(<<"proxy">>, Props, <<>>),
+ SrcProxy = get_value(<<"source_proxy">>, Props, <<>>),
+ TgtProxy = get_value(<<"target_proxy">>, Props, <<>>),
+
+ case Proxy =/= <<>> of
+ true when SrcProxy =/= <<>> ->
+ Error = "`proxy` is mutually exclusive with `source_proxy`",
+ throw({bad_request, Error});
+ true when TgtProxy =/= <<>> ->
+ Error = "`proxy` is mutually exclusive with `target_proxy`",
+ throw({bad_request, Error});
+ true ->
+ {Proxy, Proxy};
+ false ->
+ {SrcProxy, TgtProxy}
+ end.
+
+
% Update a #rep{} record with a replication_id. Calculating the id might involve
% fetching a filter from the source db, and so it could fail intermetently.
% In case of a failure to fetch the filter this function will throw a
diff --git a/src/couch_replicator/test/eunit/couch_replicator_proxy_tests.erl b/src/couch_replicator/test/eunit/couch_replicator_proxy_tests.erl
index 4f545bcb5..da46b8a26 100644
--- a/src/couch_replicator/test/eunit/couch_replicator_proxy_tests.erl
+++ b/src/couch_replicator/test/eunit/couch_replicator_proxy_tests.erl
@@ -36,7 +36,10 @@ replicator_proxy_test_() ->
fun setup/0, fun teardown/1,
[
fun parse_rep_doc_without_proxy/1,
- fun parse_rep_doc_with_proxy/1
+ fun parse_rep_doc_with_proxy/1,
+ fun parse_rep_source_target_proxy/1,
+ fun mutually_exclusive_proxy_and_source_proxy/1,
+ fun mutually_exclusive_proxy_and_target_proxy/1
]
}
}
@@ -67,3 +70,47 @@ parse_rep_doc_with_proxy(_) ->
?assertEqual((Rep#rep.source)#httpdb.proxy_url, binary_to_list(ProxyURL)),
?assertEqual((Rep#rep.target)#httpdb.proxy_url, binary_to_list(ProxyURL))
end).
+
+
+parse_rep_source_target_proxy(_) ->
+ ?_test(begin
+ SrcProxyURL = <<"http://mysrcproxy.com">>,
+ TgtProxyURL = <<"http://mytgtproxy.com:9999">>,
+ ProxyDoc = {[
+ {<<"source">>, <<"http://unproxied.com">>},
+ {<<"target">>, <<"http://otherunproxied.com">>},
+ {<<"source_proxy">>, SrcProxyURL},
+ {<<"target_proxy">>, TgtProxyURL}
+ ]},
+ Rep = couch_replicator_docs:parse_rep_doc(ProxyDoc),
+ ?assertEqual((Rep#rep.source)#httpdb.proxy_url,
+ binary_to_list(SrcProxyURL)),
+ ?assertEqual((Rep#rep.target)#httpdb.proxy_url,
+ binary_to_list(TgtProxyURL))
+ end).
+
+
+mutually_exclusive_proxy_and_source_proxy(_) ->
+ ?_test(begin
+ ProxyDoc = {[
+ {<<"source">>, <<"http://unproxied.com">>},
+ {<<"target">>, <<"http://otherunproxied.com">>},
+ {<<"proxy">>, <<"oldstyleproxy.local">>},
+ {<<"source_proxy">>, <<"sourceproxy.local">>}
+ ]},
+ ?assertThrow({bad_rep_doc, _},
+ couch_replicator_docs:parse_rep_doc(ProxyDoc))
+ end).
+
+
+mutually_exclusive_proxy_and_target_proxy(_) ->
+ ?_test(begin
+ ProxyDoc = {[
+ {<<"source">>, <<"http://unproxied.com">>},
+ {<<"target">>, <<"http://otherunproxied.com">>},
+ {<<"proxy">>, <<"oldstyleproxy.local">>},
+ {<<"target_proxy">>, <<"targetproxy.local">>}
+ ]},
+ ?assertThrow({bad_rep_doc, _},
+ couch_replicator_docs:parse_rep_doc(ProxyDoc))
+ end).