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 @@ +
+

Publish Message

+
+
+ + + + + + + + + + + + +
+ +
+
+ +
+
+ <% 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).