# ExKeyCDN
Elixir client for https://www.keycdn.com/api
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `exExKeyCDN` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:exKeyCDN, "~> 0.1.0"}
]
end
```
## API Key
`export api_key="value"`
## ExKeyCDN.zone
```elixir
iex(11)> ExKeyCDN.Zone.list
[zones: [], limits: [rate_limit_remaining: "60", rate_limit: "60"]]
```
```elixir
iex(11)> zone = %ExKeyCDN.Zone{name: "tribal", originurl: "https://blog.tentamen.eu"}
iex(11)> ExKeyCDN.Zone.add zone
[
zone: %ExKeyCDN.Zone{
cachekeyscheme: "disabled",
cachebr: "disabled",
name: "tribal",
type: "push",
cachecanonical: "disabled",
forcedownload: "disabled",
blockbadbots: "disabled",
cachehostheader: "disabled",
blockreferrer: "disabled",
securetokenkey: "",
cachemaxexpire: 1440,
forcessl: "disabled",
sslcert: "shared",
originurl: "https://example.com",
cachekeycookie: "alphanumeric32charachters",
cacheignorequerystring: "enabled",
status: "active",
expire: "0",
cacheignorecachecontrol: "enabled",
cors: "disabled",
cacheerrorpages: "disabled",
cachexpullkey: "ExKeyCDN",
cachekeywebp: "disabled",
customsslkey: nil,
gzip: "disabled",
cachestripcookies: "disabled",
cachekeydevice: "disabled",
dirlistt: "disabled",
cachekeyhost: "disabled",
id: "190710",
securetoken: "disabled",
allowemptyreferrer: "enabled",
imgproc: "disabled",
originshield: "disabled",
cacherobots: "disabled",
cachecookies: "disabled",
customsslcert: nil
},
limits: [rate_limit_remaining: "60", rate_limit: "60"]
]
```
```elixir
iex(11)> ExKeyCDN.Zone.list
[
zones: [
%ExKeyCDN.Zone{
expire: "0",
cacheerrorpages: "disabled",
name: "tribal",
type: "push",
cachekeyscheme: "disabled",
securetoken: "disabled",
customsslkey: nil,
cachecanonical: "disabled",
cachekeyhost: "disabled",
cachekeywebp: "disabled",
forcessl: "disabled",
cachexpullkey: "ExKeyCDN",
cachebr: "disabled",
originurl: "https://example.com",
cors: "disabled",
cachekeydevice: "disabled",
cachecookies: "disabled",
status: "active",
cacheignorequerystring: "enabled",
originshield: "disabled",
sslcert: "shared",
blockreferrer: "disabled",
imgproc: "disabled",
gzip: "disabled",
allowemptyreferrer: "enabled",
dirlist: "disabled",
cacherobots: "disabled",
forcedownload: "disabled",
id: "190968",
cachehostheader: "disabled",
cachemaxexpire: 1440,
cachekeycookie: "alphanumeric32charachters",
cachestripcookies: "disabled",
securetokenkey: "",
blockbadbots: "disabled",
customsslcert: nil,
cacheignorecachecontrol: "enabled"
}
],
limits: [rate_limit_remaining: "60", rate_limit: "60"]
]
```
```elixir
iex(11)> ExKeyCDN.Zone.edit(190710, %{expire: 1440})
[
zone: %ExKeyCDN.Zone{
cachekeyscheme: "disabled",
cachebr: "disabled",
name: "tribal",
type: "push",
cachecanonical: "disabled",
forcedownload: "disabled",
blockbadbots: "disabled",
cachehostheader: "disabled",
blockreferrer: "disabled",
securetokenkey: "",
cachemaxexpire: 1440,
forcessl: "disabled",
sslcert: "shared",
originurl: "https://example.com",
cachekeycookie: "alphanumeric32charachters",
cacheignorequerystring: "enabled",
status: "active",
expire: "1440",
cacheignorecachecontrol: "enabled",
cors: "disabled",
cacheerrorpages: "disabled",
cachexpullkey: "ExKeyCDN",
cachekeywebp: "disabled",
customsslkey: nil,
gzip: "disabled",
cachestripcookies: "disabled",
cachekeydevice: "disabled",
dirlistt: "disabled",
cachekeyhost: "disabled",
id: "190710",
securetoken: "disabled",
allowemptyreferrer: "enabled",
imgproc: "disabled",
originshield: "disabled",
cacherobots: "disabled",
cachecookies: "disabled",
customsslcert: nil
},
limits: [rate_limit_remaining: "60", rate_limit: "60"]
```
```elixir
ExKeyCDN.Zone.view 190395
[
zones: %ExKeyCDN.Zone{
cachehostheader: "disabled",
forcessl: "disabled",
name: "karlo",
type: "push",
expire: "0",
cachemaxexpire: 1440,
originurl: "url of max 128 characters",
cachekeycookie: "alphanumeric 32 charachters",
originshield: "disabled",
cachexpullkey: "ExKeyCDN",
cacheignorequerystring: "enabled",
cachekeydevice: "disabled",
allowemptyreferrer: "enabled",
sslcert: "shared",
cachekeyhost: "disabled",
cacheerrorpages: "disabled",
status: "active",
cachekeywebp: "disabled",
cachekeyscheme: "disabled",
blockreferrer: "disabled",
securetokenkey: nil,
customsslkey: nil,
forcedownload: "disabled",
gzip: "disabled",
securetoken: "disabled",
cachestripcookies: "disabled",
id: "190395",
blockbadbots: "disabled",
cachecanonical: "disabled",
imgproc: "disabled",
customsslcert: nil,
dirlistt: "disabled",
cors: "disabled",
cachebr: "disabled",
cacheignorecachecontrol: "enabled",
cachecookies: "disabled",
cacherobots: "disabled"
},
limits: [rate_limit_remaining: "60", rate_limit: "60"]
]
```
```elixir
iex(11)> ExKeyCDN.Zone.delete(190710)
[zone: :deleted, limits: [rate_limit_remaining: "60", rate_limit: "60"]]
```
```elixir
iex(11)> ExKeyCDN.Zone.delete 190710
{:error, :forbidden}
```
```elixir
iex(11)> ExKeyCDN.Zone.purge_cache(190395)
#note, this action lasts > 5 sec.
[zone: :cache_purged, limits: [rate_limit_remaining: "60", rate_limit: "60"]]
```
```elixir
iex(11)> ExKeyCDN.Zone.purge_url(190395, ["a.css", "b.html"])
#note, this action lasts > 5 sec.
[zone: :url_purged, limits: [rate_limit_remaining: "59", rate_limit: "60"]]
```
## ExKeyCDN.ZoneAlias
```elixir
iex(10)> ExKeyCDN.ZoneAlias.list
[zone_aliases: [], limits: [rate_limit_remaining: "60", rate_limit: "60"]]
```
```elixir
iex(10)> zone_alias = %ExKeyCDN.ZoneAlias{zone_id: 190976, name: "google.hr"}
%ExKeyCDN.ZoneAlias{id: nil, name: "google.hr", zone_id: 190976}
iex(10)> ExKeyCDN.ZoneAlias.add zone_alias
[
zone_alias: %ExKeyCDN.ZoneAlias{id: "119523", name: "google.hr", zone_id: "190976"},
limits: [rate_limit_remaining: "60", rate_limit: "60"]
]
```
```elixir
iex(10)> ExKeyCDN.ZoneAlias.list
[
zone_aliases: [
%ExKeyCDN.ZoneAlias{id: "119523", name: "google.hr", zone_id: "190976"}
],
limits: [rate_limit_remaining: "60", rate_limit: "60"]
]
```
```elixir
iex(10)> ExKeyCDN.ZoneAlias.edit(119523, %{zone_id: 190984, name: "google.hr"})
[
zone_alias: %ExKeyCDN.ZoneAlias{
id: "119523",
name: "google.hr",
zone_id: "190984"
},
limits: [rate_limit_remaining: "59", rate_limit: "60"]
]
```
```elixir
iex(10)> ExKeyCDN.ZoneAlias.delete(119523)
[zone_alias: :deleted, limits: [rate_limit_remaining: "59", rate_limit: "60"]]
```
## ExKeyCDN.ZoneReferrer
```elixir
iex(10)> ExKeyCDN.ZoneReferrer.list
[zone_referrers: [], limits: [rate_limit_remaining: "60", rate_limit: "60"]]
```
```elixir
iex(10)> zone_referrer = %ExKeyCDN.ZoneReferrer{zone_id: 190976, name: "google.hr"}
%ExKeyCDN.ZoneReferrer{id: nil, name: "google.hr", zone_id: 190976}
iex(10)> ExKeyCDN.ZoneReferrer.add zone_referrer
[
zone_referrer: %ExKeyCDN.ZoneReferrer{id: "119523", name: "google.hr", zone_id: "190976"},
limits: [rate_limit_remaining: "60", rate_limit: "60"]
]
```
```elixir
iex(10)> ExKeyCDN.ZoneReferrer.list
[
zone_referrers: [
%ExKeyCDN.ZoneReferrer{id: "119523", name: "google.hr", zone_id: "190976"}
],
limits: [rate_limit_remaining: "60", rate_limit: "60"]
]
```
```elixir
iex(10)> ExKeyCDN.ZoneReferrer.edit(119523, %{zone_id: 190984, name: "google.hr"})
[
zone_referrer: %ExKeyCDN.ZoneReferrer{
id: "119523",
name: "google.hr",
zone_id: "190984"
},
limits: [rate_limit_remaining: "59", rate_limit: "60"]
]
```
```elixir
iex(10)> ExKeyCDN.ZoneReferrer.delete(119523)
[zone_referrer: :deleted, limits: [rate_limit_remaining: "59", rate_limit: "60"]]
```
## Reports
### Traffic
```elixir
iex(8)> now = System.os_time(:second)
1612637843
iex(9)> start = now - 24 * 3600
1612551443
iex(10)> ExKeyCDN.Report.traffic(%ExKeyCDN.Report{zone_id: 191162, start: start, end: now})
[stats: [], limits: [rate_limit_remaining: "60", rate_limit: "60"]]
iex(11)>
```
### Storage
```elixir
iex(3)> ExKeyCDN.Report.storage(%ExKeyCDN.Report{zone_id: 191162, start: start, end: now})
[
stats: [%ExKeyCDN.Statistic{amount: "4096", timestamp: "1612569600"}],
limits: [rate_limit_remaining: "60", rate_limit: "60"]
]
iex(4)>
```
### Image Processing
```elixir
iex(4)> ExKeyCDN.Report.image_processing(%ExKeyCDN.Report{zone_id: 191162, start: start, end: now})
[stats: [], limits: [rate_limit_remaining: "60", rate_limit: "60"]]
```
### Status
```elixir
iex(3)> ExKeyCDN.Report.status(%ExKeyCDN.Report{zone_id: 191162, start: start, end: now})
[stats: [], limits: [rate_limit_remaining: "60", rate_limit: "60"]]
```
### Credit
```elixir
iex(3)> ExKeyCDN.Report.credit(%ExKeyCDN.Report{start: start, end: now})
[
stats: [
%ExKeyCDN.CreditStatistic{
amount: "-0.01",
timestamp: "1612483200",
type: "storage"
},
%ExKeyCDN.CreditStatistic{
amount: "-0.01",
timestamp: "1612569600",
type: "storage"
}
],
limits: [rate_limit_remaining: "60", rate_limit: "60"]
]
```
### Balance
```elixir
iex(1)> ExKeyCDN.Report.balance
[amount: "0.92", limits: [rate_limit_remaining: "60", rate_limit: "60"]]
```
## Integration Testing
Library is using behaviour which is a precondition for using Mox library. Here is example how to mock Zone list feature:
```elixir
defmodule ExKeyCDN.ZoneTest do
use ExUnit.Case, async: true
import Mox
# Make sure mocks are verified when the test exits
setup :verify_on_exit!
test "List" do
expected = [
zones: [%ExKeyCDN.Zone{}, %ExKeyCDN.Zone{}],
limits: [rate_limit_remaining: "60", rate_limit: "60"]
]
ExKeyCDN.MockZone
|> expect(:list, fn -> expected end)
assert zone().list() == expected
end
defp zone do
Application.get_env(:exkeycdn, :zone)
end
end
```
Add to your `test_helpers.exs`
```elixir
Mox.defmock(ExKeyCDN.MockZone, for: ExKeyCDN.ZoneBehaviour)
Application.put_env(:exkeycdn, :zone, ExKeyCDN.MockZone)
```
## Development
```
git checkout main
git pull
git remote prune origin
git branch -D branch_name
git tag -a v.x.x.x -m "my version x.x.x"
git push origin v.x.x.x
```
## Test
```
mix format
mix credo --strict
mix test
mix coveralls
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/exExKeyCDN](https://hexdocs.pm/exExKeyCDN).