File Coverage

blib/lib/WWW/GitHub/PostReceiveHook.pm
Criterion Covered Total %
statement 26 26 100.0
branch 3 4 75.0
condition 1 3 33.3
subroutine 6 6 100.0
pod 0 1 0.0
total 36 40 90.0


line stmt bran cond sub pod time code
1             #
2             # This file is part of WWW-GitHub-PostReceiveHook
3             #
4             # This software is copyright (c) 2011 by Matt Phillips.
5             #
6             # This is free software; you can redistribute it and/or modify it under
7             # the same terms as the Perl 5 programming language system itself.
8             #
9 1     1   1811 use Web::Simple 'WWW::GitHub::PostReceiveHook';
  1         64524  
  1         7  
10             package WWW::GitHub::PostReceiveHook;
11             # ABSTRACT: A simple means of receiving GitHub's web hooks
12             $WWW::GitHub::PostReceiveHook::VERSION = '0.004';
13 1     1   4898 use Try::Tiny;
  1         1583  
  1         49  
14 1     1   1045 use JSON;
  1         18936  
  1         6  
15 1     1   1018 use Encode;
  1         12232  
  1         431  
16              
17             has routes => (
18             is => 'rw',
19             predicate => 'has_routes',
20             required => 1,
21             isa => sub {
22             # must be hash
23             die 'Routes must be a HASH ref.' unless ref $_[0] eq 'HASH';
24              
25             # validate each route
26             while (my ($key, $value) = each %{ $_[0] }) {
27             # must match simple path
28             die 'Routes must be of the form qr{^/\w+/?}' if $key !~ m{^/\w+/?$};
29             # must map to a coderef
30             die 'route must map to CODE ref.' unless ref $value eq 'CODE';
31             }
32             },
33             );
34              
35             sub dispatch_request {
36              
37             sub (POST + /*) {
38 4     4   1002 my ( $self, $path ) = @_;
39              
40             # only pass along the request if it matches a given path
41 4 50 33     78 return if ! $self->has_routes || ! $self->routes->{ "/$path" };
42              
43             # catch the payload
44             sub (%payload=) {
45 3         834 my ( $self, $payload ) = @_;
46 3         4 my $response;
47              
48             try {
49             # encode multibyte
50 3         71 $payload = encode_utf8 $payload;
51              
52             # deserialize
53 3         42 my $json = decode_json $payload;
54              
55             # callback
56 2         39 $self->routes->{ "/$path" }->( $json );
57             }
58             catch {
59             # malformed JSON string, neither array, object, number, string or atom, at character offset 0 ?
60             # you are trying to POST non JSON data. don't do that.
61 1         23 warn "Caught exception: /$path: attempted to trigger callback but failed:\n$_";
62              
63             # override the default 200 OK
64 1         54 $response = [ 400, [ 'Content-type' => 'text/plain' ], ['Bad Request'] ];
65 3         18 };
66              
67             # return catch response if set
68 3 100       1162 return $response if $response;
69              
70 2         11 $response = [ 200, [ 'Content-type' => 'text/plain' ], ['OK'] ];
71             }
72 4         617 },
73 7     7 0 76960 }
74              
75             1;
76              
77             __END__