| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Web::Machine::FSM::States; |
|
2
|
|
|
|
|
|
|
BEGIN { |
|
3
|
13
|
|
|
13
|
|
453
|
$Web::Machine::FSM::States::AUTHORITY = 'cpan:STEVAN'; |
|
4
|
|
|
|
|
|
|
} |
|
5
|
|
|
|
|
|
|
# ABSTRACT: The States for Web Machine |
|
6
|
|
|
|
|
|
|
$Web::Machine::FSM::States::VERSION = '0.15'; |
|
7
|
13
|
|
|
13
|
|
217
|
use strict; |
|
|
13
|
|
|
|
|
29
|
|
|
|
13
|
|
|
|
|
565
|
|
|
8
|
13
|
|
|
13
|
|
69
|
use warnings; |
|
|
13
|
|
|
|
|
23
|
|
|
|
13
|
|
|
|
|
367
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
13
|
|
|
13
|
|
71
|
use B (); |
|
|
13
|
|
|
|
|
25
|
|
|
|
13
|
|
|
|
|
202
|
|
|
11
|
13
|
|
|
13
|
|
66
|
use Hash::MultiValue; |
|
|
13
|
|
|
|
|
31
|
|
|
|
13
|
|
|
|
|
315
|
|
|
12
|
|
|
|
|
|
|
|
|
13
|
13
|
|
|
13
|
|
97
|
use Carp qw[ confess ]; |
|
|
13
|
|
|
|
|
24
|
|
|
|
13
|
|
|
|
|
1056
|
|
|
14
|
|
|
|
|
|
|
|
|
15
|
13
|
|
|
|
|
121
|
use Web::Machine::Util qw[ |
|
16
|
|
|
|
|
|
|
first |
|
17
|
|
|
|
|
|
|
pair_key |
|
18
|
|
|
|
|
|
|
pair_value |
|
19
|
|
|
|
|
|
|
create_header |
|
20
|
13
|
|
|
13
|
|
2820
|
]; |
|
|
13
|
|
|
|
|
30
|
|
|
21
|
13
|
|
|
|
|
106
|
use Web::Machine::Util::BodyEncoding qw[ |
|
22
|
|
|
|
|
|
|
encode_body_if_set |
|
23
|
|
|
|
|
|
|
encode_body |
|
24
|
13
|
|
|
13
|
|
22604
|
]; |
|
|
13
|
|
|
|
|
48
|
|
|
25
|
13
|
|
|
|
|
184
|
use Web::Machine::Util::ContentNegotiation qw[ |
|
26
|
|
|
|
|
|
|
choose_media_type |
|
27
|
|
|
|
|
|
|
match_acceptable_media_type |
|
28
|
|
|
|
|
|
|
choose_language |
|
29
|
|
|
|
|
|
|
choose_charset |
|
30
|
|
|
|
|
|
|
choose_encoding |
|
31
|
13
|
|
|
13
|
|
15501
|
]; |
|
|
13
|
|
|
|
|
50
|
|
|
32
|
|
|
|
|
|
|
|
|
33
|
13
|
|
|
|
|
130
|
use Sub::Exporter -setup => { |
|
34
|
|
|
|
|
|
|
exports => [qw[ |
|
35
|
|
|
|
|
|
|
start_state |
|
36
|
|
|
|
|
|
|
is_status_code |
|
37
|
|
|
|
|
|
|
is_new_state |
|
38
|
|
|
|
|
|
|
get_state_name |
|
39
|
|
|
|
|
|
|
get_state_desc |
|
40
|
|
|
|
|
|
|
]] |
|
41
|
13
|
|
|
13
|
|
9152
|
}; |
|
|
13
|
|
|
|
|
27
|
|
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
my %STATE_DESC; |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# my exports ... |
|
46
|
|
|
|
|
|
|
|
|
47
|
123
|
|
|
123
|
0
|
496
|
sub start_state { \&b13 } |
|
48
|
2741
|
|
|
2741
|
0
|
13345
|
sub is_status_code { ref $_[0] eq 'SCALAR' } |
|
49
|
2433
|
|
|
2433
|
0
|
8849
|
sub is_new_state { ref $_[0] eq 'CODE' } |
|
50
|
1766
|
|
|
1766
|
0
|
13366
|
sub get_state_name { B::svref_2object( shift )->GV->NAME } |
|
51
|
0
|
0
|
|
0
|
0
|
0
|
sub get_state_desc { $STATE_DESC{ ref $_[0] ? get_state_name( shift ) : shift } } |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# some utilities ... |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub _unquote_header { |
|
56
|
26
|
|
|
26
|
|
624
|
my $value = shift; |
|
57
|
26
|
50
|
|
|
|
97
|
if ( $value =~ /^"(.*)"$/ ) { |
|
58
|
0
|
|
|
|
|
0
|
return $1; |
|
59
|
|
|
|
|
|
|
} |
|
60
|
26
|
|
|
|
|
124
|
return $value; |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub _ensure_quoted_header { |
|
64
|
7
|
|
|
7
|
|
10
|
my $value = shift; |
|
65
|
7
|
50
|
|
|
|
29
|
return $value if $value =~ /^"(.*)"$/; |
|
66
|
7
|
|
|
|
|
33
|
return '"' . $value . '"'; |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub _get_acceptable_content_type_handler { |
|
70
|
12
|
|
|
12
|
|
31
|
my ($resource, $request) = @_; |
|
71
|
12
|
|
100
|
|
|
44
|
my $acceptable = match_acceptable_media_type( |
|
72
|
|
|
|
|
|
|
($request->header('Content-Type') || 'application/octet-stream'), |
|
73
|
|
|
|
|
|
|
$resource->content_types_accepted |
|
74
|
|
|
|
|
|
|
); |
|
75
|
12
|
100
|
|
|
|
101
|
return \415 unless $acceptable; |
|
76
|
10
|
|
|
|
|
49
|
return pair_value( $acceptable ); |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub _add_caching_headers { |
|
80
|
43
|
|
|
43
|
|
78
|
my ($resource, $response) = @_; |
|
81
|
43
|
100
|
|
|
|
360
|
if ( my $etag = $resource->generate_etag ) { |
|
82
|
7
|
|
|
|
|
47
|
$response->header( 'Etag' => _ensure_quoted_header( $etag ) ); |
|
83
|
|
|
|
|
|
|
} |
|
84
|
43
|
50
|
|
|
|
500
|
if ( my $expires = $resource->expires ) { |
|
85
|
0
|
|
|
|
|
0
|
$response->header( 'Expires' => $expires ); |
|
86
|
|
|
|
|
|
|
} |
|
87
|
43
|
100
|
|
|
|
243
|
if ( my $modified = $resource->last_modified ) { |
|
88
|
7
|
|
|
|
|
2199
|
$response->header( 'Last-Modified' => $modified ); |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
} |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
sub _handle_304 { |
|
93
|
7
|
|
|
7
|
|
250
|
my ($resource, $response) = @_; |
|
94
|
7
|
|
|
|
|
29
|
$response->headers->remove_header('Content-Type'); |
|
95
|
7
|
|
|
|
|
177
|
$response->headers->remove_header('Content-Encoding'); |
|
96
|
7
|
|
|
|
|
129
|
$response->headers->remove_header('Content-Language'); |
|
97
|
7
|
|
|
|
|
116
|
_add_caching_headers($resource, $response); |
|
98
|
7
|
|
|
|
|
340
|
return \304; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub _is_redirect { |
|
102
|
10
|
|
|
10
|
|
22
|
my ($response) = @_; |
|
103
|
|
|
|
|
|
|
# NOTE: |
|
104
|
|
|
|
|
|
|
# this makes a guess that the user has |
|
105
|
|
|
|
|
|
|
# told the Plack::Response that they |
|
106
|
|
|
|
|
|
|
# want to redirect. We do this based |
|
107
|
|
|
|
|
|
|
# on the fact that the ->redirect method |
|
108
|
|
|
|
|
|
|
# will set the status, while in almost all |
|
109
|
|
|
|
|
|
|
# other cases the status of the response |
|
110
|
|
|
|
|
|
|
# will not be set yet. |
|
111
|
|
|
|
|
|
|
# - SL |
|
112
|
10
|
100
|
|
|
|
207
|
return 1 if $response->status; |
|
113
|
7
|
|
|
|
|
55
|
return; |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub _metadata { |
|
117
|
344
|
|
|
344
|
|
505
|
my ($request) = @_; |
|
118
|
344
|
|
|
|
|
1197
|
return $request->env->{'web.machine.context'}; |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
## States |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
$STATE_DESC{'b13'} = 'service_available'; |
|
124
|
|
|
|
|
|
|
sub b13 { |
|
125
|
123
|
|
|
123
|
0
|
265
|
my ($resource, $request, $response) = @_; |
|
126
|
123
|
100
|
|
|
|
949
|
$resource->service_available ? \&b12 : \503; |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
$STATE_DESC{'b12'} = 'known_method'; |
|
130
|
|
|
|
|
|
|
sub b12 { |
|
131
|
121
|
|
|
121
|
0
|
258
|
my ($resource, $request, $response) = @_; |
|
132
|
121
|
|
|
|
|
557
|
my $method = $request->method; |
|
133
|
121
|
100
|
|
|
|
932
|
(grep { $method eq $_ } @{ $resource->known_methods }) ? \&b11 : \501; |
|
|
948
|
|
|
|
|
1670
|
|
|
|
121
|
|
|
|
|
872
|
|
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
$STATE_DESC{'b11'} = 'uri_too_long'; |
|
137
|
|
|
|
|
|
|
sub b11 { |
|
138
|
120
|
|
|
120
|
0
|
409
|
my ($resource, $request, $response) = @_; |
|
139
|
120
|
100
|
|
|
|
582
|
$resource->uri_too_long( $request->uri ) ? \414 : \&b10; |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
$STATE_DESC{'b10'} = 'method_allowed'; |
|
143
|
|
|
|
|
|
|
sub b10 { |
|
144
|
119
|
|
|
119
|
0
|
295
|
my ($resource, $request, $response) = @_; |
|
145
|
119
|
|
|
|
|
498
|
my $method = $request->method; |
|
146
|
119
|
100
|
|
|
|
868
|
return \&b9 if grep { $method eq $_ } @{ $resource->allowed_methods }; |
|
|
288
|
|
|
|
|
1154
|
|
|
|
119
|
|
|
|
|
714
|
|
|
147
|
1
|
|
|
|
|
3
|
$response->header('Allow' => join ", " => @{ $resource->allowed_methods } ); |
|
|
1
|
|
|
|
|
5
|
|
|
148
|
1
|
|
|
|
|
74
|
return \405; |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
$STATE_DESC{'b9'} = 'malformed_request'; |
|
152
|
|
|
|
|
|
|
sub b9 { |
|
153
|
118
|
|
|
118
|
0
|
253
|
my ($resource, $request, $response) = @_; |
|
154
|
118
|
100
|
|
|
|
801
|
$resource->malformed_request ? \400 : \&b8; |
|
155
|
|
|
|
|
|
|
} |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
$STATE_DESC{'b8'} = 'is_authorized'; |
|
158
|
|
|
|
|
|
|
sub b8 { |
|
159
|
117
|
|
|
117
|
0
|
263
|
my ($resource, $request, $response) = @_; |
|
160
|
117
|
|
|
|
|
563
|
my $result = $resource->is_authorized( $request->header('Authorization') ); |
|
161
|
|
|
|
|
|
|
# if we get back a status, then use it |
|
162
|
117
|
100
|
100
|
|
|
617
|
if ( is_status_code( $result ) ) { |
|
|
|
100
|
|
|
|
|
|
|
163
|
1
|
|
|
|
|
6
|
return $result; |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
# if we just get back true, then |
|
166
|
|
|
|
|
|
|
# move onto the next state |
|
167
|
|
|
|
|
|
|
elsif ( defined $result && "$result" eq "1" ) { |
|
168
|
113
|
|
|
|
|
457
|
return \&b7 |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
# anything else will either be |
|
171
|
|
|
|
|
|
|
# a WWW-Authenticate header or |
|
172
|
|
|
|
|
|
|
# a simple false value |
|
173
|
|
|
|
|
|
|
else { |
|
174
|
3
|
100
|
|
|
|
11
|
if ( $result ) { |
|
175
|
1
|
|
|
|
|
7
|
$response->header( 'WWW-Authenticate' => $result ); |
|
176
|
|
|
|
|
|
|
} |
|
177
|
3
|
|
|
|
|
57
|
return \401; |
|
178
|
|
|
|
|
|
|
} |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
$STATE_DESC{'b7'} = 'forbidden'; |
|
182
|
|
|
|
|
|
|
sub b7 { |
|
183
|
113
|
|
|
113
|
0
|
341
|
my ($resource, $request, $response) = @_; |
|
184
|
113
|
100
|
|
|
|
776
|
$resource->forbidden ? \403 : \&b6; |
|
185
|
|
|
|
|
|
|
} |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
$STATE_DESC{'b6'} = 'content_headers_okay'; |
|
188
|
|
|
|
|
|
|
sub b6 { |
|
189
|
111
|
|
|
111
|
0
|
303
|
my ($resource, $request, $response) = @_; |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
# FIX-ME |
|
192
|
|
|
|
|
|
|
# there is a better way to do this, |
|
193
|
|
|
|
|
|
|
# also, HTTP::Headers will usually |
|
194
|
|
|
|
|
|
|
# group things into arrays, so we |
|
195
|
|
|
|
|
|
|
# can either avoid or better take |
|
196
|
|
|
|
|
|
|
# advantage of Hash::MultiValue. |
|
197
|
|
|
|
|
|
|
# But we are almost certainly not |
|
198
|
|
|
|
|
|
|
# handling that case properly maybe. |
|
199
|
111
|
|
|
|
|
1100
|
my $content_headers = Hash::MultiValue->new; |
|
200
|
|
|
|
|
|
|
$request->headers->scan(sub { |
|
201
|
155
|
|
|
155
|
|
3398
|
my ($name, $value) = @_; |
|
202
|
155
|
100
|
|
|
|
969
|
$content_headers->add( $name, $value ) if (lc $name) =~ /^content-/; |
|
203
|
111
|
|
|
|
|
5452
|
}); |
|
204
|
|
|
|
|
|
|
|
|
205
|
111
|
100
|
|
|
|
3540
|
$resource->valid_content_headers( $content_headers ) ? \&b5 : \501; |
|
206
|
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
$STATE_DESC{'b5'} = 'known_content_type'; |
|
209
|
|
|
|
|
|
|
sub b5 { |
|
210
|
110
|
|
|
110
|
0
|
280
|
my ($resource, $request, $response) = @_; |
|
211
|
110
|
100
|
|
|
|
801
|
$resource->known_content_type( $request->content_type ) ? \&b4 : \415; |
|
212
|
|
|
|
|
|
|
} |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
$STATE_DESC{'b4'} = 'request_entity_too_large'; |
|
215
|
|
|
|
|
|
|
sub b4 { |
|
216
|
109
|
|
|
109
|
0
|
243
|
my ($resource, $request, $response) = @_; |
|
217
|
109
|
100
|
|
|
|
459
|
$resource->valid_entity_length( $request->content_length ) ? \&b3 : \413; |
|
218
|
|
|
|
|
|
|
} |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
$STATE_DESC{'b3'} = 'method_is_options'; |
|
221
|
|
|
|
|
|
|
sub b3 { |
|
222
|
108
|
|
|
108
|
0
|
229
|
my ($resource, $request, $response) = @_; |
|
223
|
108
|
100
|
|
|
|
378
|
if ( $request->method eq 'OPTIONS' ) { |
|
224
|
1
|
|
|
|
|
10
|
$response->headers( $resource->options ); |
|
225
|
1
|
|
|
|
|
73
|
return \200; |
|
226
|
|
|
|
|
|
|
} |
|
227
|
107
|
|
|
|
|
1232
|
return \&c3 |
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
$STATE_DESC{'c3'} = 'accept_header_exists'; |
|
231
|
|
|
|
|
|
|
sub c3 { |
|
232
|
107
|
|
|
107
|
0
|
230
|
my ($resource, $request, $response) = @_; |
|
233
|
107
|
|
|
|
|
374
|
my $metadata = _metadata($request); |
|
234
|
107
|
100
|
|
|
|
813
|
if ( !$request->header('Accept') ) { |
|
235
|
95
|
|
|
|
|
3566
|
$metadata->{'Content-Type'} = create_header( MediaType => ( |
|
236
|
|
|
|
|
|
|
pair_key( $resource->content_types_provided->[0] ) |
|
237
|
|
|
|
|
|
|
)); |
|
238
|
95
|
|
|
|
|
237183
|
return \&d4 |
|
239
|
|
|
|
|
|
|
} |
|
240
|
12
|
|
|
|
|
1660
|
return \&c4; |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
$STATE_DESC{'c4'} = 'acceptable_media_type_available'; |
|
244
|
|
|
|
|
|
|
sub c4 { |
|
245
|
12
|
|
|
12
|
0
|
31
|
my ($resource, $request, $response) = @_; |
|
246
|
12
|
|
|
|
|
24
|
my $metadata = _metadata($request); |
|
247
|
|
|
|
|
|
|
|
|
248
|
12
|
|
|
|
|
62
|
my @types = map { pair_key( $_ ) } @{ $resource->content_types_provided }; |
|
|
13
|
|
|
|
|
133
|
|
|
|
12
|
|
|
|
|
44
|
|
|
249
|
|
|
|
|
|
|
|
|
250
|
12
|
100
|
|
|
|
74
|
if ( my $chosen_type = choose_media_type( \@types, $request->header('Accept') ) ) { |
|
251
|
11
|
|
|
|
|
2702
|
$metadata->{'Content-Type'} = $chosen_type; |
|
252
|
11
|
|
|
|
|
51
|
return \&d4; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
1
|
|
|
|
|
245
|
return \406; |
|
256
|
|
|
|
|
|
|
} |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
$STATE_DESC{'d4'} = 'accept_language_header_exists'; |
|
259
|
|
|
|
|
|
|
sub d4 { |
|
260
|
106
|
|
|
106
|
0
|
369
|
my ($resource, $request, $response) = @_; |
|
261
|
106
|
100
|
|
|
|
429
|
(not $request->header('Accept-Language')) ? \&e5 : \&d5; |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
$STATE_DESC{'d5'} = 'accept_language_choice_available'; |
|
266
|
|
|
|
|
|
|
sub d5 { |
|
267
|
17
|
|
|
17
|
0
|
41
|
my ($resource, $request, $response) = @_; |
|
268
|
17
|
|
|
|
|
33
|
my $metadata = _metadata($request); |
|
269
|
|
|
|
|
|
|
|
|
270
|
17
|
100
|
|
|
|
113
|
if ( my $language = choose_language( $resource->languages_provided, $request->header('Accept-Language') ) ) { |
|
271
|
15
|
|
|
|
|
1844
|
$metadata->{'Language'} = $language; |
|
272
|
|
|
|
|
|
|
# handle the short circuit here ... |
|
273
|
15
|
100
|
|
|
|
92
|
$response->header( 'Content-Language' => $language ) if "$language" ne "1"; |
|
274
|
15
|
|
|
|
|
662
|
return \&e5; |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
|
|
277
|
2
|
|
|
|
|
341
|
return \406; |
|
278
|
|
|
|
|
|
|
} |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
$STATE_DESC{'e5'} = 'accept_charset_exists'; |
|
281
|
|
|
|
|
|
|
sub e5 { |
|
282
|
104
|
|
|
104
|
0
|
245
|
my ($resource, $request, $response) = @_; |
|
283
|
104
|
100
|
|
|
|
382
|
(not $request->header('Accept-Charset')) ? \&f6 : \&e6; |
|
284
|
|
|
|
|
|
|
} |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
$STATE_DESC{'e6'} = 'accept_charset_choice_available'; |
|
287
|
|
|
|
|
|
|
sub e6 { |
|
288
|
22
|
|
|
22
|
0
|
45
|
my ($resource, $request, $response) = @_; |
|
289
|
22
|
|
|
|
|
53
|
my $metadata = _metadata($request); |
|
290
|
|
|
|
|
|
|
|
|
291
|
22
|
100
|
|
|
|
161
|
if ( my $charset = choose_charset( $resource->charsets_provided, $request->header('Accept-Charset') ) ) { |
|
292
|
|
|
|
|
|
|
# handle the short circuit here ... |
|
293
|
20
|
50
|
|
|
|
8376
|
$metadata->{'Charset'} = $charset if "$charset" ne "1"; |
|
294
|
20
|
|
|
|
|
88
|
return \&f6; |
|
295
|
|
|
|
|
|
|
} |
|
296
|
|
|
|
|
|
|
|
|
297
|
2
|
|
|
|
|
864
|
return \406; |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
$STATE_DESC{'f6'} = 'accept_encoding_exists'; |
|
301
|
|
|
|
|
|
|
# (also, set content-type header here, now that charset is chosen) |
|
302
|
|
|
|
|
|
|
sub f6 { |
|
303
|
102
|
|
|
102
|
0
|
276
|
my ($resource, $request, $response) = @_; |
|
304
|
102
|
|
|
|
|
237
|
my $metadata = _metadata($request); |
|
305
|
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
# If the client doesn't provide an Accept-Charset header we should just |
|
307
|
|
|
|
|
|
|
# encode with the default. |
|
308
|
102
|
100
|
100
|
|
|
1107
|
if ( $resource->default_charset && !$request->header('Accept-Charset') ) { |
|
309
|
4
|
|
|
|
|
180
|
my $default = $resource->default_charset; |
|
310
|
4
|
100
|
|
|
|
37
|
$metadata->{'Charset'} = ref $default ? pair_key($default) : $default; |
|
311
|
|
|
|
|
|
|
} |
|
312
|
|
|
|
|
|
|
|
|
313
|
102
|
100
|
|
|
|
1424
|
if ( my $charset = $metadata->{'Charset'} ) { |
|
314
|
|
|
|
|
|
|
# Add the charset to the content type now ... |
|
315
|
24
|
|
|
|
|
145
|
$metadata->{'Content-Type'}->add_param( 'charset' => $charset ); |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
# put the content type in the header now ... |
|
318
|
102
|
|
|
|
|
1123
|
$response->header( 'Content-Type' => $metadata->{'Content-Type'}->as_string ); |
|
319
|
|
|
|
|
|
|
|
|
320
|
102
|
100
|
|
|
|
9905
|
if ( $request->header('Accept-Encoding') ) { |
|
321
|
13
|
|
|
|
|
1464
|
return \&f7 |
|
322
|
|
|
|
|
|
|
} |
|
323
|
|
|
|
|
|
|
else { |
|
324
|
89
|
100
|
|
|
|
3295
|
if ( my $encoding = choose_encoding( $resource->encodings_provided, "identity;q=1.0,*;q=0.5" ) ) { |
|
325
|
85
|
100
|
|
|
|
62004
|
$response->header( 'Content-Encoding' => $encoding ) unless $encoding eq 'identity'; |
|
326
|
85
|
|
|
|
|
1149
|
$metadata->{'Content-Encoding'} = $encoding; |
|
327
|
85
|
|
|
|
|
436
|
return \&g7; |
|
328
|
|
|
|
|
|
|
} |
|
329
|
|
|
|
|
|
|
else { |
|
330
|
4
|
|
|
|
|
59
|
return \406; |
|
331
|
|
|
|
|
|
|
} |
|
332
|
|
|
|
|
|
|
} |
|
333
|
|
|
|
|
|
|
} |
|
334
|
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
$STATE_DESC{'f7'} = 'accept_encoding_choice_available'; |
|
336
|
|
|
|
|
|
|
sub f7 { |
|
337
|
13
|
|
|
13
|
0
|
32
|
my ($resource, $request, $response) = @_; |
|
338
|
13
|
|
|
|
|
31
|
my $metadata = _metadata($request); |
|
339
|
|
|
|
|
|
|
|
|
340
|
13
|
100
|
|
|
|
99
|
if ( my $encoding = choose_encoding( $resource->encodings_provided, $request->header('Accept-Encoding') ) ) { |
|
341
|
9
|
100
|
|
|
|
1256
|
$response->header( 'Content-Encoding' => $encoding ) unless $encoding eq 'identity'; |
|
342
|
9
|
|
|
|
|
343
|
$metadata->{'Content-Encoding'} = $encoding; |
|
343
|
9
|
|
|
|
|
35
|
return \&g7; |
|
344
|
|
|
|
|
|
|
} |
|
345
|
|
|
|
|
|
|
|
|
346
|
4
|
|
|
|
|
72
|
return \406; |
|
347
|
|
|
|
|
|
|
} |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
$STATE_DESC{'g7'} = 'resource_exists'; |
|
350
|
|
|
|
|
|
|
sub g7 { |
|
351
|
94
|
|
|
94
|
0
|
231
|
my ($resource, $request, $response) = @_; |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
# NOTE: |
|
354
|
|
|
|
|
|
|
# set Vary header here since we are |
|
355
|
|
|
|
|
|
|
# done with content negotiation |
|
356
|
|
|
|
|
|
|
# - SL |
|
357
|
94
|
|
|
|
|
174
|
my @variances = @{ $resource->variances }; |
|
|
94
|
|
|
|
|
710
|
|
|
358
|
|
|
|
|
|
|
|
|
359
|
94
|
100
|
|
|
|
186
|
push @variances => 'Accept' if scalar @{ $resource->content_types_provided } > 1; |
|
|
94
|
|
|
|
|
329
|
|
|
360
|
94
|
100
|
|
|
|
968
|
push @variances => 'Accept-Encoding' if scalar keys %{ $resource->encodings_provided } > 1; |
|
|
94
|
|
|
|
|
309
|
|
|
361
|
94
|
100
|
66
|
|
|
800
|
push @variances => 'Accept-Charset' if defined $resource->charsets_provided && scalar @{ $resource->charsets_provided } > 1; |
|
|
94
|
|
|
|
|
736
|
|
|
362
|
94
|
100
|
|
|
|
933
|
push @variances => 'Accept-Language' if scalar @{ $resource->languages_provided } > 1; |
|
|
94
|
|
|
|
|
391
|
|
|
363
|
|
|
|
|
|
|
|
|
364
|
94
|
100
|
|
|
|
579
|
$response->header( 'Vary' => join ', ' => @variances ) if @variances; |
|
365
|
|
|
|
|
|
|
|
|
366
|
94
|
100
|
|
|
|
1509
|
$resource->resource_exists ? \&g8 : \&h7; |
|
367
|
|
|
|
|
|
|
} |
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
$STATE_DESC{'g8'} = 'if_match_exists'; |
|
370
|
|
|
|
|
|
|
sub g8 { |
|
371
|
58
|
|
|
58
|
0
|
135
|
my ($resource, $request, $response) = @_; |
|
372
|
58
|
100
|
|
|
|
255
|
$request->header('If-Match') ? \&g9 : \&h10; |
|
373
|
|
|
|
|
|
|
} |
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
$STATE_DESC{'g9'} = 'if_match_is_wildcard'; |
|
376
|
|
|
|
|
|
|
sub g9 { |
|
377
|
3
|
|
|
3
|
0
|
6
|
my ($resource, $request, $response) = @_; |
|
378
|
3
|
100
|
|
|
|
12
|
_unquote_header( $request->header('If-Match') ) eq "*" ? \&h10 : \&g11; |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
$STATE_DESC{'g11'} = 'etag_in_if_match_list'; |
|
382
|
|
|
|
|
|
|
sub g11 { |
|
383
|
2
|
|
|
2
|
0
|
4
|
my ($resource, $request, $response) = @_; |
|
384
|
2
|
|
|
|
|
10
|
my @etags = map { _unquote_header( $_ ) } split /\s*\,\s*/ => $request->header('If-Match'); |
|
|
2
|
|
|
|
|
62
|
|
|
385
|
2
|
|
|
|
|
8
|
my $etag = $resource->generate_etag; |
|
386
|
2
|
100
|
|
|
|
10
|
(grep { $etag eq $_ } @etags) ? \&h10 : \412; |
|
|
2
|
|
|
|
|
13
|
|
|
387
|
|
|
|
|
|
|
} |
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
$STATE_DESC{'h7'} = 'if_match_exists_and_if_match_is_wildcard'; |
|
390
|
|
|
|
|
|
|
sub h7 { |
|
391
|
36
|
|
|
36
|
0
|
70
|
my ($resource, $request, $response) = @_; |
|
392
|
36
|
100
|
100
|
|
|
140
|
($request->header('If-Match') && _unquote_header( $request->header('If-Match') ) eq "*") ? \412 : \&i7; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
$STATE_DESC{'h10'} = 'if_unmodified_since_exists'; |
|
396
|
|
|
|
|
|
|
sub h10 { |
|
397
|
57
|
|
|
57
|
0
|
136
|
my ($resource, $request, $response) = @_; |
|
398
|
57
|
100
|
|
|
|
195
|
$request->header('If-Unmodified-Since') ? \&h11 : \&i12; |
|
399
|
|
|
|
|
|
|
} |
|
400
|
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
$STATE_DESC{'h11'} = 'if_unmodified_since_is_valid_date'; |
|
402
|
|
|
|
|
|
|
sub h11 { |
|
403
|
6
|
|
|
6
|
0
|
16
|
my ($resource, $request, $response) = @_; |
|
404
|
6
|
|
|
|
|
13
|
my $metadata = _metadata($request); |
|
405
|
6
|
50
|
|
|
|
36
|
if ( my $date = $request->header('If-Unmodified-Since') ) { |
|
406
|
6
|
|
|
|
|
414
|
$metadata->{'If-Unmodified-Since'} = $date; |
|
407
|
6
|
|
|
|
|
21
|
return \&h12; |
|
408
|
|
|
|
|
|
|
} |
|
409
|
0
|
|
|
|
|
0
|
return \&i12; |
|
410
|
|
|
|
|
|
|
} |
|
411
|
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
$STATE_DESC{'h12'} = 'last_modified_is_greater_than_if_unmodified_since'; |
|
413
|
|
|
|
|
|
|
sub h12 { |
|
414
|
6
|
|
|
6
|
0
|
13
|
my ($resource, $request, $response) = @_; |
|
415
|
6
|
|
|
|
|
11
|
my $metadata = _metadata($request); |
|
416
|
6
|
100
|
66
|
|
|
39
|
defined $resource->last_modified |
|
417
|
|
|
|
|
|
|
&& |
|
418
|
|
|
|
|
|
|
($resource->last_modified->epoch > $metadata->{'If-Unmodified-Since'}->epoch) |
|
419
|
|
|
|
|
|
|
? \412 : \&i12; |
|
420
|
|
|
|
|
|
|
} |
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
$STATE_DESC{'i4'} = 'moved_permanently'; |
|
423
|
|
|
|
|
|
|
sub i4 { |
|
424
|
8
|
|
|
8
|
0
|
16
|
my ($resource, $request, $response) = @_; |
|
425
|
8
|
100
|
|
|
|
51
|
if ( my $uri = $resource->moved_permanently ) { |
|
426
|
2
|
100
|
|
|
|
21
|
if ( is_status_code( $uri ) ) { |
|
427
|
1
|
|
|
|
|
4
|
return $uri; |
|
428
|
|
|
|
|
|
|
} |
|
429
|
1
|
|
|
|
|
7
|
$response->header('Location' => $uri ); |
|
430
|
1
|
|
|
|
|
48
|
return \301; |
|
431
|
|
|
|
|
|
|
} |
|
432
|
6
|
|
|
|
|
21
|
return \&p3; |
|
433
|
|
|
|
|
|
|
} |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
$STATE_DESC{'i7'} = 'method_is_put'; |
|
436
|
|
|
|
|
|
|
sub i7 { |
|
437
|
30
|
|
|
30
|
0
|
67
|
my ($resource, $request, $response) = @_; |
|
438
|
30
|
100
|
|
|
|
103
|
$request->method eq 'PUT' ? \&i4 : \&k7 |
|
439
|
|
|
|
|
|
|
} |
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
$STATE_DESC{'i12'} = 'if_none_match_exists'; |
|
442
|
|
|
|
|
|
|
sub i12 { |
|
443
|
54
|
|
|
54
|
0
|
134
|
my ($resource, $request, $response) = @_; |
|
444
|
54
|
100
|
|
|
|
206
|
$request->header('If-None-Match') ? \&i13 : \&l13 |
|
445
|
|
|
|
|
|
|
} |
|
446
|
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
$STATE_DESC{'i13'} = 'if_none_match_is_wildcard'; |
|
448
|
|
|
|
|
|
|
sub i13 { |
|
449
|
19
|
|
|
19
|
0
|
43
|
my ($resource, $request, $response) = @_; |
|
450
|
19
|
100
|
|
|
|
61
|
$request->header('If-None-Match') eq "*" ? \&j18 : \&k13 |
|
451
|
|
|
|
|
|
|
} |
|
452
|
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
$STATE_DESC{'j18'} = 'method_is_get_or_head'; |
|
454
|
|
|
|
|
|
|
sub j18 { |
|
455
|
9
|
|
|
9
|
0
|
21
|
my ($resource, $request, $response) = @_; |
|
456
|
9
|
100
|
100
|
|
|
29
|
$request->method eq 'GET' || $request->method eq 'HEAD' |
|
457
|
|
|
|
|
|
|
? _handle_304( $resource, $response ) |
|
458
|
|
|
|
|
|
|
: \412 |
|
459
|
|
|
|
|
|
|
} |
|
460
|
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
$STATE_DESC{'k5'} = 'moved_permanently'; |
|
462
|
|
|
|
|
|
|
sub k5 { |
|
463
|
20
|
|
|
20
|
0
|
95
|
my ($resource, $request, $response) = @_; |
|
464
|
20
|
100
|
|
|
|
170
|
if ( my $uri = $resource->moved_permanently ) { |
|
465
|
2
|
100
|
|
|
|
12
|
if ( is_status_code( $uri ) ) { |
|
466
|
1
|
|
|
|
|
5
|
return $uri; |
|
467
|
|
|
|
|
|
|
} |
|
468
|
1
|
|
|
|
|
4
|
$response->header('Location' => $uri ); |
|
469
|
1
|
|
|
|
|
32
|
return \301; |
|
470
|
|
|
|
|
|
|
} |
|
471
|
18
|
|
|
|
|
253
|
return \&l5; |
|
472
|
|
|
|
|
|
|
} |
|
473
|
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
$STATE_DESC{'k7'} = 'previously_existed'; |
|
475
|
|
|
|
|
|
|
sub k7 { |
|
476
|
22
|
|
|
22
|
0
|
55
|
my ($resource, $request, $response) = @_; |
|
477
|
22
|
100
|
|
|
|
102
|
$resource->previously_existed ? \&k5 : \&l7; |
|
478
|
|
|
|
|
|
|
} |
|
479
|
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
$STATE_DESC{'k13'} = 'etag_in_if_none_match'; |
|
481
|
|
|
|
|
|
|
sub k13 { |
|
482
|
13
|
|
|
13
|
0
|
40
|
my ($resource, $request, $response) = @_; |
|
483
|
13
|
|
|
|
|
55
|
my @etags = map { _unquote_header( $_ ) } split /\s*\,\s*/ => $request->header('If-None-Match'); |
|
|
13
|
|
|
|
|
523
|
|
|
484
|
13
|
|
|
|
|
60
|
my $etag = $resource->generate_etag; |
|
485
|
13
|
100
|
100
|
|
|
174
|
$etag && (grep { $etag eq $_ } @etags) ? \&j18 : \&l13; |
|
486
|
|
|
|
|
|
|
} |
|
487
|
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
$STATE_DESC{'l5'} = 'moved_temporarily'; |
|
489
|
|
|
|
|
|
|
sub l5 { |
|
490
|
18
|
|
|
18
|
0
|
48
|
my ($resource, $request, $response) = @_; |
|
491
|
18
|
100
|
|
|
|
143
|
if ( my $uri = $resource->moved_temporarily ) { |
|
492
|
2
|
100
|
|
|
|
14
|
if ( is_status_code( $uri ) ) { |
|
493
|
1
|
|
|
|
|
3
|
return $uri; |
|
494
|
|
|
|
|
|
|
} |
|
495
|
1
|
|
|
|
|
5
|
$response->header('Location' => $uri ); |
|
496
|
1
|
|
|
|
|
40
|
return \307; |
|
497
|
|
|
|
|
|
|
} |
|
498
|
16
|
|
|
|
|
63
|
return \&m5; |
|
499
|
|
|
|
|
|
|
} |
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
$STATE_DESC{'l7'} = 'method_is_post'; |
|
502
|
|
|
|
|
|
|
sub l7 { |
|
503
|
2
|
|
|
2
|
0
|
5
|
my ($resource, $request, $response) = @_; |
|
504
|
2
|
100
|
|
|
|
7
|
$request->method eq 'POST' ? \&m7 : \404 |
|
505
|
|
|
|
|
|
|
} |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
$STATE_DESC{'l13'} = 'if_modified_since_exists'; |
|
508
|
|
|
|
|
|
|
sub l13 { |
|
509
|
45
|
|
|
45
|
0
|
107
|
my ($resource, $request, $response) = @_; |
|
510
|
45
|
100
|
|
|
|
169
|
$request->header('If-Modified-Since') ? \&l14 : \&m16 |
|
511
|
|
|
|
|
|
|
} |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
$STATE_DESC{'l14'} = 'if_modified_since_is_valid_date'; |
|
514
|
|
|
|
|
|
|
sub l14 { |
|
515
|
9
|
|
|
9
|
0
|
21
|
my ($resource, $request, $response) = @_; |
|
516
|
9
|
|
|
|
|
25
|
my $metadata = _metadata($request); |
|
517
|
9
|
50
|
|
|
|
70
|
if ( my $date = $request->header('If-Modified-Since') ) { |
|
518
|
9
|
|
|
|
|
657
|
$metadata->{'If-Modified-Since'} = $date; |
|
519
|
9
|
|
|
|
|
35
|
return \&l15; |
|
520
|
|
|
|
|
|
|
} |
|
521
|
0
|
|
|
|
|
0
|
return \&m16; |
|
522
|
|
|
|
|
|
|
} |
|
523
|
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
$STATE_DESC{'l15'} = 'if_modified_since_greater_than_now'; |
|
525
|
|
|
|
|
|
|
sub l15 { |
|
526
|
9
|
|
|
9
|
0
|
31
|
my ($resource, $request, $response) = @_; |
|
527
|
9
|
|
|
|
|
21
|
my $metadata = _metadata($request); |
|
528
|
9
|
100
|
|
|
|
76
|
($metadata->{'If-Modified-Since'}->epoch > (scalar time)) ? \&m16 : \&l17; |
|
529
|
|
|
|
|
|
|
} |
|
530
|
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
$STATE_DESC{'l17'} = 'last_modified_is_greater_than_if_modified_since'; |
|
532
|
|
|
|
|
|
|
sub l17 { |
|
533
|
1
|
|
|
1
|
0
|
3
|
my ($resource, $request, $response) = @_; |
|
534
|
1
|
|
|
|
|
2
|
my $metadata = _metadata($request); |
|
535
|
1
|
50
|
33
|
|
|
8
|
defined $resource->last_modified |
|
536
|
|
|
|
|
|
|
&& |
|
537
|
|
|
|
|
|
|
($resource->last_modified->epoch > $metadata->{'If-Modified-Since'}->epoch) |
|
538
|
|
|
|
|
|
|
? \&m16 : _handle_304( $resource, $response ); |
|
539
|
|
|
|
|
|
|
} |
|
540
|
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
$STATE_DESC{'m5'} = 'method_is_post'; |
|
542
|
|
|
|
|
|
|
sub m5 { |
|
543
|
16
|
|
|
16
|
0
|
37
|
my ($resource, $request, $response) = @_; |
|
544
|
16
|
100
|
|
|
|
56
|
$request->method eq 'POST' ? \&n5 : \410 |
|
545
|
|
|
|
|
|
|
} |
|
546
|
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
$STATE_DESC{'m7'} = 'allow_post_to_missing_resource'; |
|
548
|
|
|
|
|
|
|
sub m7 { |
|
549
|
1
|
|
|
1
|
0
|
4
|
my ($resource, $request, $response) = @_; |
|
550
|
1
|
50
|
|
|
|
5
|
$resource->allow_missing_post ? \&n11 : \404 |
|
551
|
|
|
|
|
|
|
} |
|
552
|
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
$STATE_DESC{'m16'} = 'method_is_delete'; |
|
554
|
|
|
|
|
|
|
sub m16 { |
|
555
|
44
|
|
|
44
|
0
|
105
|
my ($resource, $request, $response) = @_; |
|
556
|
44
|
100
|
|
|
|
176
|
$request->method eq 'DELETE' ? \&m20 : \&n16 |
|
557
|
|
|
|
|
|
|
} |
|
558
|
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
$STATE_DESC{'m20'} = 'delete_enacted_immediately'; |
|
560
|
|
|
|
|
|
|
sub m20 { |
|
561
|
4
|
|
|
4
|
0
|
10
|
my ($resource, $request, $response) = @_; |
|
562
|
4
|
100
|
|
|
|
17
|
$resource->delete_resource ? \&m20b : \500 |
|
563
|
|
|
|
|
|
|
} |
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
$STATE_DESC{'m20b'} = 'did_delete_complete'; |
|
566
|
|
|
|
|
|
|
sub m20b { |
|
567
|
3
|
|
|
3
|
0
|
8
|
my ($resource, $request, $response) = @_; |
|
568
|
3
|
100
|
|
|
|
14
|
$resource->delete_completed ? \&o20 : \202 |
|
569
|
|
|
|
|
|
|
} |
|
570
|
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
$STATE_DESC{'n5'} = 'allow_post_to_missing_resource'; |
|
572
|
|
|
|
|
|
|
sub n5 { |
|
573
|
15
|
|
|
15
|
0
|
32
|
my ($resource, $request, $response) = @_; |
|
574
|
15
|
100
|
|
|
|
57
|
$resource->allow_missing_post ? \&n11 : \410 |
|
575
|
|
|
|
|
|
|
} |
|
576
|
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
sub _n11_create_path { |
|
578
|
6
|
|
|
6
|
|
15
|
my ($resource, $request, $response) = @_; |
|
579
|
|
|
|
|
|
|
|
|
580
|
6
|
|
|
|
|
20
|
my $uri = $resource->create_path; |
|
581
|
6
|
100
|
|
|
|
207
|
confess "Create Path Nil" unless $uri; |
|
582
|
5
|
|
66
|
|
|
27
|
my $base_uri = $resource->base_uri || $request->base; |
|
583
|
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
# do a little cleanup |
|
585
|
5
|
50
|
|
|
|
882
|
$base_uri =~ s!/$!! if $uri =~ m!^/!; |
|
586
|
5
|
100
|
33
|
|
|
34
|
$base_uri .= '/' if $uri !~ m!^/! && $base_uri !~ m!/$!; |
|
587
|
5
|
|
|
|
|
51
|
my $new_uri = URI->new( $base_uri . $uri )->canonical; |
|
588
|
|
|
|
|
|
|
# NOTE: |
|
589
|
|
|
|
|
|
|
# the ruby and JS versions will set the path_info |
|
590
|
|
|
|
|
|
|
# for the request object here, but since our requests |
|
591
|
|
|
|
|
|
|
# are immutable, we don't allow that. I don't see |
|
592
|
|
|
|
|
|
|
# where this ends up being useful so I am going to |
|
593
|
|
|
|
|
|
|
# skip it and not bother. |
|
594
|
|
|
|
|
|
|
# - SL |
|
595
|
5
|
|
|
|
|
657
|
$response->header( 'Location' => $new_uri->path_query ); |
|
596
|
|
|
|
|
|
|
} |
|
597
|
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
$STATE_DESC{'n11'} = 'redirect'; |
|
599
|
|
|
|
|
|
|
sub n11 { |
|
600
|
15
|
|
|
15
|
0
|
43
|
my ($resource, $request, $response) = @_; |
|
601
|
15
|
100
|
|
|
|
71
|
if ( $resource->post_is_create ) { |
|
602
|
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
# the default behavior as specified by |
|
604
|
|
|
|
|
|
|
# the Erlang/Ruby versions, however this |
|
605
|
|
|
|
|
|
|
# is a very unpopular "feature" so we are |
|
606
|
|
|
|
|
|
|
# allowing it to be bypassed here. |
|
607
|
6
|
50
|
|
|
|
76
|
_n11_create_path( $resource, $request, $response ) |
|
608
|
|
|
|
|
|
|
if not $resource->create_path_after_handler; |
|
609
|
|
|
|
|
|
|
|
|
610
|
5
|
|
|
|
|
308
|
my $handler = _get_acceptable_content_type_handler( $resource, $request ); |
|
611
|
5
|
100
|
|
|
|
20
|
return $handler if is_status_code( $handler ); |
|
612
|
|
|
|
|
|
|
|
|
613
|
4
|
|
|
|
|
17
|
my $result = $resource->$handler(); |
|
614
|
4
|
100
|
|
|
|
17
|
return $result if is_status_code( $result ); |
|
615
|
|
|
|
|
|
|
|
|
616
|
3
|
50
|
|
|
|
14
|
_n11_create_path( $resource, $request, $response ) |
|
617
|
|
|
|
|
|
|
if $resource->create_path_after_handler; |
|
618
|
|
|
|
|
|
|
} |
|
619
|
|
|
|
|
|
|
else { |
|
620
|
9
|
|
|
|
|
223
|
my $result = $resource->process_post; |
|
621
|
9
|
100
|
|
|
|
227
|
if ( $result ) { |
|
622
|
8
|
100
|
|
|
|
20
|
return $result if is_status_code( $result ); |
|
623
|
7
|
|
|
|
|
52
|
encode_body_if_set( $resource, $response ); |
|
624
|
|
|
|
|
|
|
} |
|
625
|
|
|
|
|
|
|
else { |
|
626
|
1
|
|
|
|
|
370
|
confess "Process Post Invalid"; |
|
627
|
|
|
|
|
|
|
} |
|
628
|
|
|
|
|
|
|
} |
|
629
|
|
|
|
|
|
|
|
|
630
|
10
|
100
|
|
|
|
383
|
if ( _is_redirect( $response ) ) { |
|
631
|
3
|
100
|
|
|
|
193
|
if ( $response->location ) { |
|
632
|
2
|
|
|
|
|
816
|
return \303; |
|
633
|
|
|
|
|
|
|
} |
|
634
|
|
|
|
|
|
|
else { |
|
635
|
1
|
|
|
|
|
251
|
confess "Bad Redirect" |
|
636
|
|
|
|
|
|
|
} |
|
637
|
|
|
|
|
|
|
} |
|
638
|
|
|
|
|
|
|
|
|
639
|
7
|
|
|
|
|
27
|
return \&p11; |
|
640
|
|
|
|
|
|
|
} |
|
641
|
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
$STATE_DESC{'n16'} = 'method_is_post'; |
|
643
|
|
|
|
|
|
|
sub n16 { |
|
644
|
40
|
|
|
40
|
0
|
84
|
my ($resource, $request, $response) = @_; |
|
645
|
40
|
100
|
|
|
|
125
|
$request->method eq 'POST' ? \&n11 : \&o16 |
|
646
|
|
|
|
|
|
|
} |
|
647
|
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
$STATE_DESC{'o14'} = 'in_conflict'; |
|
649
|
|
|
|
|
|
|
sub o14 { |
|
650
|
3
|
|
|
3
|
0
|
9
|
my ($resource, $request, $response) = @_; |
|
651
|
3
|
100
|
|
|
|
24
|
return \409 if $resource->is_conflict; |
|
652
|
|
|
|
|
|
|
|
|
653
|
2
|
|
|
|
|
8
|
my $handler = _get_acceptable_content_type_handler( $resource, $request ); |
|
654
|
2
|
50
|
|
|
|
9
|
return $handler if is_status_code( $handler ); |
|
655
|
|
|
|
|
|
|
|
|
656
|
2
|
|
|
|
|
11
|
my $result = $resource->$handler(); |
|
657
|
|
|
|
|
|
|
|
|
658
|
2
|
100
|
|
|
|
7
|
return $result if is_status_code( $result ); |
|
659
|
1
|
|
|
|
|
5
|
return \&p11; |
|
660
|
|
|
|
|
|
|
} |
|
661
|
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
$STATE_DESC{'o16'} = 'method_is_put'; |
|
663
|
|
|
|
|
|
|
sub o16 { |
|
664
|
39
|
|
|
39
|
0
|
84
|
my ($resource, $request, $response) = @_; |
|
665
|
39
|
100
|
|
|
|
1275
|
$request->method eq 'PUT' ? \&o14 : \&o18; |
|
666
|
|
|
|
|
|
|
} |
|
667
|
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
$STATE_DESC{'o18'} = 'multiple_representations'; |
|
669
|
|
|
|
|
|
|
sub o18 { |
|
670
|
40
|
|
|
40
|
0
|
82
|
my ($resource, $request, $response) = @_; |
|
671
|
40
|
|
|
|
|
117
|
my $metadata = _metadata($request); |
|
672
|
40
|
100
|
100
|
|
|
255
|
if ( $request->method eq 'GET' || $request->method eq 'HEAD' ) { |
|
673
|
36
|
|
|
|
|
368
|
_add_caching_headers( $resource, $response ); |
|
674
|
|
|
|
|
|
|
|
|
675
|
36
|
|
|
|
|
102
|
my $content_type = $metadata->{'Content-Type'}; |
|
676
|
|
|
|
|
|
|
my $match = first { |
|
677
|
36
|
|
|
36
|
|
347
|
my $ct = create_header( MediaType => pair_key( $_ ) ); |
|
678
|
36
|
|
|
|
|
3994
|
$content_type->match( $ct ) |
|
679
|
36
|
|
|
|
|
207
|
} @{ $resource->content_types_provided }; |
|
|
36
|
|
|
|
|
134
|
|
|
680
|
|
|
|
|
|
|
|
|
681
|
36
|
|
|
|
|
2063
|
my $handler = pair_value( $match ); |
|
682
|
36
|
|
|
|
|
307
|
my $result = $resource->$handler(); |
|
683
|
|
|
|
|
|
|
|
|
684
|
36
|
100
|
|
|
|
3913
|
return $result if is_status_code( $result ); |
|
685
|
|
|
|
|
|
|
|
|
686
|
35
|
100
|
|
|
|
141
|
unless($request->method eq 'HEAD') { |
|
687
|
34
|
100
|
|
|
|
311
|
if (ref($result) eq 'CODE') { |
|
688
|
5
|
|
|
|
|
14
|
$request->env->{'web.machine.streaming_push'} = $result; |
|
689
|
|
|
|
|
|
|
} |
|
690
|
|
|
|
|
|
|
else { |
|
691
|
29
|
|
|
|
|
179
|
$response->body( $result ); |
|
692
|
|
|
|
|
|
|
} |
|
693
|
34
|
|
|
|
|
377
|
encode_body( $resource, $response ); |
|
694
|
|
|
|
|
|
|
} |
|
695
|
35
|
|
|
|
|
611
|
return \&o18b; |
|
696
|
|
|
|
|
|
|
} |
|
697
|
|
|
|
|
|
|
else { |
|
698
|
4
|
|
|
|
|
73
|
return \&o18b; |
|
699
|
|
|
|
|
|
|
} |
|
700
|
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
} |
|
702
|
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
$STATE_DESC{'o18b'} = 'multiple_choices'; |
|
704
|
|
|
|
|
|
|
sub o18b { |
|
705
|
39
|
|
|
39
|
0
|
88
|
my ($resource, $request, $response) = @_; |
|
706
|
39
|
100
|
|
|
|
273
|
$resource->multiple_choices ? \300 : \200; |
|
707
|
|
|
|
|
|
|
} |
|
708
|
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
$STATE_DESC{'o20'} = 'response_body_includes_entity'; |
|
710
|
|
|
|
|
|
|
sub o20 { |
|
711
|
7
|
|
|
7
|
0
|
18
|
my ($resource, $request, $response) = @_; |
|
712
|
7
|
100
|
|
|
|
28
|
$response->body ? \&o18 : \204; |
|
713
|
|
|
|
|
|
|
} |
|
714
|
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
$STATE_DESC{'p3'} = 'in_conflict'; |
|
716
|
|
|
|
|
|
|
sub p3 { |
|
717
|
6
|
|
|
6
|
0
|
16
|
my ($resource, $request, $response) = @_; |
|
718
|
6
|
100
|
|
|
|
39
|
return \409 if $resource->is_conflict; |
|
719
|
|
|
|
|
|
|
|
|
720
|
5
|
|
|
|
|
20
|
my $handler = _get_acceptable_content_type_handler( $resource, $request ); |
|
721
|
5
|
100
|
|
|
|
16
|
return $handler if is_status_code( $handler ); |
|
722
|
|
|
|
|
|
|
|
|
723
|
4
|
|
|
|
|
18
|
my $result = $resource->$handler(); |
|
724
|
|
|
|
|
|
|
|
|
725
|
4
|
100
|
|
|
|
15
|
return $result if is_status_code( $result ); |
|
726
|
3
|
|
|
|
|
16
|
return \&p11; |
|
727
|
|
|
|
|
|
|
} |
|
728
|
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
$STATE_DESC{'p11'} = 'new_resource'; |
|
730
|
|
|
|
|
|
|
sub p11 { |
|
731
|
11
|
|
|
11
|
0
|
31
|
my ($resource, $request, $response) = @_; |
|
732
|
11
|
100
|
|
|
|
41
|
(not $response->header('Location')) ? \&o20 : \201 |
|
733
|
|
|
|
|
|
|
} |
|
734
|
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
1; |
|
736
|
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
__END__ |