diff --git a/deps/rabbitmq_management/priv/www/css/main.css b/deps/rabbitmq_management/priv/www/css/main.css
index cf0f76a6b8..36da06812c 100644
--- a/deps/rabbitmq_management/priv/www/css/main.css
+++ b/deps/rabbitmq_management/priv/www/css/main.css
@@ -95,6 +95,7 @@ form.inline-form-right { float: right; }
input, select { padding: 0.2em; }
input[type=text] { font: 1.1em Lucidatypewriter, Courier, monospace; }
input[type=text].wide { width: 300px; }
+textarea { width: 600px; height: 200px; }
.mand { color: #f88; padding: 0 5px;}
table.form { margin-bottom: 0.5em; }
diff --git a/deps/rabbitmq_management/priv/www/js/main.js b/deps/rabbitmq_management/priv/www/js/main.js
index 7d107ca0fc..359515f0a8 100644
--- a/deps/rabbitmq_management/priv/www/js/main.js
+++ b/deps/rabbitmq_management/priv/www/js/main.js
@@ -142,6 +142,10 @@ function dispatcher() {
go_to('#/exchanges');
return false;
});
+ this.post('#/exchanges/publish', function() {
+ publish_msg(this.params);
+ return false;
+ });
path('#/queues', {'queues': '/queues', 'vhosts': '/vhosts', 'nodes': '/nodes'}, 'queues');
this.get('#/queues/:vhost/:name', function() {
@@ -536,6 +540,18 @@ function toggle_visibility(item) {
}
}
+function publish_msg(params) {
+ var path = fill_path_template('/exchanges/:vhost/:name/publish', params);
+ with_req('POST', path, JSON.stringify(params), function(resp) {
+ var result = jQuery.parseJSON(resp.responseText);
+ if (result.routed) {
+ show_popup('info', 'Message published.');
+ } else {
+ show_popup('warn', 'Message published, but not routed.');
+ }
+ });
+}
+
function get_msgs(params) {
var path = fill_path_template('/queues/:vhost/:name/get', params);
with_req('POST', path, JSON.stringify(params), function(resp) {
diff --git a/deps/rabbitmq_management/priv/www/js/tmpl/exchange.ejs b/deps/rabbitmq_management/priv/www/js/tmpl/exchange.ejs
index 0162735614..c7125657c1 100644
--- a/deps/rabbitmq_management/priv/www/js/tmpl/exchange.ejs
+++ b/deps/rabbitmq_management/priv/www/js/tmpl/exchange.ejs
@@ -94,6 +94,30 @@
+
+
<% if (exchange.name != "") { %>
Delete This Exchange
diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl b/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl
index f762169e82..42a0b256b0 100644
--- a/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl
+++ b/deps/rabbitmq_management/src/rabbit_mgmt_dispatcher.erl
@@ -30,6 +30,7 @@ dispatcher() ->
{["exchanges"], rabbit_mgmt_wm_exchanges, []},
{["exchanges", vhost], rabbit_mgmt_wm_exchanges, []},
{["exchanges", vhost, exchange], rabbit_mgmt_wm_exchange, []},
+ {["exchanges", vhost, exchange, "publish"], rabbit_mgmt_wm_exchange_publish, []},
{["exchanges", vhost, exchange, "bindings", "source"], rabbit_mgmt_wm_bindings, [exchange_source]},
{["exchanges", vhost, exchange, "bindings", "destination"], rabbit_mgmt_wm_bindings, [exchange_destination]},
{["queues"], rabbit_mgmt_wm_queues, []},
diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_util.erl b/deps/rabbitmq_management/src/rabbit_mgmt_util.erl
index a78eba527e..fa08cd4f15 100644
--- a/deps/rabbitmq_management/src/rabbit_mgmt_util.erl
+++ b/deps/rabbitmq_management/src/rabbit_mgmt_util.erl
@@ -20,12 +20,12 @@
-export([is_authorized_vhost/2, is_authorized/3, is_authorized_user/3]).
-export([bad_request/3, id/2, parse_bool/1, parse_int/1]).
-export([with_decode/4, with_decode_opts/4, not_found/3, amqp_request/4]).
--export([with_amqp_request/4, with_amqp_request/5]).
+-export([with_channel/4, with_channel/5]).
-export([props_to_method/2]).
-export([all_or_one_vhost/2, http_to_amqp/5, reply/3, filter_vhost/3]).
-export([filter_user/3, with_decode/5, redirect/2, args/1]).
-export([reply_list/3, reply_list/4, sort_list/4, destination_type/1]).
--export([relativise/2]).
+-export([relativise/2, post_respond/3]).
-include("rabbit_mgmt.hrl").
-include_lib("amqp_client/include/amqp_client.hrl").
@@ -317,18 +317,18 @@ amqp_request(VHost, ReqData, Context, Method) ->
amqp_request(VHost, ReqData, Context, node(), Method).
amqp_request(VHost, ReqData, Context, Node, Method) ->
- with_amqp_request(VHost, ReqData, Context, Node,
+ with_channel(VHost, ReqData, Context, Node,
fun (Ch) ->
amqp_channel:call(Ch, Method),
{true, ReqData, Context}
end).
-with_amqp_request(VHost, ReqData, Context, Fun) ->
- with_amqp_request(VHost, ReqData, Context, node(), Fun).
+with_channel(VHost, ReqData, Context, Fun) ->
+ with_channel(VHost, ReqData, Context, node(), Fun).
-with_amqp_request(VHost, ReqData,
- Context = #context{ user = #user { username = Username },
- password = Password }, Node, Fun) ->
+with_channel(VHost, ReqData,
+ Context = #context{ user = #user { username = Username },
+ password = Password }, Node, Fun) ->
try
Params = #amqp_params{username = Username,
password = Password,
@@ -404,4 +404,8 @@ relativise0(From, To) ->
relativise(From, To, Diff) ->
string:join(lists:duplicate(length(From) - Diff, "..") ++ To, "/").
-
+post_respond(Response, ReqData, Context) ->
+ {JSON, _, _} = reply(Response, ReqData, Context),
+ {true, wrq:set_resp_header(
+ "content-type", "application/json",
+ wrq:append_to_response_body(JSON, ReqData)), Context}.
diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_wm_exchange.erl b/deps/rabbitmq_management/src/rabbit_mgmt_wm_exchange.erl
index ab9d98af1b..087f1ce861 100644
--- a/deps/rabbitmq_management/src/rabbit_mgmt_wm_exchange.erl
+++ b/deps/rabbitmq_management/src/rabbit_mgmt_wm_exchange.erl
@@ -17,7 +17,7 @@
-export([init/1, resource_exists/2, to_json/2,
content_types_provided/2, content_types_accepted/2,
is_authorized/2, allowed_methods/2, accept_content/2,
- delete_resource/2, exchange/2]).
+ delete_resource/2, exchange/1, exchange/2]).
-include("rabbit_mgmt.hrl").
-include_lib("webmachine/include/webmachine.hrl").
diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_wm_exchange_publish.erl b/deps/rabbitmq_management/src/rabbit_mgmt_wm_exchange_publish.erl
new file mode 100644
index 0000000000..5b0da3a242
--- /dev/null
+++ b/deps/rabbitmq_management/src/rabbit_mgmt_wm_exchange_publish.erl
@@ -0,0 +1,70 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License at
+%% http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+%% License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Original Code is RabbitMQ Management Plugin.
+%%
+%% The Initial Developer of the Original Code is VMware, Inc.
+%% Copyright (c) 2007-2010 VMware, Inc. All rights reserved.
+-module(rabbit_mgmt_wm_exchange_publish).
+
+-export([init/1, resource_exists/2, post_is_create/2, is_authorized/2,
+ allowed_methods/2, process_post/2]).
+
+-include("rabbit_mgmt.hrl").
+-include_lib("webmachine/include/webmachine.hrl").
+-include_lib("amqp_client/include/amqp_client.hrl").
+
+%%--------------------------------------------------------------------
+init(_Config) -> {ok, #context{}}.
+
+allowed_methods(ReqData, Context) ->
+ {['POST'], ReqData, Context}.
+
+resource_exists(ReqData, Context) ->
+ {case rabbit_mgmt_wm_exchange:exchange(ReqData) of
+ not_found -> false;
+ _ -> true
+ end, ReqData, Context}.
+
+post_is_create(ReqData, Context) ->
+ {false, ReqData, Context}.
+
+process_post(ReqData, Context) ->
+ VHost = rabbit_mgmt_util:vhost(ReqData),
+ X = rabbit_mgmt_util:id(exchange, ReqData),
+ rabbit_mgmt_util:with_decode(
+ [routing_key, properties, payload], ReqData, Context,
+ fun([RoutingKey, Properties, Payload]) ->
+ rabbit_mgmt_util:with_channel(
+ VHost, ReqData, Context,
+ fun (Ch) ->
+ amqp_channel:register_confirm_handler(Ch, self()),
+ amqp_channel:register_return_handler(Ch, self()),
+ amqp_channel:call(Ch, #'confirm.select'{}),
+ Props = rabbit_mgmt_format:to_amqp_table(Properties),
+ amqp_channel:cast(Ch, #'basic.publish'{
+ exchange = X,
+ routing_key = RoutingKey,
+ mandatory = true},
+ #amqp_msg{props = Props,
+ payload = Payload}),
+ Routed = receive
+ {#'basic.return'{}, _} -> false;
+ #'basic.ack'{} -> true
+ end,
+ rabbit_mgmt_util:post_respond(
+ [{routed, Routed}], ReqData, Context)
+ end)
+ end).
+
+is_authorized(ReqData, Context) ->
+ rabbit_mgmt_util:is_authorized_vhost(ReqData, Context).
+
+%%--------------------------------------------------------------------
diff --git a/deps/rabbitmq_management/src/rabbit_mgmt_wm_queue_get.erl b/deps/rabbitmq_management/src/rabbit_mgmt_wm_queue_get.erl
index 5379e85c5e..9fb9e90318 100644
--- a/deps/rabbitmq_management/src/rabbit_mgmt_wm_queue_get.erl
+++ b/deps/rabbitmq_management/src/rabbit_mgmt_wm_queue_get.erl
@@ -43,13 +43,13 @@ process_post(ReqData, Context) ->
rabbit_mgmt_util:with_decode(
[requeue, count], ReqData, Context,
fun([RequeueBin, CountBin]) ->
- rabbit_mgmt_util:with_amqp_request(
+ rabbit_mgmt_util:with_channel(
VHost, ReqData, Context,
fun (Ch) ->
NoAck = not rabbit_mgmt_util:parse_bool(RequeueBin),
Count = rabbit_mgmt_util:parse_int(CountBin),
- post_respond(basic_gets(Count, Ch, Q, NoAck),
- ReqData, Context)
+ rabbit_mgmt_util:post_respond(
+ basic_gets(Count, Ch, Q, NoAck), ReqData, Context)
end)
end).
@@ -90,12 +90,6 @@ basic_get(Ch, Q, NoAck) ->
none
end.
-post_respond(Response, ReqData, Context) ->
- {JSON, _, _} = rabbit_mgmt_util:reply(Response, ReqData, Context),
- {true, wrq:set_resp_header(
- "content-type", "application/json",
- wrq:append_to_response_body(JSON, ReqData)), Context}.
-
is_authorized(ReqData, Context) ->
rabbit_mgmt_util:is_authorized_vhost(ReqData, Context).