1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
%% Copyright (c) 2007-2024 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
%%
-module(rabbit_web_dispatch_sup).
-behaviour(supervisor).
-define(SUP, ?MODULE).
%% External exports
-export([start_link/0, ensure_listener/1, stop_listener/1]).
%% supervisor callbacks
-export([init/1]).
%% @spec start_link() -> ServerRet
%% @doc API for starting the supervisor.
start_link() ->
supervisor:start_link({local, ?SUP}, ?MODULE, []).
ensure_listener(Listener) ->
case proplists:get_value(port, Listener) of
undefined ->
{error, {no_port_given, Listener}};
_ ->
{Transport, TransportOpts, ProtoOpts} = preprocess_config(Listener),
ProtoOptsMap = maps:from_list(ProtoOpts),
StreamHandlers = stream_handlers_config(ProtoOpts),
rabbit_log:debug("Starting HTTP[S] listener with transport ~ts", [Transport]),
CowboyOptsMap =
maps:merge(#{env =>
#{rabbit_listener => Listener},
middlewares =>
[rabbit_cowboy_middleware, cowboy_router, cowboy_handler],
stream_handlers => StreamHandlers},
ProtoOptsMap),
Child = ranch:child_spec(rabbit_networking:ranch_ref(Listener),
Transport, TransportOpts,
cowboy_clear, CowboyOptsMap),
case supervisor:start_child(?SUP, Child) of
{ok, _} -> new;
{error, {already_started, _}} -> existing;
{error, {E, _}} -> check_error(Listener, E)
end
end.
stop_listener(Listener) ->
Name = rabbit_networking:ranch_ref(Listener),
ok = supervisor:terminate_child(?SUP, {ranch_embedded_sup, Name}),
ok = supervisor:delete_child(?SUP, {ranch_embedded_sup, Name}).
%% @spec init([[instance()]]) -> SupervisorTree
%% @doc supervisor callback.
init([]) ->
Registry = {rabbit_web_dispatch_registry,
{rabbit_web_dispatch_registry, start_link, []},
transient, 5000, worker, [rabbit_web_dispatch_registry]},
Log = {rabbit_mgmt_access_logger, {gen_event, start_link,
[{local, webmachine_log_event}]},
permanent, 5000, worker, dynamic},
{ok, {{one_for_one, 10, 10}, [Registry, Log]}}.
%%
%% Implementation
%%
preprocess_config(Options) ->
case proplists:get_value(ssl, Options) of
true -> _ = rabbit_networking:ensure_ssl(),
case proplists:get_value(ssl_opts, Options) of
undefined -> auto_ssl(Options);
_ -> fix_ssl(Options)
end;
_ -> {ranch_tcp, transport_config(Options), protocol_config(Options)}
end.
auto_ssl(Options) ->
{ok, ServerOpts} = application:get_env(rabbit, ssl_options),
Remove = [verify, fail_if_no_peer_cert],
SSLOpts = [{K, V} || {K, V} <- ServerOpts,
not lists:member(K, Remove)],
fix_ssl([{ssl_opts, SSLOpts} | Options]).
fix_ssl(Options) ->
SSLOpts = proplists:get_value(ssl_opts, Options),
{ranch_ssl,
transport_config(Options ++ rabbit_networking:fix_ssl_options(SSLOpts)),
protocol_config(Options)}.
transport_config(Options0) ->
Options = proplists:delete(protocol,
proplists:delete(ssl,
proplists:delete(ssl_opts,
proplists:delete(cowboy_opts,
Options0)))),
case proplists:get_value(ip, Options) of
undefined ->
Options;
IP when is_tuple(IP) ->
Options;
IP when is_list(IP) ->
{ok, ParsedIP} = inet_parse:address(IP),
[{ip, ParsedIP}|proplists:delete(ip, Options)]
end.
protocol_config(Options) ->
proplists:get_value(cowboy_opts, Options, []).
stream_handlers_config(Options) ->
case lists:keyfind(compress, 1, Options) of
{compress, false} -> [rabbit_cowboy_stream_h, cowboy_stream_h];
%% Compress by default. Since 2.0 the compress option in cowboys
%% has been replaced by the cowboy_compress_h handler
%% Compress is not applied if data < 300 bytes
_ -> [rabbit_cowboy_stream_h, cowboy_compress_h, cowboy_stream_h]
end.
check_error(Listener, Error) ->
Ignore = proplists:get_value(ignore_in_use, Listener, false),
case {Error, Ignore} of
{eaddrinuse, true} -> ignore;
_ -> exit({could_not_start_listener, Listener, Error})
end.
|