experimental upload support
[catagits/Web-Simple.git] / lib / Web / Dispatch / Predicates.pm
CommitLineData
d63bcdae 1package Web::Dispatch::Predicates;
2
3use strictures 1;
4use base qw(Exporter);
5
5ba2eb68 6our @EXPORT = qw(
ce573717 7 match_and match_or match_not match_method match_path match_path_strip
05aafc1a 8 match_extension match_query match_body match_uploads
5ba2eb68 9);
d63bcdae 10
11sub match_and {
12 my @match = @_;
13 sub {
14 my ($env) = @_;
15 my $my_env = { %$env };
16 my $new_env;
17 my @got;
18 foreach my $match (@match) {
19 if (my @this_got = $match->($my_env)) {
4ed4fb42 20 my %change_env = %{shift(@this_got)};
21 @{$my_env}{keys %change_env} = values %change_env;
22 @{$new_env}{keys %change_env} = values %change_env;
23 push @got, @this_got;
d63bcdae 24 } else {
4ed4fb42 25 return;
d63bcdae 26 }
27 }
28 return ($new_env, @got);
29 }
30}
31
32sub match_or {
33 my @match = @_;
34 sub {
35 foreach my $try (@match) {
36 if (my @ret = $try->(@_)) {
37 return @ret;
38 }
39 }
40 return;
41 }
42}
43
ce573717 44sub match_not {
45 my ($match) = @_;
46 sub {
47 if (my @discard = $match->($_[0])) {
48 ();
49 } else {
50 ({});
51 }
52 }
53}
54
d63bcdae 55sub match_method {
56 my ($method) = @_;
57 sub {
58 my ($env) = @_;
59 $env->{REQUEST_METHOD} eq $method ? {} : ()
60 }
61}
62
63sub match_path {
64 my ($re) = @_;
65 sub {
66 my ($env) = @_;
67 if (my @cap = ($env->{PATH_INFO} =~ /$re/)) {
68 $cap[0] = {}; return @cap;
69 }
70 return;
71 }
72}
73
74sub match_path_strip {
75 my ($re) = @_;
76 sub {
77 my ($env) = @_;
78 if (my @cap = ($env->{PATH_INFO} =~ /$re/)) {
79 $cap[0] = {
4ed4fb42 80 SCRIPT_NAME => ($env->{SCRIPT_NAME}||'').$cap[0],
81 PATH_INFO => pop(@cap),
d63bcdae 82 };
83 return @cap;
84 }
85 return;
86 }
87}
88
5ba2eb68 89sub match_extension {
90 my ($extension) = @_;
91 my $wild = (!$extension or $extension eq '*');
92 my $re = $wild
93 ? qr/\.(\w+)$/
94 : qr/\.(\Q${extension}\E)$/;
95 sub {
96 if ($_[0]->{PATH_INFO} =~ $re) {
97 ($wild ? ({}, $1) : {});
98 } else {
99 ();
100 }
101 };
102}
103
b6bf9ed3 104sub match_query {
05aafc1a 105 _param_matcher(query => $_[0]);
b6bf9ed3 106}
107
108sub match_body {
05aafc1a 109 _param_matcher(body => $_[0]);
110}
111
112sub match_uploads {
113 _param_matcher(uploads => $_[0]);
114}
115
116sub _param_matcher {
117 my ($type, $spec) = @_;
b6bf9ed3 118 require Web::Dispatch::ParamParser;
05aafc1a 119 my $unpack = Web::Dispatch::ParamParser->can("get_unpacked_${type}_from");
b6bf9ed3 120 sub {
05aafc1a 121 _extract_params($unpack->($_[0]), $spec)
b6bf9ed3 122 };
123}
124
052bdd54 125sub _extract_params {
126 my ($raw, $spec) = @_;
127 foreach my $name (@{$spec->{required}||[]}) {
128 return unless exists $raw->{$name};
129 }
130 my @ret = (
131 {},
132 map {
133 $_->{multi} ? $raw->{$_->{name}}||[] : $raw->{$_->{name}}->[-1]
134 } @{$spec->{positional}||[]}
135 );
136 # separated since 'or' is short circuit
137 my ($named, $star) = ($spec->{named}, $spec->{star});
138 if ($named or $star) {
139 my %kw;
140 if ($star) {
141 @kw{keys %$raw} = (
142 $star->{multi}
143 ? values %$raw
144 : map $_->[-1], values %$raw
145 );
146 }
147 foreach my $n (@{$named||[]}) {
148 next if !$n->{multi} and !exists $raw->{$n->{name}};
149 $kw{$n->{name}} =
150 $n->{multi} ? $raw->{$n->{name}}||[] : $raw->{$n->{name}}->[-1];
151 }
152 push @ret, \%kw;
153 }
154 @ret;
155}
156
d63bcdae 1571;