Skip to content
This repository was archived by the owner on Nov 17, 2020. It is now read-only.

Commit 6c1ad93

Browse files
Merge branch 'rabbitmq-management-157' into stable
2 parents 90b0157 + 68efd14 commit 6c1ad93

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+375
-18
lines changed

src/rabbit_mgmt_cors.erl

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
%% The contents of this file are subject to the Mozilla Public License
2+
%% Version 1.1 (the "License"); you may not use this file except in
3+
%% compliance with the License. You may obtain a copy of the License at
4+
%% http://www.mozilla.org/MPL/
5+
%%
6+
%% Software distributed under the License is distributed on an "AS IS"
7+
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
8+
%% License for the specific language governing rights and limitations
9+
%% under the License.
10+
%%
11+
%% The Original Code is RabbitMQ Management Plugin.
12+
%%
13+
%% The Initial Developer of the Original Code is GoPivotal, Inc.
14+
%% Copyright (c) 2007-2016 Pivotal Software, Inc. All rights reserved.
15+
%%
16+
17+
%% Useful documentation about CORS:
18+
%% * https://tools.ietf.org/html/rfc6454
19+
%% * https://www.w3.org/TR/cors/
20+
%% * https://staticapps.org/articles/cross-domain-requests-with-cors/
21+
-module(rabbit_mgmt_cors).
22+
23+
-export([set_headers/2]).
24+
25+
%% We don't set access-control-max-age because we currently have
26+
%% no way to know which headers apply to the whole resource. We
27+
%% only know for the next request.
28+
set_headers(ReqData, Module) ->
29+
ReqData1 = case wrq:get_resp_header("vary", ReqData) of
30+
undefined -> wrq:set_resp_header("vary", "origin", ReqData);
31+
VaryValue -> wrq:set_resp_header("vary", VaryValue ++ ", origin", ReqData)
32+
end,
33+
case match_origin(ReqData1) of
34+
false ->
35+
ReqData1;
36+
Origin ->
37+
ReqData2 = case wrq:method(ReqData1) of
38+
'OPTIONS' -> handle_options(ReqData1, Module);
39+
_ -> ReqData1
40+
end,
41+
wrq:set_resp_headers([
42+
{"access-control-allow-origin", Origin},
43+
{"access-control-allow-credentials", "true"}
44+
], ReqData2)
45+
end.
46+
47+
%% Set max-age from configuration (default: 30 minutes).
48+
%% Set allow-methods from what is defined in Module:allowed_methods/2.
49+
%% Set allow-headers to the same as the request (accept all headers).
50+
handle_options(ReqData, Module) ->
51+
MaxAge = application:get_env(rabbitmq_management, cors_max_age, 1800),
52+
{Methods, _, _} = Module:allowed_methods(undefined, undefined),
53+
AllowMethods = string:join([atom_to_list(M) || M <- Methods], ", "),
54+
ReqHeaders = wrq:get_req_header("access-control-request-headers", ReqData),
55+
MaxAgeHd = case MaxAge of
56+
undefined -> [];
57+
_ -> {"access-control-max-age", integer_to_list(MaxAge)}
58+
end,
59+
MaybeAllowHeaders = case ReqHeaders of
60+
undefined -> [];
61+
_ -> [{"access-control-allow-headers", ReqHeaders}]
62+
end,
63+
wrq:set_resp_headers([MaxAgeHd,
64+
{"access-control-allow-methods", AllowMethods}
65+
|MaybeAllowHeaders], ReqData).
66+
67+
%% If the origin header is missing or "null", we disable CORS.
68+
%% Otherwise, we only enable it if the origin is found in the
69+
%% cors_allow_origins configuration variable, or if "*" is (it
70+
%% allows all origins).
71+
match_origin(ReqData) ->
72+
case wrq:get_req_header("origin", ReqData) of
73+
undefined -> false;
74+
"null" -> false;
75+
Origin ->
76+
AllowedOrigins = application:get_env(rabbitmq_management,
77+
cors_allow_origins, []),
78+
case lists:member(Origin, AllowedOrigins) of
79+
true ->
80+
Origin;
81+
false ->
82+
%% Maybe the configuration explicitly allows "*".
83+
case lists:member("*", AllowedOrigins) of
84+
true -> Origin;
85+
false -> false
86+
end
87+
end
88+
end.

src/rabbit_mgmt_wm_aliveness_test.erl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
-module(rabbit_mgmt_wm_aliveness_test).
1818

1919
-export([init/1, to_json/2, content_types_provided/2, is_authorized/2]).
20+
-export([finish_request/2, allowed_methods/2]).
2021
-export([encodings_provided/2]).
2122
-export([resource_exists/2]).
2223

@@ -30,6 +31,12 @@
3031

3132
init(_Config) -> {ok, #context{}}.
3233

34+
finish_request(ReqData, Context) ->
35+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
36+
37+
allowed_methods(ReqData, Context) ->
38+
{['HEAD', 'GET', 'OPTIONS'], ReqData, Context}.
39+
3340
content_types_provided(ReqData, Context) ->
3441
{[{"application/json", to_json}], ReqData, Context}.
3542

src/rabbit_mgmt_wm_binding.erl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
content_types_provided/2, content_types_accepted/2,
2121
is_authorized/2, allowed_methods/2, delete_resource/2,
2222
args_hash/1]).
23+
-export([finish_request/2]).
2324
-export([encodings_provided/2]).
2425

2526
-include("rabbit_mgmt.hrl").
@@ -29,6 +30,9 @@
2930
%%--------------------------------------------------------------------
3031
init(_Config) -> {ok, #context{}}.
3132

33+
finish_request(ReqData, Context) ->
34+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
35+
3236
content_types_provided(ReqData, Context) ->
3337
{[{"application/json", to_json}], ReqData, Context}.
3438

@@ -40,7 +44,7 @@ content_types_accepted(ReqData, Context) ->
4044
{[{"application/json", accept_content}], ReqData, Context}.
4145

4246
allowed_methods(ReqData, Context) ->
43-
{['HEAD', 'GET', 'DELETE'], ReqData, Context}.
47+
{['HEAD', 'GET', 'DELETE', 'OPTIONS'], ReqData, Context}.
4448

4549
resource_exists(ReqData, Context) ->
4650
Binding = binding(ReqData),

src/rabbit_mgmt_wm_bindings.erl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
-export([allowed_methods/2, post_is_create/2, create_path/2]).
2121
-export([content_types_accepted/2, accept_content/2, resource_exists/2]).
2222
-export([basic/1, augmented/2]).
23+
-export([finish_request/2]).
2324
-export([encodings_provided/2]).
2425

2526
-include("rabbit_mgmt.hrl").
@@ -31,6 +32,9 @@
3132
init([Mode]) ->
3233
{ok, {Mode, #context{}}}.
3334

35+
finish_request(ReqData, Context) ->
36+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
37+
3438
content_types_provided(ReqData, Context) ->
3539
{[{"application/json", to_json}], ReqData, Context}.
3640

@@ -49,8 +53,8 @@ content_types_accepted(ReqData, Context) ->
4953

5054
allowed_methods(ReqData, {Mode, Context}) ->
5155
{case Mode of
52-
source_destination -> ['HEAD', 'GET', 'POST'];
53-
_ -> ['HEAD', 'GET']
56+
source_destination -> ['HEAD', 'GET', 'POST', 'OPTIONS'];
57+
_ -> ['HEAD', 'GET', 'OPTIONS']
5458
end, ReqData, {Mode, Context}}.
5559

5660
post_is_create(ReqData, Context) ->

src/rabbit_mgmt_wm_channel.erl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
-module(rabbit_mgmt_wm_channel).
1818

1919
-export([init/1, to_json/2, content_types_provided/2, is_authorized/2]).
20+
-export([finish_request/2, allowed_methods/2]).
2021
-export([encodings_provided/2]).
2122
-export([resource_exists/2]).
2223

@@ -28,6 +29,12 @@
2829

2930
init(_Config) -> {ok, #context{}}.
3031

32+
finish_request(ReqData, Context) ->
33+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
34+
35+
allowed_methods(ReqData, Context) ->
36+
{['HEAD', 'GET', 'OPTIONS'], ReqData, Context}.
37+
3138
content_types_provided(ReqData, Context) ->
3239
{[{"application/json", to_json}], ReqData, Context}.
3340

src/rabbit_mgmt_wm_channels.erl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
-export([init/1, to_json/2, content_types_provided/2, is_authorized/2,
2020
augmented/2]).
21+
-export([finish_request/2, allowed_methods/2]).
2122
-export([encodings_provided/2]).
2223

2324
-import(rabbit_misc, [pget/2]).
@@ -30,6 +31,12 @@
3031

3132
init(_Config) -> {ok, #context{}}.
3233

34+
finish_request(ReqData, Context) ->
35+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
36+
37+
allowed_methods(ReqData, Context) ->
38+
{['HEAD', 'GET', 'OPTIONS'], ReqData, Context}.
39+
3340
content_types_provided(ReqData, Context) ->
3441
{[{"application/json", to_json}], ReqData, Context}.
3542

src/rabbit_mgmt_wm_channels_vhost.erl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
-export([init/1, to_json/2, content_types_provided/2, is_authorized/2,
2222
augmented/2, resource_exists/2]).
23+
-export([finish_request/2, allowed_methods/2]).
2324
-export([encodings_provided/2]).
2425

2526
-import(rabbit_misc, [pget/2]).
@@ -32,6 +33,12 @@
3233

3334
init(_Config) -> {ok, #context{}}.
3435

36+
finish_request(ReqData, Context) ->
37+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
38+
39+
allowed_methods(ReqData, Context) ->
40+
{['HEAD', 'GET', 'OPTIONS'], ReqData, Context}.
41+
3542
content_types_provided(ReqData, Context) ->
3643
{[{"application/json", to_json}], ReqData, Context}.
3744

src/rabbit_mgmt_wm_cluster_name.erl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
-export([init/1, resource_exists/2, to_json/2,
2020
content_types_provided/2, content_types_accepted/2,
2121
is_authorized/2, allowed_methods/2, accept_content/2]).
22+
-export([finish_request/2]).
2223
-export([encodings_provided/2]).
2324

2425
-include("rabbit_mgmt.hrl").
@@ -28,6 +29,9 @@
2829
%%--------------------------------------------------------------------
2930
init(_Config) -> {ok, #context{}}.
3031

32+
finish_request(ReqData, Context) ->
33+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
34+
3135
content_types_provided(ReqData, Context) ->
3236
{[{"application/json", to_json}], ReqData, Context}.
3337

@@ -39,7 +43,7 @@ content_types_accepted(ReqData, Context) ->
3943
{[{"application/json", accept_content}], ReqData, Context}.
4044

4145
allowed_methods(ReqData, Context) ->
42-
{['HEAD', 'GET', 'PUT'], ReqData, Context}.
46+
{['HEAD', 'GET', 'PUT', 'OPTIONS'], ReqData, Context}.
4347

4448
resource_exists(ReqData, Context) ->
4549
{true, ReqData, Context}.

src/rabbit_mgmt_wm_connection.erl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
-export([init/1, resource_exists/2, to_json/2, content_types_provided/2,
2020
is_authorized/2, allowed_methods/2, delete_resource/2, conn/1]).
21+
-export([finish_request/2]).
2122
-export([encodings_provided/2]).
2223

2324
-include("rabbit_mgmt.hrl").
@@ -28,6 +29,9 @@
2829

2930
init(_Config) -> {ok, #context{}}.
3031

32+
finish_request(ReqData, Context) ->
33+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
34+
3135
content_types_provided(ReqData, Context) ->
3236
{[{"application/json", to_json}], ReqData, Context}.
3337

@@ -36,7 +40,7 @@ encodings_provided(ReqData, Context) ->
3640
{"gzip", fun(X) -> zlib:gzip(X) end}], ReqData, Context}.
3741

3842
allowed_methods(ReqData, Context) ->
39-
{['HEAD', 'GET', 'DELETE'], ReqData, Context}.
43+
{['HEAD', 'GET', 'DELETE', 'OPTIONS'], ReqData, Context}.
4044

4145
resource_exists(ReqData, Context) ->
4246
case conn(ReqData) of

src/rabbit_mgmt_wm_connection_channels.erl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
-module(rabbit_mgmt_wm_connection_channels).
1818

1919
-export([init/1, to_json/2, content_types_provided/2, is_authorized/2]).
20+
-export([finish_request/2, allowed_methods/2]).
2021
-export([encodings_provided/2]).
2122
-export([resource_exists/2]).
2223

@@ -28,6 +29,12 @@
2829

2930
init(_Config) -> {ok, #context{}}.
3031

32+
finish_request(ReqData, Context) ->
33+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
34+
35+
allowed_methods(ReqData, Context) ->
36+
{['HEAD', 'GET', 'OPTIONS'], ReqData, Context}.
37+
3138
content_types_provided(ReqData, Context) ->
3239
{[{"application/json", to_json}], ReqData, Context}.
3340

src/rabbit_mgmt_wm_connections.erl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
-export([init/1, to_json/2, content_types_provided/2, is_authorized/2,
2020
augmented/2]).
21+
-export([finish_request/2, allowed_methods/2]).
2122
-export([encodings_provided/2]).
2223

2324
-import(rabbit_misc, [pget/2]).
@@ -30,6 +31,12 @@
3031

3132
init(_Config) -> {ok, #context{}}.
3233

34+
finish_request(ReqData, Context) ->
35+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
36+
37+
allowed_methods(ReqData, Context) ->
38+
{['HEAD', 'GET', 'OPTIONS'], ReqData, Context}.
39+
3340
content_types_provided(ReqData, Context) ->
3441
{[{"application/json", to_json}], ReqData, Context}.
3542

src/rabbit_mgmt_wm_connections_vhost.erl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
-export([init/1, to_json/2, content_types_provided/2, is_authorized/2,
2222
augmented/2, resource_exists/2]).
23+
-export([finish_request/2, allowed_methods/2]).
2324
-export([encodings_provided/2]).
2425

2526
-import(rabbit_misc, [pget/2]).
@@ -32,6 +33,12 @@
3233

3334
init(_Config) -> {ok, #context{}}.
3435

36+
finish_request(ReqData, Context) ->
37+
{ok, rabbit_mgmt_cors:set_headers(ReqData, ?MODULE), Context}.
38+
39+
allowed_methods(ReqData, Context) ->
40+
{['HEAD', 'GET', 'OPTIONS'], ReqData, Context}.
41+
3542
content_types_provided(ReqData, Context) ->
3643
{[{"application/json", to_json}], ReqData, Context}.
3744

src/rabbit_mgmt_wm_consumers.erl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
-export([init/1, to_json/2, content_types_provided/2, resource_exists/2,
1919
is_authorized/2]).
20+
-export([finish_request/2, allowed_methods/2]).
2021
-export([encodings_provided/2]).
2122

2223
-import(rabbit_misc, [pget/2]).
@@ -29,6 +30,12 @@
2930

3031
init(_Config) -> {ok, #context{}}.
3132

33+
finish_request(ReqData, Context) ->
34+
{ok, rabbit_mgmt_cors:set_headers(ReqData, Context), Context}.
35+
36+
allowed_methods(ReqData, Context) ->
37+
{['HEAD', 'GET', 'OPTIONS'], ReqData, Context}.
38+
3239
content_types_provided(ReqData, Context) ->
3340
{[{"application/json", to_json}], ReqData, Context}.
3441

src/rabbit_mgmt_wm_definitions.erl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
-export([init/1, to_json/2, content_types_provided/2, is_authorized/2]).
2020
-export([content_types_accepted/2, allowed_methods/2, accept_json/2]).
2121
-export([post_is_create/2, create_path/2, accept_multipart/2]).
22+
-export([finish_request/2]).
2223
-export([encodings_provided/2]).
2324

2425
-export([apply_defs/3]).
@@ -32,6 +33,9 @@
3233
%%--------------------------------------------------------------------
3334
init(_Config) -> {ok, #context{}}.
3435

36+
finish_request(ReqData, Context) ->
37+
{ok, rabbit_mgmt_cors:set_headers(ReqData, Context), Context}.
38+
3539
content_types_provided(ReqData, Context) ->
3640
{[{"application/json", to_json}], ReqData, Context}.
3741

@@ -44,7 +48,7 @@ content_types_accepted(ReqData, Context) ->
4448
{"multipart/form-data", accept_multipart}], ReqData, Context}.
4549

4650
allowed_methods(ReqData, Context) ->
47-
{['HEAD', 'GET', 'POST'], ReqData, Context}.
51+
{['HEAD', 'GET', 'POST', 'OPTIONS'], ReqData, Context}.
4852

4953
post_is_create(ReqData, Context) ->
5054
{true, ReqData, Context}.

0 commit comments

Comments
 (0)