mirror of
https://github.com/processone/ejabberd.git
synced 2024-07-04 23:15:31 +02:00
Making progress on the Atom interface.
- GET items - POST items - GET nodes HTTP error codes now are the ones XMPP returns.
This commit is contained in:
parent
a22ebd3c49
commit
cd923838c3
45
doc/http_post.md
Normal file
45
doc/http_post.md
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# Managing pubsub nodes through HTTP Atompub #
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration ##
|
||||||
|
|
||||||
|
These options will be used by the service to know how to build URLs. Using the previous configuration items the service should be accessed through `http://notify.push.bbc.co.uk:5280/pshb/<host>/<node>/`.
|
||||||
|
|
||||||
|
Also, in the ejabberd_http handler configuration, add the identified line.
|
||||||
|
|
||||||
|
{5280, ejabberd_http, [
|
||||||
|
http_poll,
|
||||||
|
web_admin,
|
||||||
|
{request_handlers, [{["pshb"], pshb_http}]} % this should be added
|
||||||
|
]}
|
||||||
|
|
||||||
|
## Usage example with cURL ##
|
||||||
|
|
||||||
|
### Getting the service document ###
|
||||||
|
|
||||||
|
No authentication necessary. All nodes are listed.
|
||||||
|
|
||||||
|
curl -i http://<host>:<port>/pshb/<domain>/
|
||||||
|
|
||||||
|
### Getting items from a node ###
|
||||||
|
|
||||||
|
No authentication done, and all nodes are accessible.
|
||||||
|
|
||||||
|
curl -i http://<host>:<port>/pshb/<domain>/<node>/
|
||||||
|
|
||||||
|
|
||||||
|
### Posting a new item ###
|
||||||
|
|
||||||
|
curl -u <jid>:<password> -i -X POST -d @entry.atom http://<host>:<port>/pshb/<domain>/<node>
|
||||||
|
|
||||||
|
User ability to post is based on node configuration.
|
||||||
|
|
||||||
|
|
||||||
|
### Creating a new node ###
|
||||||
|
|
||||||
|
An instant node can be created :
|
||||||
|
|
||||||
|
curl -X POST -u cstar@localhost:encore -d "" http://localhost:5280/pshb/localhost
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,19 +44,17 @@
|
||||||
|
|
||||||
-include("mod_pubsub/pubsub.hrl").
|
-include("mod_pubsub/pubsub.hrl").
|
||||||
|
|
||||||
-export([process/2]).
|
-export([process/2]).
|
||||||
|
|
||||||
process([_Domain, _Node|_Rest]=LocalPath, #request{auth = Auth} = Request)->
|
process(LocalPath, #request{auth = Auth} = Request)->
|
||||||
|
?DEBUG("LocalPath = ~p", [LocalPath]),
|
||||||
case get_auth(Auth) of
|
case get_auth(Auth) of
|
||||||
%%make sure user belongs to pubsub domain
|
%%make sure user belongs to pubsub domain
|
||||||
{User, Domain} ->
|
{User, Domain} ->
|
||||||
out(Request, Request#request.method, LocalPath,{User, Domain});
|
out(Request, Request#request.method, LocalPath,{User, Domain});
|
||||||
_ ->
|
_ ->
|
||||||
out(Request, Request#request.method, LocalPath,undefined)
|
out(Request, Request#request.method, LocalPath, undefined)
|
||||||
end;
|
end.
|
||||||
|
|
||||||
process(_LocalPath, _Request)->
|
|
||||||
error(404).
|
|
||||||
|
|
||||||
get_auth(Auth) ->
|
get_auth(Auth) ->
|
||||||
case Auth of
|
case Auth of
|
||||||
|
@ -128,13 +126,42 @@ out(Args, 'POST', [Domain, Node]=Uri, {User, _Domain}) ->
|
||||||
?DEBUG("Publishing to ~p~n",[entry_uri(Args, Domain, Node,Slug)]),
|
?DEBUG("Publishing to ~p~n",[entry_uri(Args, Domain, Node,Slug)]),
|
||||||
{201, [{"location", entry_uri(Args, Domain,Node,Slug)}], Payload};
|
{201, [{"location", entry_uri(Args, Domain,Node,Slug)}], Payload};
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
error(400, Error)
|
error(Error)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
out(Args, 'GET', [Domain]=Uri, From)->
|
||||||
|
Host = get_host(Uri),
|
||||||
|
?DEBUG("Host = ~p", [Host]),
|
||||||
|
case mod_pubsub:tree_action(Host, get_subnodes, [Host, <<>>, From ]) of
|
||||||
|
[] ->
|
||||||
|
?DEBUG("Error getting URI ~p : ~p",[Uri, From]),
|
||||||
|
error(404);
|
||||||
|
Collections ->
|
||||||
|
{200, [{"Content-Type", "application/atomsvc+xml"}], "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
|
||||||
|
++ xml:element_to_string(service(Args,Domain, Collections))}
|
||||||
|
end;
|
||||||
|
|
||||||
|
out(Args, 'POST', [Domain]=Uri, {User, UDomain})->
|
||||||
|
Host = get_host(Uri),
|
||||||
|
case mod_pubsub:create_node(Host, Domain, <<>>, {User, UDomain}, "default") of
|
||||||
|
{error, Error} ->
|
||||||
|
?ERROR_MSG("Error create node via HTTP : ~p",[Error]),
|
||||||
|
|
||||||
|
error(Error); % will probably detail more
|
||||||
|
{result, [Node]} ->
|
||||||
|
{200, [{"Content-Type", "application/xml"}], "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
|
||||||
|
++ xml:element_to_string(Node)}
|
||||||
|
end;
|
||||||
|
|
||||||
|
out(Args, 'POST', [Domain]=Uri, undefined) ->
|
||||||
|
error(403);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
out(Args, 'GET', [Domain, Node, _Item]=URI, _) ->
|
out(Args, 'GET', [Domain, Node, _Item]=URI, _) ->
|
||||||
Failure = fun(Error)->
|
Failure = fun(Error)->
|
||||||
?DEBUG("Error getting URI ~p : ~p",[URI, Error]),
|
?DEBUG("Error getting URI ~p : ~p",[URI, Error]),
|
||||||
error(404)
|
error(Error)
|
||||||
end,
|
end,
|
||||||
Success = fun(Item)->
|
Success = fun(Item)->
|
||||||
Etag =generate_etag(Item),
|
Etag =generate_etag(Item),
|
||||||
|
@ -169,10 +196,10 @@ get_member([_Domain, _Node, Member])->
|
||||||
Member.
|
Member.
|
||||||
|
|
||||||
collection_uri(R, Domain, Node) ->
|
collection_uri(R, Domain, Node) ->
|
||||||
base_uri(R, Domain)++ "/" ++Node.
|
base_uri(R, Domain)++ "/" ++ b2l(Node).
|
||||||
|
|
||||||
entry_uri(R,Domain, Node, Id)->
|
entry_uri(R,Domain, Node, Id)->
|
||||||
collection_uri(R,Domain, Node)++"/"++Id.
|
collection_uri(R,Domain, Node)++"/"++b2l(Id).
|
||||||
|
|
||||||
base_uri(#request{host=Host, port=Port}, Domain)->
|
base_uri(#request{host=Host, port=Port}, Domain)->
|
||||||
"http://"++Host++":"++i2l(Port)++"/pshb/" ++ Domain.
|
"http://"++Host++":"++i2l(Port)++"/pshb/" ++ Domain.
|
||||||
|
@ -208,8 +235,25 @@ collection(Title, Link, Updated, _Id, Entries)->
|
||||||
{xmlelement, "title", [],[{xmlcdata, Title}]} |
|
{xmlelement, "title", [],[{xmlcdata, Title}]} |
|
||||||
Entries
|
Entries
|
||||||
]}.
|
]}.
|
||||||
|
|
||||||
|
service(Args, Domain,Collections)->
|
||||||
|
{xmlelement, "service", [{"xmlns", "http://www.w3.org/2007/app"},
|
||||||
|
{"xmlns:atom", "http://www.w3.org/2005/Atom"},
|
||||||
|
{"xmlns:app", "http://www.w3.org/2007/app"}],[
|
||||||
|
{xmlelement, "workspace", [],[
|
||||||
|
{xmlelement, "atom:title", [],[{xmlcdata,"Pubsub node Feed for " ++Domain}]} |
|
||||||
|
lists:map(fun(#pubsub_node{nodeid={_Server, Id}, type=_Type})->
|
||||||
|
{xmlelement, "collection", [{"href", collection_uri(Args,Domain, Id)}], [
|
||||||
|
{xmlelement, "atom:title", [], [{xmlcdata, Id}]}
|
||||||
|
]}
|
||||||
|
end, Collections)
|
||||||
|
]}
|
||||||
|
]}.
|
||||||
|
|
||||||
%% simple output functions
|
%% simple output functions
|
||||||
|
error({xmlelement, "error", Attrs, _}=Error) ->
|
||||||
|
Value = list_to_integer(xml:get_attr_s("code", Attrs)),
|
||||||
|
{Value, [{"Content-type", "application/xml"}], xml:element_to_string(Error)};
|
||||||
error(404)->
|
error(404)->
|
||||||
{404, [], "Not Found"};
|
{404, [], "Not Found"};
|
||||||
error(403)->
|
error(403)->
|
||||||
|
@ -221,7 +265,6 @@ error(401)->
|
||||||
error(Code)->
|
error(Code)->
|
||||||
{Code, [], ""}.
|
{Code, [], ""}.
|
||||||
error(Code, Error) when is_list(Error) -> {Code, [], Error};
|
error(Code, Error) when is_list(Error) -> {Code, [], Error};
|
||||||
error(Code, {xmlelement, "error",_,_}=Error) -> {Code, [], xml:element_to_string(Error)};
|
|
||||||
error(Code, _Error) -> {Code, [], "Bad request"}.
|
error(Code, _Error) -> {Code, [], "Bad request"}.
|
||||||
success(200)->
|
success(200)->
|
||||||
{200, [], ""};
|
{200, [], ""};
|
||||||
|
@ -295,4 +338,7 @@ add_zero(L) when is_list(L) -> L.
|
||||||
|
|
||||||
|
|
||||||
i2l(I) when is_integer(I) -> integer_to_list(I);
|
i2l(I) when is_integer(I) -> integer_to_list(I);
|
||||||
i2l(L) when is_list(L) -> L.
|
i2l(L) when is_list(L) -> L.
|
||||||
|
|
||||||
|
b2l(B) when is_binary(B) -> binary_to_list(B);
|
||||||
|
b2l(L) when is_list(L) -> L.
|
Loading…
Reference in New Issue
Block a user