package WebService::CloudFlare::Host; use Moose; use Try::Tiny; use Data::Dumper; use LWP; our $VERSION = "000100"; # 0.1.0 $VERSION = eval $VERSION; has 'host_key' => ( is => 'rw', isa => 'Str', required => 1, ); has 'base_api' => ( is => 'ro', isa => 'Str', default => 'https://api.cloudflare.com/host-gw.html', ); has 'user_agent' => ( is => 'ro', isa => 'Str', default => 'WebService::CloudFlare::Host/1.0', ); has 'http_timeout' => ( is => 'ro', isa => 'Int', default => 60, ); has 'ua' => ( is => 'ro', isa => 'LWP::UserAgent', lazy_build => 1, ); sub call { my ( $self, $class, %args ) = @_; # Load the request class. try { Class::MOP::load_class("WebService::CloudFlare::Host::Request::$class"); } catch { $self->_throw_exception( $_, "Loading request class: $class", "Class::MOP::load_class", "WebService::CloudFlare::Host::Request::$class" ); }; # Create the request object. my $req = try { "WebService::CloudFlare::Host::Request::$class"->new( %args ) } catch { $self->_throw_exception( $_, 'Creating API Request', "WebService::CloudFlare::Host::Request::$class", Dumper \%args ); }; # Make the actual HTTP request. my $http_res = try { $self->_do_call( $req ); } catch { $self->_throw_exception( $_, 'Making HTTP Call To Server API', 'WebService::CloudFlare::Host::do_call', Dumper $req ); }; # Create a response object to send back to the user. my $res = try { $self->_create_response( $class, $http_res ); } catch { $self->_throw_exception( $_, 'Creating API Response From HTTP Data', 'WebService::CloudFlare::Host::create_response', Dumper $http_res, ); }; return $res; } sub _throw_exception { my ( $self, $message, $layer, $function, $args ) = @_; # We installed ::Exception with the package, it's here. Class::MOP::load_class('WebService::CloudFlare::Host::Exception'); # Let's get to the bottom of the exception... my $exception; while ( $message->isa( 'WebService::CloudFlare::Host::Exception' ) ) { $exception = $message; $message = $message->message; } die $exception if $exception; die WebService::CloudFlare::Host::Exception->new( message => $message, layer => $layer, function => $function, args => $args, ); } sub _do_call { my ( $self, $request ) = @_; my %arguments = $request->as_post_params; $arguments{host_key} = $self->host_key; return $self->ua->post($self->base_api, \%arguments); } sub _create_response { my ( $self, $class, $http ) = @_; try { Class::MOP::load_class("WebService::CloudFlare::Host::Response::$class"); } catch { $self->_throw_exception( $_, "Loading request class: $class", "Class::MOP::load_class", "WebService::CloudFlare::Host::Reponse::$class" ); }; return "WebService::CloudFlare::Host::Response::$class"->new( $http ); } sub _build_ua { my ( $self ) = @_; return LWP::UserAgent->new( timeout => $self->http_timeout, user_agent => $self->user_agent ); } 1; =head1 NAME WebService::CloudFlare::Host - A client API For Hosting Partners =head1 VERSION 000100 (0.1.0) =head1 SYNOPSIS my $CloudFlare = WebService::CloudFlare::Host->new( host_key => 'cloudflare hostkey', timeout => 30, ); my $response = eval { $CloudFlare->call('UserCreate', email => 'richard.castle@hyperionbooks.com', pass => 'ttekceBetaK', ) }; if ( $@ ) { die "Error: in " . $@->function . ": " . $@->message; } printf("Got API Keys: User Key: %s, User API Key: %s", $response->user_key, $response->api_key ); =head1 DESCRIPTION WebService::CloudFlare::Host is a client side API library to make using CloudFlare simple for hosting providers. It gives a simple interface for making API calls, getting response objects, and implementing additional API calls. All API calls have a Request and Response object that define the accepted information for that call. =head1 METHODS The only method used is C. When making an API call, the first argument defines the API request to load. This is loaded from Request::. Additional arguments are passed as-is to the Request Object. Once the object has been made, an HTTP call to the CloudFlare API is made. The JSON returned is used to construct a Response object loaded from Response:: with the same name as the Request object. C dies on error, giving a WebService::CloudFlare::Host::Exception object and should be run in an eval or with Try::Tiny. =head1 STANDARD OBJECT METHODS =head2 Standard Request Object The host key is dynamically inserted into the Requests. =head2 Standard Response Object The following methods are avilable on standard Response objects. =over 4 =item result The result sent from the API: 'success' or 'error'. =item message If the result is 'error', a message will be set with a user-readable explaination of the error; otherwise, this method will not exist. =item code If the result is 'error', a code will be set. This error can be found at L. =back =head1 API CALLS =head2 UserCreate The UserCreate API call creates a user for the CloudFlare service, as if they had signed up through CloudFlare's website. my $response = eval { $CloudFlare->call('UserCreate', email => 'Casey.Klein@partydown.com', pass => 'omgPassword', unique_id => '506172747920446f776e203c33205521', )}; =head3 Request The request uses the following parameters: =over 4 =item email The email address that the end-user can use to sign into the CloudFlare service. =item pass The password the user can use to sign into the CloudFlare service. This should not be recorded on the Hosting Provider's side. =item user A username for the user. This is used in saluations and emails from CloudFlare. It has no bearing in the rest of the API. =item unique_id A unique id that may be used for UserLookup calls (as opposed to the user's email address). =item clobber When set to 1, a user's unique_id can be replaced with a new unique_id. =back =head3 Response printf("Created account for %s, with Unique ID => %s, " . "User Key => %s, and API Key => %s", $response->unique_id, $response->user_key, $response->api_key ); The response sets the following methods: =over 4 =item api_key This API key allows a hosting provider to act as the user. All user API requests can be completed with this key. =item email This is the registered email account for the CloudFlare user. =item user_key This user_key is used to make Hosting API calls, specifically the ZoneSet, ZoneDelete, and ZoneLookup API calls. =item unique_id This can be used instead of the email address to do UserLookup calls. =item username The username. =back =head2 UserAuth The UserAuth API call gives the hosting provider access to the User's account. The call returns a user_key as well as the api_key and authenticates the Hosting Provider to perform actions as the user. =head3 Request my $response = eval { $CloudFlare->call('UserAuth', email => 'Casey.Klein@partydown.com', pass => 'omgPassword', ) }; The request uses the following parameters: =over 4 =item email The email address that the user used to register the account with CloudFlare. =item pass The password the user uses to login to CloudFlare. This should not be stored on a hosting provider's side. =item unique_id A unique_id that may be used to perform UserLookup API calls. =item clobber If true, the unique_id can be clobbered. =back =head3 Response The response sets the following methods: =over 4 =item api_key This API key allows a hosting provider to act as the user. All user API requests can be completed with this key. =item email This is the registered email account for the CloudFlare user. =item user_key This user_key is used to make Hosting API calls, specifically the ZoneSet, ZoneDelete, and ZoneLookup API calls. =item unique_id This can be used instead of the email address to do UserLookup calls. =back =head2 UserLookup The UserLookup API call gives a hosting provider the ablity to find information on a user account that it has access to through either the unique_id or the email address that was used in UserAuth or UserCreate API calls. =head3 Request my $response = eval { $CloudFlare->call('UserLookup', email => 'Casey.Klein@partydown.com', ) }; The request uses the following parameters: =over 4 =item email The email address that was used in UserCreate or UserAuth API call. This is required if C is not set. =item unique_id The unique_id that was last set in UserCreate or UserAuth API call. This is required if C is not set. =back =head3 Response The response sets the following methods: =over 4 =item api_key This API key allows a hosting provider to act as the user. All user API requests can be completed with this key. =item email This is the registered email account for the CloudFlare user. =item user_key This user_key is used to make Hosting API calls, specifically the ZoneSet, ZoneDelete, and ZoneLookup API calls. =item unique_id This can be used instead of the email address to do UserLookup calls. =item user_authed True if the hosting provider has access to this user. =item user_exists True if the user exists in the CloudFlare system. =item zones A list of zones that the user has associated with his or her account. =back =head2 ZoneSet This associates a zone with the CloudFlare service for the user whose user_key is used. =head3 Request my $response = eval { $CloudFlare->call('ZoneSet', user_key => 'e7af5f120e3240e7bfba063b5f62c922', resolve_to => '173.230.133.102', zone_name => 'partydown.com', subdomains => 'www', ) }; The request uses the following parameters: =over 4 =item user_key The user_key provided by UserCreate, UserLookup, or UserAuth. The zone will be associated with the user whose user_key is used. =item resolve_to The IP address or a CNAME that resolves to the origin server that hosts the content for the given website. =item zone_name The name of the domain. =item subdomains A comma-seperated list of the subdomains from the zone for which CloudFlare should act as a reverse proxy. =back =head3 Response The response sets the following methods: =over 4 =item zone_name The name of the domain. =item resolving The origin server that has been recorded. The same as the one submitted in the Request. =item forwarded A hashref whose keys are the domain, and whose value is the CNAME that should be used in the DNS system to have the requests be processed by CloudFlare. =item hosted A hashref whose keys are the the domain name(s) that are hosted, and whose value is the resolving address. =back =head2 ZoneDelete This will remove a zone from being hosted by the user whose user_key is used, provided they are the ones hosting the zone. =head3 Request my $response = eval { $CloudFlare->call('ZoneDelete', user_key => 'e7af5f120e3240e7bfba063b5f62c922', zone_name => 'partydown.com', ) }; The request uses the following parameters: =over 4 =item user_key The user_key of the user whose zone is being removed from CloudFlare. =item zone_name The name of the zone to be removed. =back =head3 Response The response sets the following methods: =over 4 =item zone_name The name of the zone from the Request. =item zone_deleted True if the zone was deleted. =back =head2 ZoneLookup Find information on a zone hosted by a given user_key. =head3 Request my $response = eval { $CloudFlare->call('ZoneLookup', user_key => 'e7af5f120e3240e7bfba063b5f62c922', zone_name => 'partydown.com', ) }; The request uses the following parameters: =over 4 =item user_key The user_key of the user whose zone is being removed from CloudFlare. =item zone_name The name of the zone to be removed. =back =head3 Response The response sets the following methods: =over 4 =item zone_name =item resolving The origin server that has been recorded. The same as the one submitted in the Request. =item forwarded A hashref whose keys are the domain, and whose value is the CNAME that should be used in the DNS system to have the requests be processed by CloudFlare. =item hosted A hashref whose keys are the the domain name(s) that are hosted, and whose value is the resolving address. =item zone_exists True if the zone exists in the CloudFlare service. =item zone_hosted True if the zone is hosted by this user_key. =back =head1 CREATING API CALLS TBD =head2 Request Classes =head2 Response Classes =head1 AUTHOR SymKat Isymkat@symkat.comE> =head1 COPYRIGHT AND LICENSE This is free software licensed under a I License. Please see the LICENSE file included in this package for more detailed information. =head1 AVAILABILITY The latest version of this software is available through GitHub at https://github.com/symkat/webservice-cloudflare-host/ =cut