This tutorial describes the basics of using Perl to communicate with our API as an end point for managing your MaxCDN account.

  1. Before you start, there are couple of pre-requisites. Assuming Perl is installed on your box, you will need to get into CPANand install following requirements:
    1. install JSON
    2. install Net::OAuth
    3. install LWP::UserAgent
    4. install URI
    5. install Data::Dumper
    6. install IO::Socket::SSL
    7. install LWP::Protocol::https
  2. … and now the actual MaxCDN library:
    1. wget https://github.com/MaxCDN/perl-maxcdn.git
    2. unzip master.zip
    3. cd perl-maxcdn-master/src
  3. At this point, everything is installed. Now we can create our first Perl script with request for account information:
    nano account-info.pl
  4. … and define our API key/secret parameters along with including some libraries we might need later on:
    use strict;
    use warnings;
    use JSON qw( decode_json );
    use MaxCDNRWS;
    use Data::Dumper;
    
    $api = new MaxCDNRWS( 'ALIAS', 'KEY', 'SECRET');
  5. To actually call API and get account info in JSON format, we’ll use the GET method against /account.json:
    Methods: GET.

    my $data = $api->get("/account.json");
    print $data->{'account'}{'name'};
  6. This will return raw json that we want to parse. So let’s try this:
    my $api = new MaxCDNRWS('ALIAS', 'KEY', 'SECRET');
    
    my $data = $api->get("/account.json");
    print "Date Created: " . $data->{'account'}{'date_created'} . "\n";
    print "Company Name: " . $data->{'account'}{'name'} . "\n";
    print "SSL Credits: " . $data->{'account'}{'ssl_credits'} . "\n";
    
  7. Output:
    Date Created:  2012-07-11 19:53:43
    Company Name:  TNT
    SSL Credits:  1
  1. Purge
    Methods: PURGE, DELETE.

    #function to purge single file:
          sub single{
            my ($file, $zone) = @_;
            my @params = ($file);
            $api->delete("/zones/pull.json/" . $zone . "/cache", @params);
    }
    
          #function to purge all
          sub all{
            my ($zone) = @_;
            $api->delete("/zones/pull.json/" . $zone . "/cache");
    }
    
          #function that takes an array of files to purge
          sub multi{
            my (@params, $zone) = @_;
            print @params;
            $api->delete("/zones/pull.json/" . $zone . "/cache", @params);
    }
          print "1. purge single file\n2. purge multiple files\n3. purge all\n\n";
    my $option = <>;
    if($option == "1"){
            print "Zone ID: \n";
            my $zone = <>;
            chomp($zone);
            print "File Path: \n";
            my $file = <>;
            single($file, $zone);
    }
    if($option == "2"){
    print "Enter files and break by hitting CTRL+D\n";
            my @arr = ();
            while () {
                    chomp($_);
                    last if ($_ eq '');
                    push(@arr, $_);
            }
            print "Zone ID: \n";
            my $zone = <>;
            chomp($zone);
            multi(@arr, $zone);
    }
    if($option = "3"){
            print "Zone ID: \n";
            my $zone = <>;
            chomp($zone);
            print "Purging all...\n";
            all($zone);
            print "Done!\n"
    }
  2. List zones
    Methods: GET.

    #define function
             sub list{
            my ($type) = @_;
            chomp($type);
            my $ztype = $type . "zones";
            my $data = $api->get("/zones/" . $type . ".json");
            my $c = $data->{'current_page_size'};
            my $cp = $data->{'pages'};
            print $c;
            my $i = 0;
            my $ip = 0;
            for($ip = 0; $ip < $cp; $ip++){
                    my $page = $ip + 1;
                    $data = $api->get("/zones/" . $type . ".json?page=" . $page, 1);
                    $c = $data->{'current_page_size'};
                    for($i = 0; $i < $c; $i++){
                            print "Name: " . $data->{$ztype}[$i]{'name'} . "\n";
                            if(($type eq "pull") || ($type eq "push")){
                                    print "Compression flag: " . $data->{$ztype}[$i]{'compress'} . "\n";
                            }
                            if($type eq "pull"){
                                    print "Origin: " . $data->{$ztype}[$i]{'url'} . "\n";
                            }
                            print "Name: " . $data->{$ztype}[$i]{'label'} . "\n";
                            print "Page: " . $ip . ", Item: " . $i . "\n\n";
                    }
            }
    }
    
    print "Zone Type: (pull, push, vod)\n";
    my $type = <>;
    list($type);
  3. Create zones
    Methods: POST.

    sub create{
            my ($type) = @_;
            my $name = "";
            my $label = "Zone";
            my $origin = "";
            my $password = "";
            print "Name: \n";
            $name = <>;
            chomp($name);
            print "Label: (Optional)\n";
            $label = <>;
            chomp($label);
            if($type eq "pull"){
                    print "Origin: (http:// included)\n";
                    $origin = <>;
                    chomp($origin);
                    my @params = {name => $name, url => $origin, label => $label};
                    $api->post("/zones/pull.json", @params);
            }
            if(($type eq "push") || ($type eq "vod")){
                    print "Password: \n";
                    $password = <>;
                    chomp($password);
                    my @params = {name => $name, password => $password};
                    $api->post("/zones/" . $type . ".json", @params);
            }
    }
    
    print "Type: (pull, push, vod)\n";
    
    my $type = <>;
    chomp($type);
    
    create($type);
  4. Edit zones
    Methods: PUT.

    sub view{
            my ($zone, $type) = @_;
            my $type1 = $type . "zone";
            my $data = $api->get("/zones/" . $type . ".json/" . $zone);
            print Dumper($data);
            print "Name: " . $data->{$type1}{'name'} . "\n";
            if($type eq "pull" || $type eq "push"){
                    print "Compress: " . $data->{$type1}{'compress'} . "\n";
                    print "Origin: " . $data->{$type1}{'url'} . "\n";
            }
            print "Label: " . $data->{$type1}{'label'} . "\n";
            print "Enter property name to edit: (compress, label,...)\n";
            my $prop = <>;
            chomp($prop);
            edit($prop, $type, $zone);
    }
    
    sub edit{
            my ($prop, $type, $zone) = @_;
            print $prop . "\n\n";
            print "Enter new value for " . $prop . ": \n";
            my $val = <>;
            chomp($val);
            my @params = "";
            push @params, $prop . "=" . $val;
            $api->put("/zones/" . $type . ".json/" . $zone, @params);
            view($zone, $type);
    }
    
    print "Zone to edit: \n";
    my $zone = <>;
    chomp($zone);
    print "Zone type: (pull, push, vod)\n";
    my $type = <>;
    chomp($type);
    view($zone, $type);
  5. Manage Users
    Methods: DELETE, POST, GET.

    sub view{
            my $c = 0;
            my $data = $api->get("/users.json");
            print Dumper($data);
            my $i = $data->{'current_page_size'};
            for($c = 0; $c < $i; $c++){
                    print "ID: " . $data->{'users'}[$c]{'id'} . "\n";
                    print "First Name: " . $data->{'users'}[$c]{'firstname'} . "\n";
                    print "Last Name: " . $data->{'users'}[$c]{'lastname'} . "\n";
                    print "email: " . $data->{'users'}[$c]{'email'} . "\n";
                    print "Phone: " . $data->{'users'}[$c]{'phone'} . "\n";
                    print $c . "! " . $i . "\n";
            }
            print "Enter User ID to edit: \n";
            my $id = <>;
            chomp($id);
            edit($id);
    }
    
    sub edit{
            my ($id) = @_;
            print "Enter property to edit: (phone,...)\n";
            my $prop = <>;
            chomp($prop);
            print "Enter new value for " . $prop . ": \n";
            my $val = <>;
            chomp($val);
            my @params = "";
            push @params, $prop . "=" . $val;
            $api->put("/users.json/" . $id, @params);
            my $data = $api->get("/users.json/" . $id);
            print Dumper($data);
    }
    
    sub add{
            print "First Name: \n";
            my $fname = <>;
            chomp($fname);
            print "Last Name: \n";
            my $lname = <>;
            chomp($lname);
            print "Email: \n";
            my $email = <>;
            chomp($email);
            print "Password: \n";
            my $password = <>;
            chomp($password);
            my @params = {firstname => $fname, lastname => $lname, email => $email, password => $password};
            $api->post("/users.json", @params);
            view();
    }
    
    sub del{
            print "Enter User ID to delete: \n";
            my $id = <>;
            chomp($id);
            $api->delete("/users.json/" . $id);
            view();
    }
    
    print "Choose action (type the number infront of it): \n\n1. View Users\n2. Edit User\n3. Add User\n4. Delete Users\n\n";
    my $option = <>;
    chomp($option);
    if($option eq "1"){
            view();
    }
    if($option eq "2"){
            print "Enter User ID to edit or choose view option if you don't know the user id yet: \n";
            my $id = <>;
            chomp($id);
            edit($id);
    }
    if($option eq "3"){
            add();
    }
    if($option eq "4"){
            del();
    }
  6. Manage Custom Domains
    Methods: GET, POST, DELETE.

    sub view{
            print "Zone type: \n";
            my $type = <>;
            chomp($type);
            print "Zone: (name or id): \n";
            my $zone = <>;
            chomp($zone);
            my $c = 0;
            my $i = 0;
            my $data = $api->get("/zones/" . $type . "/" . $zone . "/customdomains.json");
            $c = $data->{'total'};
            print Dumper($data);
            for($i = 0; $i < $c; $i++){
                    print "ID: " . $data->{'customdomains'}[$i]{'id'} . "\n";
                    print "Custom Domain: " . $data->{'customdomains'}[$i]{'custom_domain'} . "\n\n";
            }
            print "Enter custom domain ip you want to edit: \n";
            my $id = <>;
            chomp($id);
            edit($id, $type, $zone);
    }
    
    sub edit{
            my ($id, $type, $zone) = @_;
            print "Enter new value for custom domain " . $id . "\n";
            my $val = <>;
            chomp($val);
            my @params = "";
            push @params, "custom_domain=" . $val;
            $api->put("/zones/" . $type . "/" . $zone . "/customdomains.json/" . $id, @params);
    }
    
    sub add{
            print "Zone Type: \n";
            my $type = <>;
            chomp($type);
            print "zone name or id: \n";
            my $zone = <>;
            chomp($zone);
            print "Custom Domain: \n";
            my $name = <>;
            chomp($name);
            my @params = {custom_domain => $name};
            $api->post("/zones/" . $type . "/" . $zone . "/customdomains.json", @params);
    }
    
    sub del{
            print "Zone Type: \n";
            my $type = <>;
            chomp($type);
            print "Zone Name or ID: \n";
            my $zone = <>;
            chomp($zone);
            print "Custom Domain ID: \n";
            my $id = <>;
            chomp($id);
            $api->delete("/zones/" . $type . "/" . $zone . "/customdomains.json/" . $id);
    }
    
    print "Choose option: \n1. View\n2. Add\n3. Edit\n4. Delete\n\n";
    my $option = <>;
    chomp($option);
    if($option eq "1"){
            view();
    }
    if($option eq "2"){
            add();
    }
    if($option eq "3"){
            print "Zone type: (pull, push, vod)\n";
            my $type = <>;
            chomp($type);
            print "Zone name or id: \n";
            my $zone = <>;
            chomp($zone);
            print "Custom Domain ID: \n";
            my $id = <>;
            chomp($id);
            edit($id, $type, $zone);
    }
    if($option eq "4"){
            del();
    }
  7. Reporting
    Methods: GET.

    sub sum{
            my ($param, $type) = @_;
            print "Report type:(hourly/daily/monthly - hit [ENTER] to show total usage): \n~\$";
            my $rtype = <>;
            chomp($rtype);
            my $separator = "/";
            my $zone = "";
            if($param ne ""){
                    $zone = $param . "/";
            }
            if($rtype eq ""){
                    $separator = "";
            }
            if($type eq  ""){
                    $type = "stats";
            }
            my $data = $api->get("/reports/" . $zone . "stats.json" . $separator . $rtype);
            print Dumper($data);
    }
    
    sub nodes{
            my ($zone, $node) = @_;
            print "Report type (hourly/daily/monthly - hit [ENTER] to show total usage): \n~\$ ";
            my $rtype = <>;
            chomp($rtype);
            if($rtype ne ""){
                    $rtype = "/stats/" . $rtype;
            }
            if($zone ne ""){
                    $zone = $zone . "/";
            }
            if($node ne ""){
                    $node = "/" . $node;
            }
            my $data = $api->get("/reports/" . $zone . "nodes.json" . $rtype);
            print Dumper($data);
    }
    
    sub statuscodes{
            my ($zone, $ztype) = @_;
            print "Report type (hourly/daily/monthly - hit [ENTER] to show total usage): \n~\$ ";
            my $rtype = <>;
            chomp($rtype);
            if($rtype ne ""){
                    $rtype = "/" . $rtype;
            }
            if($zone ne ""){
                    $zone = "/" . $zone;
            }
            if($ztype ne ""){
                    $ztype = "/" . $ztype;
            }
            my $data = $api->get("/reports" . $ztype . $zone . "/statuscodes.json" . $rtype);
            print Dumper($data);
    }
    
    sub filetypes{
            my ($zone, $ztype) = @_;
            print "Report type (hourly/daily/monthly - hit [ENTER] to show total usage): \n~\$ ";
            my $rtype = <>;
            chomp($rtype);
            if($rtype ne ""){
                    $rtype = "/" . $rtype;
            }
            if($zone ne ""){
                    $zone = "/" . $zone;
            }
            if($ztype ne ""){
                    $ztype = "/" . $ztype;
            }
            my $data = $api->get("/reports" . $ztype . $zone . "/filetypes.json" . $rtype);
            print Dumper($data);
    }
    
    sub popular{
            my ($zone, $ztype) = @_;
            if($zone ne ""){
                    $zone = "/" . $zone;
            }
            if($ztype ne ""){
                    $ztype = "/" . $ztype;
            }
            my $data = $api->get("/reports" . $ztype . $zone . "/popularfiles.json");
            print Dumper($data);
    }
    
    print "1. Summary\n2. Stats per zone\n3. Node distribution\n4. Status codes\n5. File types\n6. Popular files\n\n~\$ ";
    my $option = <>;
    chomp($option);
    if($option eq "1"){
            sum("", "");
            }
    if($option eq "2"){
            print "Zone ID or Name: \n~\$ ";
            my $zone = <>;
            chomp($zone);
            sum($zone, "");
    }
    if($option eq "3"){
            print "zone ID or Name (Hit ENTER for all): \n~\$ ";
            my $zone = <>;
            chomp($zone);
            print "Node ID (Hit ENTER for all): \n~\$ ";
            my $node = <>;
            chomp($node);
            nodes($zone, $node);
    }
    if($option eq "4"){
            print "Zone ID or Name (Hit ENTER for total usage): \n~\$ ";
            my $zone = <>;
            chomp($zone);
            print "Zone type (Hit ENTER for any - pull, push or vod): \n~\$ ";
            my $ztype = <>;
            chomp($ztype);
            statuscodes($zone, $ztype);
    }
    if($option eq "5"){
            print "zone ID or Name (Hit ENTER for total usage): \n~\$ ";
            my $zone = <>;
            chomp($zone);
            print "Zone type (Hit ENTER for any - pull, push or vod): \n~\$ ";
            my $ztype = <>;
            chomp($ztype);
            filetypes($zone, $ztype);
    }
    if($option eq "6"){
            print "zone ID or Name (Hit ENTER for all): \n~\$ ";
            my $zone = <>;
            chomp($zone);
            print "zone type (Hit ENTER for any - pull, push or vod): \n~\$ ";
            my $ztype = <>;
            chomp($ztype);
            popular($zone, $ztype);
    }
  8. Raw Logs
    Methods: GET.

    sub fetch{
            my ($dfrom, $dto, $option, $value, $zone) = @_;
            if($option ne ""){
                    $option = "&" . $option . "=" . $value;
            }
            if($zone ne ""){
                    $option .= "&zone_id=" . $zone;
            }
            my $data = $api->get("/v3/reporting/logs.json?start=" . $dfrom . "&end=" . $dto . $option);
            print Dumper($data);
            print $data->[0]{'client_country'};
    }
    print "--------------------------\nFilter Options - type the number in front of an option:\n--------------------------\n1. summary\n2. status codes\n3. referrers\n4. host names\n5. URi\n6. source ip\n\n~\$ ";
    my $option = <>;
    chomp($option);
    if($option eq "1"){
            print "FROM: (yyyy-mm-dd)\n~\$ ";
            my $dfrom = <>;
            chomp($dfrom);
            print "TO: (yyyy-mm-dd)\n~\$ ";
            my $dto = <>;
            chomp($dto);
            print "Zone ID (Empty for all): \n~\$ ";
            my $zone = <>;
            chomp($zone);
            fetch($dfrom, $dto, "", "", $zone);
    }
    if($option eq "2"){
            print "FROM: (yyyy-mm-dd)\n~\$ ";
            my $dfrom = <>;
            chomp($dfrom);
            print "TO: (yyyy-mm-dd)\n~\$ ";
            my $dto = <>;
            chomp($dto);
            print "Zone ID (Empty for all): \n~\$ ";
            my $zone = <>;
            chomp($zone);
            print "Status code: \n~\$ ";
            my $status = <>;
            chomp($status);
            fetch($dfrom, $dto, "status", $status, $zone);
    }
    if($option eq "3"){
            print "FROM: (yyyy-mm-dd)\n~\$ ";
            my $dfrom = <>;
            chomp($dfrom);
            print "TO: (yyyy-mm-dd)\n~\$ ";
            my $dto = <>;
            chomp($dto);
            print "Zone ID (Empty for all): \n~\$ ";
            my $zone = <>;
            chomp($zone);
            print "Referrer: \n~\$ ";
            my $ref = <>;
            chomp($ref);
            fetch($dfrom, $dto, "referer", $ref, $zone);
    }
    if($option eq "4"){
            print "FROM: (yyyy-mm-dd)\n~\$ ";
            my $dfrom = <>;
            chomp($dfrom);
            print "TO: (yyyy-mm-dd)\n~\$ ";
            my $dto = <>;
            chomp($dto);
            print "Zone ID (Empty for all): \n~\$ ";
            my $zone = <>;
            chomp($zone);
            print "Hostname: \n~\$ ";
            my $host = <>;
            chomp($host);
            fetch($dfrom, $dto, "hostname", $host, $zone);
    }
    if($option eq "5"){
            print "FROM: (yyyy-mm-dd)\n~\$ ";
            my $dfrom = <>;
            chomp($dfrom);
            print "TO: (yyyy-mm-dd)\n~\$ ";
            my $dto = <>;
            chomp($dto);
            print "Zone ID (Empty for all): \n~\$ ";
            my $zone = <>;
            chomp($zone);
            print "URi: \n~\$ ";
            my $uri = <>;
            chomp($uri);
            fetch($dfrom, $dto, "uri", $uri, $zone);
    }
    if($option eq "6"){
            print "FROM: (yyyy-mm-dd)\n~\$ ";
            my $dfrom = <>;
            chomp($dfrom);
            print "TO: (yyyy-mm-dd)\n~\$ ";
            my $dto = <>;
            chomp($dto);
            print "Zone ID (Empty for all): \n~\$ ";
            my $zone = <>;
            chomp($zone);
            print "Source IP: \n~\$ ";
            my $ip = <>;
            chomp($ip);
            fetch($dfrom, $dto, "client_ip", $ip, $zone);
    }