diff options
author | Nick Vatamaniuc <vatamane@apache.org> | 2019-10-25 12:18:03 -0400 |
---|---|---|
committer | Nick Vatamaniuc <nickva@users.noreply.github.com> | 2019-10-28 12:51:21 -0400 |
commit | 053d494e698181ae3b0b0698055f5a24e7995172 (patch) | |
tree | 759b7b69bbd18e4c2cfe8cb5024760153e4dd843 | |
parent | b99d6e09052f04bb6655829d7ab51128ea88310f (diff) | |
download | couchdb-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.erl | 25 | ||||
-rw-r--r-- | src/couch_replicator/test/eunit/couch_replicator_proxy_tests.erl | 49 |
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). |