The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Net::HTTP::Knork - Lightweight implementation of Spore specification

VERSION

version 0.09

SYNOPSIS

    use strict; 
    use warnings; 
    use Net::HTTP::Knork;
    use JSON;
    my $spec = to_json(
        {   version => 1,
            format  => [ "json", ],
            methods => {
                test => {
                    method => 'GET',
                    path   => '/test/:foo',
                    required_params => [ "foo" ],
                }
            }
            base_url => 'http://example.com',
        }
    );

    my $knork = Net::HTTP::Knork->new(spec => $spec);

    # make a GET to 'http://example.com/test/bar'
    my $resp = $knork->test({ foo => bar}); 

DESCRIPTION

Net::HTTP::Knork is a module that aims to be compatible with the Spore specification. So it is like Net::HTTP::Spore but with some differences.

Moo !

When I was working with Net::HTTP::Spore, I found it hard to get around all the magic done with Moose. So this implementation aims at having something more lightweight.

Specifications

Specifications can be written either in a JSON file, string, or as a pure Perl hash. On top of that, every specification passed is validated against the Spore specification, using Data::Rx.

No middlewares

This module does not provide middlewares as in Net::HTTP::Spore, but there are some ways around it that should fit basic needs. See Middlewares below

HTTP::Response compliant

All the responses returned by Knork are objects from a class extending HTTP::Response. This means that you can basically manipulate any response returned by a Knork client as an HTTP::Response.

Always check your HTTP codes !

No assumptions are made regarding the responses you may receive from an API. It means that, contrary to Net::HTTP::Spore, the code won't just die if the API returns a 4XX. This also implies that you should always check the responses returned.

METHODS

new

Creates a new Knork object.

    my $client = Net::HTTP::Knork->new(spec => '/some/file.json');
    # or 
    my $client = Net::HTTP::Knork->new(spec => $a_perl_hash); 
    # or 
    my $client = Net::HTTP::Knork->new($spec => $a_json_object);

Other constructor options:

default_params:

hash specifying default parameters to pass on every requests.

    # pass foo=bar on every request 
    my $client = Net::HTTP::Knork->new(spec => 'some_file.json', default_params => {foo => bar}); 
client: a LWP::UserAgent HTTP client. Automatically created if not passed.
http_options: options to pass to the LWP::UserAgent used as a backend for Knork.
make_sub_from_spec

Creates a new Knork sub from a snippet of spec. You might want to do that if you want to create new subs with parameters you can get on runtime, while maintaining all the benefits of using Knork.

    my $client = Net::HTTP::Knork->new(spec => '/some/file.json');
    my $response = $client->get_foo_url(); 
    my $foo_url = $response->body->{foo_url}; 
    my $post_foo = $client->make_sub_from_spec({method => 'POST', path => $foo_url});
    $client->$post_foo(payload => { bar => 'baz' });

MIDDLEWARES

Usage

    use strict; 
    use warnings; 
    use JSON; 
    use Net::HTTP::Knork; 
    # create a client with a middleware that encode requests to json and
    # decode responses from json 
    my $client = Net::HTTP::Knork->new(spec => '/path/to/spec.json');
    $client->add_middleware(
        {   on_request => sub {
                my $self = shift;
                my $req = shift;
                $req->header( 'Content-Type' => 'application/json' );
                $req->header( 'Accept'       => 'application/json' );
                $req->content( $json->encode( $req->content ) );
                return $req;
            },
            on_response => sub {
                my $self = shift;
                my $resp = shift;
                $resp->content( $json->decode( $resp->content ) );
                return $resp;
              }
        }
    );

Although middlewares cannot be created as in Net::HTTP::Spore, there is still the possibility to declare subs that will be executed either on requests or responses. To accomplish this, it installs modifiers around some core functions in Net::HTTP::Knork, using Class::Method::Modifiers.

Limitations

Basic

The system is kind of rough on edges. It should match simple needs, but for complex middlewares it would need a lot of code.

Order of application

The last middleware applicated will always be the first executed.

TESTING

As a HTTP client can be specified as a parameter when building a Net::HTTP::Knork client, this means that you can use Test::LWP::UserAgent to test your client. This is also how tests for Net::HTTP::Knork are implemented.

    use Test::More;
    use Test::LWP::UserAgent;
    use Net::HTTP::Knork;
    use Net::HTTP::Knork::Response;
    my $tua = Test::LWP::UserAgent->new;
    $tua->map_response(
        sub {
            my $req = shift;
            my $uri_path = $req->uri->path;
            if ( $req->method eq 'GET' ) {
                return ( $uri_path eq '/show/foo' );
            }
        },
        Net::HTTP::Knork::Response->new('200','OK')
    );
    my $client = Net::HTTP::Knork->new(
        spec => {
            base_url => 'http://example.com',
            name     => 'test',
            methods  => [
                {   get_user_info => { method => 'GET', path => '/show/:user' }
                }
            ]
        },
        client => $tua
    );


    my $resp = $client->get_user_info( { user => 'foo' } );
    is( $resp->code, '200', 'our user is correctly set to foo' );

TODO

This is still early alpha code but there are still some things missing :

debug mode
more tests
a real life usage

BUGS

This code is early alpha, so there will be a whole bucket of bugs.

ACKNOWLEDGEMENTS

Many thanks to Franck Cuny, the originator of Net::HTTP::Spore. Some parts of this module borrow code from his module.

SEE ALSO

Net::HTTP::Spore

AUTHOR

Emmanuel Peroumalnaïk

COPYRIGHT AND LICENSE

This software is copyright (c) 2014 by E. Peroumalnaik.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.