Current section

Files

Jump to
erldns src admin erldns_admin_zone_records_handler.erl
Raw

src/admin/erldns_admin_zone_records_handler.erl

-module(erldns_admin_zone_records_handler).
-moduledoc """
Support for the erldns Admin API root resource at path `/zones/:zonename/records[/:record_name]`.
The following is implemented:
- `GET`: Returns information about records in a given zone cached in erldns.
The response JSON body looks like the following:
```json
[
{
"name": "www.example.com.",
"type": "CNAME",
"ttl": 120,
"content": "example.com."
},
{
"name": "mail.example.com.",
"type": "MX",
"ttl": 3600,
"content": "10 mail.example.com."
}
]
```
""".
-export([
init/2,
content_types_provided/2,
resource_exists/2,
allowed_methods/2
]).
-export([to_html/2, to_text/2, to_json/2]).
-behaviour(cowboy_rest).
-include_lib("kernel/include/logger.hrl").
-define(LOG_METADATA, #{domain => [erldns, admin]}).
-doc false.
-spec init(cowboy_req:req(), dynamic()) ->
{cowboy_rest, cowboy_req:req(), dynamic()}.
init(Req, State) ->
{cowboy_rest, Req, State}.
-doc false.
-spec allowed_methods(cowboy_req:req(), dynamic()) ->
{[binary()], cowboy_req:req(), dynamic()}.
allowed_methods(Req, State) ->
{[~"GET"], Req, State}.
-doc false.
-spec content_types_provided(cowboy_req:req(), dynamic()) ->
{[{{binary(), binary(), '*'}, atom()}], cowboy_req:req(), dynamic()}.
content_types_provided(Req, State) ->
{
[
{{~"application", ~"json", '*'}, to_json},
{{~"text", ~"html", '*'}, to_html},
{{~"text", ~"plain", '*'}, to_text}
],
Req,
State
}.
-doc false.
-spec resource_exists(cowboy_req:req(), dynamic()) ->
{boolean(), cowboy_req:req(), dynamic()}.
resource_exists(Req, State) ->
Name = cowboy_req:binding(zonename, Req),
{erldns_zone_cache:is_in_any_zone(Name), Req, State}.
-doc false.
-spec to_html(cowboy_req:req(), dynamic()) ->
{cowboy_req:resp_body(), cowboy_req:req(), dynamic()}.
to_html(Req, State) ->
{~"erldns admin", Req, State}.
-doc false.
-spec to_text(cowboy_req:req(), dynamic()) ->
{cowboy_req:resp_body(), cowboy_req:req(), dynamic()}.
to_text(Req, State) ->
{~"erldns admin", Req, State}.
-doc false.
-spec to_json(cowboy_req:req(), dynamic()) ->
{stop | cowboy_req:resp_body(), cowboy_req:req(), dynamic()}.
to_json(Req, State) ->
ZoneName = cowboy_req:binding(zonename, Req),
RecordName = cowboy_req:binding(record_name, Req),
Type = lists:keyfind(~"type", 1, cowboy_req:parse_qs(Req)),
?LOG_DEBUG(
#{what => get_zone_resource_call, zone => ZoneName, record => RecordName, type => Type},
?LOG_METADATA
),
case {RecordName, Type} of
{undefined, false} ->
Opts = #{mode => zone_records_to_json},
return_answer(ZoneName, Opts, Req, State);
{_, false} ->
Opts = #{mode => {zone_records_to_json, RecordName}},
return_answer(ZoneName, Opts, Req, State);
{_, {_, RecordType}} ->
Opts = #{mode => {zone_records_to_json, RecordName, RecordType}},
return_answer(ZoneName, Opts, Req, State)
end.
return_answer(ZoneName, Opts, Req, State) ->
case erldns_zone_cache:lookup_zone(ZoneName) of
zone_not_found ->
?LOG_ERROR(#{what => get_zone_records_error, error => zone_not_found}, ?LOG_METADATA),
Resp = "Error getting zone: zone not found",
{stop, cowboy_req:reply(400, #{}, Resp, Req), State};
Zone ->
Json = erldns_zone_codec:encode(Zone, Opts),
Response = json:encode(Json),
{Response, Req, State}
end.