/exkeycdn

Elixir library for keycdn API

Primary LanguageElixirMIT LicenseMIT

ExKeyCDN

Elixir client for https://www.keycdn.com/api

Installation

If available in Hex, the package can be installed by adding exExKeyCDN to your list of dependencies in mix.exs:

def deps do
  [
    {:exKeyCDN, "~> 0.1.0"}
  ]
end

API Key

export api_key="value"

ExKeyCDN.zone

iex(11)> ExKeyCDN.Zone.list
[zones: [], limits: [rate_limit_remaining: "60", rate_limit: "60"]]
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"]
]
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"]
]
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"]
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"]
]
iex(11)> ExKeyCDN.Zone.delete(190710)
[zone: :deleted, limits: [rate_limit_remaining: "60", rate_limit: "60"]]
iex(11)> ExKeyCDN.Zone.delete 190710
{:error, :forbidden}
iex(11)> ExKeyCDN.Zone.purge_cache(190395)
#note, this action lasts > 5 sec.
[zone: :cache_purged, limits: [rate_limit_remaining: "60", rate_limit: "60"]]
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

iex(10)> ExKeyCDN.ZoneAlias.list
[zone_aliases: [], limits: [rate_limit_remaining: "60", rate_limit: "60"]]
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"]
]
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"]
]
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"]
]
iex(10)> ExKeyCDN.ZoneAlias.delete(119523)
[zone_alias: :deleted, limits: [rate_limit_remaining: "59", rate_limit: "60"]]

ExKeyCDN.ZoneReferrer

iex(10)> ExKeyCDN.ZoneReferrer.list
[zone_referrers: [], limits: [rate_limit_remaining: "60", rate_limit: "60"]]
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"]
]
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"]
]
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"]
]
iex(10)> ExKeyCDN.ZoneReferrer.delete(119523)
[zone_referrer: :deleted, limits: [rate_limit_remaining: "59", rate_limit: "60"]]

Reports

Traffic

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

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

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

iex(3)> ExKeyCDN.Report.status(%ExKeyCDN.Report{zone_id: 191162, start: start, end: now})        
[stats: [], limits: [rate_limit_remaining: "60", rate_limit: "60"]]

Credit

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

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:

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

Mox.defmock(ExKeyCDN.MockZone, for: ExKeyCDN.ZoneBehaviour)
Application.put_env(:exkeycdn, :zone, ExKeyCDN.MockZone)

When you test your module that calls any ExKeyCDN module, apply same technique. Add to your config file:

config :your_application,
  exkeycdn_zone: ExKeyCDN.Zone

and in your module define a private function:

defp zone do
  Application.get_env(:your_application, :exkeycdn_zone)
end

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 and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/exExKeyCDN.