anchor.diff:              throw(not_found)
       end;
   handle_scheduler_req(#httpd{method='GET', path_parts=[_,<<"docs">>]}=Req) ->
  -    VArgs0 = couch_mrview_http:parse_params(Req, undefined),
  -    StatesQs = chttpd:qs_value(Req, "states"),
  -    States = couch_replicator_httpd_util:parse_replication_state_filter(StatesQs),
  -    VArgs1 = VArgs0#mrargs{
  -        view_type = map,
  -        include_docs = true,
  -        reduce = false,
  -        extra = [{filter_states, States}]
  -    },
  -    VArgs2 = couch_mrview_util:validate_args(VArgs1),
  -    Opts = [{user_ctx, Req#httpd.user_ctx}],
  -    Db = ?REPDB,
  -    Max = chttpd:chunked_response_buffer_size(),
  -    Acc = couch_replicator_httpd_util:docs_acc_new(Req, Db, Max),
  -    Cb = fun couch_replicator_httpd_util:docs_cb/2,
  -    {ok, RAcc} = couch_replicator_fabric:docs(Db, Opts, VArgs2, Cb, Acc),
  -    {ok,  couch_replicator_httpd_util:docs_acc_response(RAcc)};
  -handle_scheduler_req(#httpd{method='GET', path_parts=[_,<<"docs">>,DocId]}=Req) ->
  -    UserCtx = Req#httpd.user_ctx,
  -    case couch_replicator:doc(?REPDB, DocId, UserCtx#user_ctx.roles) of
  -        {ok, DocInfo} ->
  -            send_json(Req, couch_replicator_httpd_util:update_db_name(DocInfo));
  -        {error, not_found} ->
  -            throw(not_found)
  +    handle_scheduler_docs(?REPDB, Req);
  +handle_scheduler_req(#httpd{method='GET', path_parts=[_,<<"docs">>,Db]}=Req)
  +        when ?ISREPDB(Db) ->
  +    handle_scheduler_docs(Db, Req);
  +handle_scheduler_req(#httpd{method='GET', path_parts=[_,<<"docs">>,Db,DocId]}
  +        = Req)  when ?ISREPDB(Db) ->
  +    handle_scheduler_doc(Db, DocId, Req);
  +% Allow users to pass in unencoded _replicator database names (/ are not
  +% escaped). This is possible here because _replicator is not a valid document
  +% ID so can disambiguate between an element of a db path and the document ID.
  +handle_scheduler_req(#httpd{method='GET', path_parts=[_,<<"docs">>|Unquoted]}
  +        = Req) ->
  +    case parse_unquoted_docs_path(Unquoted) of
  +        {db_only, Db} ->
  +            handle_scheduler_docs(Db, Req);
  +        {db_and_doc, Db, DocId} ->
  +            handle_scheduler_doc(Db, DocId, Req);
  +        {error, invalid} ->
  +            throw(bad_request)
       end;
   handle_scheduler_req(Req) ->
       send_method_not_allowed(Req, "GET,HEAD").
  
positive.code: 
  -define(DEFAULT_TASK_LIMIT, 100).
  -define(REPDB, <<"_replicator">>).
  
  
  handle_scheduler_req(#httpd{method='GET', path_parts=[_,<<"jobs">>]}=Req) ->
  
negative.code: 
  handle_req(Req) ->
      send_method_not_allowed(Req, "POST").
  
  
  handle_scheduler_docs(Db, Req) when is_binary(Db) ->
      VArgs0 = couch_mrview_http:parse_params(Req, undefined),
      StatesQs = chttpd:qs_value(Req, "states"),
      States = couch_replicator_httpd_util:parse_replication_state_filter(StatesQs),
      VArgs1 = VArgs0#mrargs{
          view_type = map,
          include_docs = true,
          reduce = false,
          extra = [{filter_states, States}]
      },
      VArgs2 = couch_mrview_util:validate_args(VArgs1),
      Opts = [{user_ctx, Req#httpd.user_ctx}],
      Max = chttpd:chunked_response_buffer_size(),
      Acc = couch_replicator_httpd_util:docs_acc_new(Req, Db, Max),
      Cb = fun couch_replicator_httpd_util:docs_cb/2,
      {ok, RAcc} = couch_replicator_fabric:docs(Db, Opts, VArgs2, Cb, Acc),
      {ok,  couch_replicator_httpd_util:docs_acc_response(RAcc)}.
  
  
  handle_scheduler_doc(Db, DocId, Req) when is_binary(Db), is_binary(DocId) ->
      UserCtx = Req#httpd.user_ctx,
      case couch_replicator:doc(Db, DocId, UserCtx#user_ctx.roles) of
          {ok, DocInfo} ->
              send_json(Req, couch_replicator_httpd_util:update_db_name(DocInfo));
          {error, not_found} ->
              throw(not_found)
      end.
  
  
  parse_unquoted_docs_path([_, _ | _] = Unquoted) ->
      DbAndAfter = lists:dropwhile(fun(E) -> E =/= ?REPDB end, Unquoted),
      BeforeRDb = lists:takewhile(fun(E) -> E =/= ?REPDB end, Unquoted),
      case DbAndAfter of
          [] ->
              {error, invalid};
          [?REPDB] ->
              {db_only, filename:join(BeforeRDb ++ [?REPDB])};
          [?REPDB, DocId] ->
              {db_and_doc, filename:join(BeforeRDb ++ [?REPDB]), DocId}
      end.
  
  
  -ifdef(TEST).
  
  -include_lib("eunit/include/eunit.hrl").
  
  unquoted_scheduler_docs_path_test_() ->
      [?_assertEqual(Res, parse_unquoted_docs_path(Path)) || {Res, Path} <- [
          {{error, invalid}, [<<"a">>,<< "b">>]},
          {{db_only, <<"a/_replicator">>}, [<<"a">>, ?REPDB]},
          {{db_only, <<"a/b/_replicator">>}, [<<"a">>, <<"b">>, ?REPDB]},
          {{db_and_doc, <<"_replicator">>, <<"x">>}, [?REPDB, <<"x">>]},
          {{db_and_doc, <<"a/_replicator">>, <<"x">>}, [<<"a">>, ?REPDB, <<"x">>]},
          {{error, invalid}, [<<"a/_replicator">>,<<"x">>]}
      ]].
  
  -endif.
  