diff options
Diffstat (limited to 'src/couch_replicator/src/couch_replicator_ids.erl')
-rw-r--r-- | src/couch_replicator/src/couch_replicator_ids.erl | 297 |
1 files changed, 150 insertions, 147 deletions
diff --git a/src/couch_replicator/src/couch_replicator_ids.erl b/src/couch_replicator/src/couch_replicator_ids.erl index 316e6a28a..6543cf069 100644 --- a/src/couch_replicator/src/couch_replicator_ids.erl +++ b/src/couch_replicator/src/couch_replicator_ids.erl @@ -34,7 +34,6 @@ replication_id(#rep{options = Options} = Rep) -> BaseId = replication_id(Rep, ?REP_ID_VERSION), {BaseId, maybe_append_options([continuous, create_target], Options)}. - % Versioned clauses for generating replication IDs. % If a change is made to how replications are identified, % please add a new clause and increase ?REP_ID_VERSION. @@ -44,37 +43,34 @@ replication_id(#rep{} = Rep, 4) -> SrcInfo = get_v4_endpoint(Rep#rep.source), TgtInfo = get_v4_endpoint(Rep#rep.target), maybe_append_filters([UUID, SrcInfo, TgtInfo], Rep); - replication_id(#rep{} = Rep, 3) -> UUID = couch_server:get_uuid(), Src = get_rep_endpoint(Rep#rep.source), Tgt = get_rep_endpoint(Rep#rep.target), maybe_append_filters([UUID, Src, Tgt], Rep); - replication_id(#rep{} = Rep, 2) -> {ok, HostName} = inet:gethostname(), - Port = case (catch mochiweb_socket_server:get(couch_httpd, port)) of - P when is_number(P) -> - P; - _ -> - % On restart we might be called before the couch_httpd process is - % started. - % TODO: we might be under an SSL socket server only, or both under - % SSL and a non-SSL socket. - % ... mochiweb_socket_server:get(https, port) - config:get_integer("httpd", "port", 5984) - end, + Port = + case (catch mochiweb_socket_server:get(couch_httpd, port)) of + P when is_number(P) -> + P; + _ -> + % On restart we might be called before the couch_httpd process is + % started. + % TODO: we might be under an SSL socket server only, or both under + % SSL and a non-SSL socket. + % ... mochiweb_socket_server:get(https, port) + config:get_integer("httpd", "port", 5984) + end, Src = get_rep_endpoint(Rep#rep.source), Tgt = get_rep_endpoint(Rep#rep.target), maybe_append_filters([HostName, Port, Src, Tgt], Rep); - replication_id(#rep{} = Rep, 1) -> {ok, HostName} = inet:gethostname(), Src = get_rep_endpoint(Rep#rep.source), Tgt = get_rep_endpoint(Rep#rep.target), maybe_append_filters([HostName, Src, Tgt], Rep). - -spec convert([_] | binary() | {string(), string()}) -> {string(), string()}. convert(Id) when is_list(Id) -> convert(?l2b(Id)); @@ -87,59 +83,62 @@ convert(Id0) when is_binary(Id0) -> convert({BaseId, Ext} = Id) when is_list(BaseId), is_list(Ext) -> Id. - % Private functions -maybe_append_filters(Base, - #rep{source = Source, options = Options}) -> - Base2 = Base ++ - case couch_replicator_filters:parse(Options) of - {ok, nil} -> - []; - {ok, {view, Filter, QueryParams}} -> - [Filter, QueryParams]; - {ok, {user, {Doc, Filter}, QueryParams}} -> - case couch_replicator_filters:fetch(Doc, Filter, Source) of - {ok, Code} -> - [Code, QueryParams]; - {error, Error} -> - throw({filter_fetch_error, Error}) - end; - {ok, {docids, DocIds}} -> - [DocIds]; - {ok, {mango, Selector}} -> - [Selector]; - {error, FilterParseError} -> - throw({error, FilterParseError}) - end, +maybe_append_filters( + Base, + #rep{source = Source, options = Options} +) -> + Base2 = + Base ++ + case couch_replicator_filters:parse(Options) of + {ok, nil} -> + []; + {ok, {view, Filter, QueryParams}} -> + [Filter, QueryParams]; + {ok, {user, {Doc, Filter}, QueryParams}} -> + case couch_replicator_filters:fetch(Doc, Filter, Source) of + {ok, Code} -> + [Code, QueryParams]; + {error, Error} -> + throw({filter_fetch_error, Error}) + end; + {ok, {docids, DocIds}} -> + [DocIds]; + {ok, {mango, Selector}} -> + [Selector]; + {error, FilterParseError} -> + throw({error, FilterParseError}) + end, couch_util:to_hex(couch_hash:md5_hash(term_to_binary(Base2))). - maybe_append_options(Options, RepOptions) -> - lists:foldl(fun(Option, Acc) -> - Acc ++ - case couch_util:get_value(Option, RepOptions, false) of - true -> - "+" ++ atom_to_list(Option); - false -> - "" - end - end, [], Options). - + lists:foldl( + fun(Option, Acc) -> + Acc ++ + case couch_util:get_value(Option, RepOptions, false) of + true -> + "+" ++ atom_to_list(Option); + false -> + "" + end + end, + [], + Options + ). -get_rep_endpoint(#httpdb{url=Url, headers=Headers}) -> +get_rep_endpoint(#httpdb{url = Url, headers = Headers}) -> DefaultHeaders = (#httpdb{})#httpdb.headers, {remote, Url, Headers -- DefaultHeaders}. - get_v4_endpoint(#httpdb{} = HttpDb) -> {remote, Url, Headers} = get_rep_endpoint(HttpDb), {User, _} = couch_replicator_utils:get_basic_auth_creds(HttpDb), {Host, NonDefaultPort, Path} = get_v4_url_info(Url), - OAuth = undefined, % Keep this to ensure checkpoints don't change + % Keep this to ensure checkpoints don't change + OAuth = undefined, {remote, User, Host, NonDefaultPort, Path, Headers, OAuth}. - get_v4_url_info(Url) when is_binary(Url) -> get_v4_url_info(binary_to_list(Url)); get_v4_url_info(Url) -> @@ -158,7 +157,6 @@ get_v4_url_info(Url) -> {Host, NonDefaultPort, Path} end. - get_non_default_port(https, 443) -> default; get_non_default_port(http, 80) -> @@ -168,112 +166,117 @@ get_non_default_port(http, 5984) -> get_non_default_port(_Schema, Port) -> Port. - -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). - replication_id_convert_test_() -> - [?_assertEqual(Expected, convert(Id)) || {Expected, Id} <- [ - {{"abc", ""}, "abc"}, - {{"abc", ""}, <<"abc">>}, - {{"abc", "+x+y"}, <<"abc+x+y">>}, - {{"abc", "+x+y"}, {"abc", "+x+y"}}, - {{"abc", "+x+y"}, <<"abc x y">>} - ]]. + [ + ?_assertEqual(Expected, convert(Id)) + || {Expected, Id} <- [ + {{"abc", ""}, "abc"}, + {{"abc", ""}, <<"abc">>}, + {{"abc", "+x+y"}, <<"abc+x+y">>}, + {{"abc", "+x+y"}, {"abc", "+x+y"}}, + {{"abc", "+x+y"}, <<"abc x y">>} + ] + ]. http_v4_endpoint_test_() -> - [?_assertMatch({remote, User, Host, Port, Path, HeadersNoAuth, undefined}, - begin - HttpDb = #httpdb{url = Url, headers = Headers, auth_props = Auth}, - HttpDb1 = couch_replicator_utils:normalize_basic_auth(HttpDb), - get_v4_endpoint(HttpDb1) - end) || - {{User, Host, Port, Path, HeadersNoAuth}, {Url, Headers, Auth}} <- [ - { - {undefined, "host", default, "/", []}, - {"http://host", [], []} - }, - { - {undefined, "host", default, "/", []}, - {"https://host", [], []} - }, - { - {undefined, "host", default, "/", []}, - {"http://host:5984", [], []} - }, - { - {undefined, "host", 1, "/", []}, - {"http://host:1", [], []} - }, - { - {undefined, "host", 2, "/", []}, - {"https://host:2", [], []} - }, - { - {undefined, "host", default, "/", [{"h","v"}]}, - {"http://host", [{"h","v"}], []} - }, - { - {undefined, "host", default, "/a/b", []}, - {"http://host/a/b", [], []} - }, - { - {"user", "host", default, "/", []}, - {"http://user:pass@host", [], []} - }, - { - {"user", "host", 3, "/", []}, - {"http://user:pass@host:3", [], []} - }, - { - {"user", "host", default, "/", []}, - {"http://user:newpass@host", [], []} - }, - { - {"user", "host", default, "/", []}, - {"http://host", [basic_auth("user","pass")], []} - }, - { - {"user", "host", default, "/", []}, - {"http://host", [basic_auth("user","newpass")], []} - }, - { - {"user3", "host", default, "/", []}, - {"http://user1:pass1@host", [basic_auth("user2","pass2")], - auth_props("user3", "pass3")} - }, - { - {"user2", "host", default, "/", [{"h", "v"}]}, - {"http://host", [{"h", "v"}, basic_auth("user","pass")], - auth_props("user2", "pass2")} - }, - { - {"user", "host", default, "/", [{"h", "v"}]}, - {"http://host", [{"h", "v"}], auth_props("user", "pass")} - }, - { - {undefined, "random_junk", undefined, undefined}, - {"random_junk", [], []} - }, - { - {undefined, "host", default, "/", []}, - {"http://host", [{"Authorization", "Basic bad"}], []} - } + [ + ?_assertMatch( + {remote, User, Host, Port, Path, HeadersNoAuth, undefined}, + begin + HttpDb = #httpdb{url = Url, headers = Headers, auth_props = Auth}, + HttpDb1 = couch_replicator_utils:normalize_basic_auth(HttpDb), + get_v4_endpoint(HttpDb1) + end + ) + || {{User, Host, Port, Path, HeadersNoAuth}, {Url, Headers, Auth}} <- [ + { + {undefined, "host", default, "/", []}, + {"http://host", [], []} + }, + { + {undefined, "host", default, "/", []}, + {"https://host", [], []} + }, + { + {undefined, "host", default, "/", []}, + {"http://host:5984", [], []} + }, + { + {undefined, "host", 1, "/", []}, + {"http://host:1", [], []} + }, + { + {undefined, "host", 2, "/", []}, + {"https://host:2", [], []} + }, + { + {undefined, "host", default, "/", [{"h", "v"}]}, + {"http://host", [{"h", "v"}], []} + }, + { + {undefined, "host", default, "/a/b", []}, + {"http://host/a/b", [], []} + }, + { + {"user", "host", default, "/", []}, + {"http://user:pass@host", [], []} + }, + { + {"user", "host", 3, "/", []}, + {"http://user:pass@host:3", [], []} + }, + { + {"user", "host", default, "/", []}, + {"http://user:newpass@host", [], []} + }, + { + {"user", "host", default, "/", []}, + {"http://host", [basic_auth("user", "pass")], []} + }, + { + {"user", "host", default, "/", []}, + {"http://host", [basic_auth("user", "newpass")], []} + }, + { + {"user3", "host", default, "/", []}, + {"http://user1:pass1@host", [basic_auth("user2", "pass2")], + auth_props("user3", "pass3")} + }, + { + {"user2", "host", default, "/", [{"h", "v"}]}, + {"http://host", [{"h", "v"}, basic_auth("user", "pass")], + auth_props("user2", "pass2")} + }, + { + {"user", "host", default, "/", [{"h", "v"}]}, + {"http://host", [{"h", "v"}], auth_props("user", "pass")} + }, + { + {undefined, "random_junk", undefined, undefined}, + {"random_junk", [], []} + }, + { + {undefined, "host", default, "/", []}, + {"http://host", [{"Authorization", "Basic bad"}], []} + } ] ]. - basic_auth(User, Pass) -> B64Auth = base64:encode_to_string(User ++ ":" ++ Pass), {"Authorization", "Basic " ++ B64Auth}. - auth_props(User, Pass) when is_list(User), is_list(Pass) -> - [{<<"basic">>, {[ - {<<"username">>, list_to_binary(User)}, - {<<"password">>, list_to_binary(Pass)} - ]}}]. + [ + {<<"basic">>, + {[ + {<<"username">>, list_to_binary(User)}, + {<<"password">>, list_to_binary(Pass)} + ]}} + ]. -endif. |