line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Web::Machine::FSM::States; |
2
|
|
|
|
|
|
|
# ABSTRACT: The States for Web Machine |
3
|
|
|
|
|
|
|
|
4
|
13
|
|
|
13
|
|
122
|
use strict; |
|
13
|
|
|
|
|
17
|
|
|
13
|
|
|
|
|
426
|
|
5
|
13
|
|
|
13
|
|
55
|
use warnings; |
|
13
|
|
|
|
|
19
|
|
|
13
|
|
|
|
|
609
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our $VERSION = '0.16'; |
8
|
|
|
|
|
|
|
|
9
|
13
|
|
|
13
|
|
59
|
use B (); |
|
13
|
|
|
|
|
15
|
|
|
13
|
|
|
|
|
166
|
|
10
|
13
|
|
|
13
|
|
46
|
use Hash::MultiValue; |
|
13
|
|
|
|
|
15
|
|
|
13
|
|
|
|
|
239
|
|
11
|
|
|
|
|
|
|
|
12
|
13
|
|
|
13
|
|
45
|
use Carp qw[ confess ]; |
|
13
|
|
|
|
|
14
|
|
|
13
|
|
|
|
|
712
|
|
13
|
|
|
|
|
|
|
|
14
|
13
|
|
|
|
|
98
|
use Web::Machine::Util qw[ |
15
|
|
|
|
|
|
|
first |
16
|
|
|
|
|
|
|
pair_key |
17
|
|
|
|
|
|
|
pair_value |
18
|
|
|
|
|
|
|
create_header |
19
|
13
|
|
|
13
|
|
1027
|
]; |
|
13
|
|
|
|
|
21
|
|
20
|
13
|
|
|
|
|
89
|
use Web::Machine::Util::BodyEncoding qw[ |
21
|
|
|
|
|
|
|
encode_body_if_set |
22
|
|
|
|
|
|
|
encode_body |
23
|
13
|
|
|
13
|
|
10615
|
]; |
|
13
|
|
|
|
|
32
|
|
24
|
13
|
|
|
|
|
86
|
use Web::Machine::Util::ContentNegotiation qw[ |
25
|
|
|
|
|
|
|
choose_media_type |
26
|
|
|
|
|
|
|
match_acceptable_media_type |
27
|
|
|
|
|
|
|
choose_language |
28
|
|
|
|
|
|
|
choose_charset |
29
|
|
|
|
|
|
|
choose_encoding |
30
|
13
|
|
|
13
|
|
8231
|
]; |
|
13
|
|
|
|
|
32
|
|
31
|
|
|
|
|
|
|
|
32
|
13
|
|
|
|
|
88
|
use Sub::Exporter -setup => { |
33
|
|
|
|
|
|
|
exports => [qw[ |
34
|
|
|
|
|
|
|
start_state |
35
|
|
|
|
|
|
|
is_status_code |
36
|
|
|
|
|
|
|
is_new_state |
37
|
|
|
|
|
|
|
get_state_name |
38
|
|
|
|
|
|
|
get_state_desc |
39
|
|
|
|
|
|
|
]] |
40
|
13
|
|
|
13
|
|
5571
|
}; |
|
13
|
|
|
|
|
20
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
my %STATE_DESC; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# my exports ... |
45
|
|
|
|
|
|
|
|
46
|
124
|
|
|
124
|
0
|
286
|
sub start_state { \&b13 } |
47
|
2766
|
|
|
2766
|
0
|
8089
|
sub is_status_code { ref $_[0] eq 'SCALAR' } |
48
|
2455
|
|
|
2455
|
0
|
5185
|
sub is_new_state { ref $_[0] eq 'CODE' } |
49
|
1766
|
|
|
1766
|
0
|
7451
|
sub get_state_name { B::svref_2object( shift )->GV->NAME } |
50
|
0
|
0
|
|
0
|
0
|
0
|
sub get_state_desc { $STATE_DESC{ ref $_[0] ? get_state_name( shift ) : shift } } |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
# some utilities ... |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub _unquote_header { |
55
|
26
|
|
|
26
|
|
351
|
my $value = shift; |
56
|
26
|
50
|
|
|
|
58
|
if ( $value =~ /^"(.*)"$/ ) { |
57
|
0
|
|
|
|
|
0
|
return $1; |
58
|
|
|
|
|
|
|
} |
59
|
26
|
|
|
|
|
75
|
return $value; |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub _ensure_quoted_header { |
63
|
7
|
|
|
7
|
|
9
|
my $value = shift; |
64
|
7
|
50
|
|
|
|
15
|
return $value if $value =~ /^"(.*)"$/; |
65
|
7
|
|
|
|
|
29
|
return '"' . $value . '"'; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub _get_acceptable_content_type_handler { |
69
|
12
|
|
|
12
|
|
18
|
my ($resource, $request) = @_; |
70
|
12
|
|
100
|
|
|
27
|
my $acceptable = match_acceptable_media_type( |
71
|
|
|
|
|
|
|
($request->header('Content-Type') || 'application/octet-stream'), |
72
|
|
|
|
|
|
|
$resource->content_types_accepted |
73
|
|
|
|
|
|
|
); |
74
|
12
|
100
|
|
|
|
62
|
return \415 unless $acceptable; |
75
|
10
|
|
|
|
|
32
|
return pair_value( $acceptable ); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub _add_caching_headers { |
79
|
43
|
|
|
43
|
|
79
|
my ($resource, $response) = @_; |
80
|
43
|
100
|
|
|
|
176
|
if ( my $etag = $resource->generate_etag ) { |
81
|
7
|
|
|
|
|
27
|
$response->header( 'Etag' => _ensure_quoted_header( $etag ) ); |
82
|
|
|
|
|
|
|
} |
83
|
43
|
50
|
|
|
|
312
|
if ( my $expires = $resource->expires ) { |
84
|
0
|
|
|
|
|
0
|
$response->header( 'Expires' => $expires ); |
85
|
|
|
|
|
|
|
} |
86
|
43
|
100
|
|
|
|
153
|
if ( my $modified = $resource->last_modified ) { |
87
|
7
|
|
|
|
|
1323
|
$response->header( 'Last-Modified' => $modified ); |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub _handle_304 { |
92
|
7
|
|
|
7
|
|
186
|
my ($resource, $response) = @_; |
93
|
7
|
|
|
|
|
18
|
$response->headers->remove_header('Content-Type'); |
94
|
7
|
|
|
|
|
115
|
$response->headers->remove_header('Content-Encoding'); |
95
|
7
|
|
|
|
|
82
|
$response->headers->remove_header('Content-Language'); |
96
|
7
|
|
|
|
|
75
|
_add_caching_headers($resource, $response); |
97
|
7
|
|
|
|
|
189
|
return \304; |
98
|
|
|
|
|
|
|
} |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub _is_redirect { |
101
|
10
|
|
|
10
|
|
12
|
my ($response) = @_; |
102
|
|
|
|
|
|
|
# NOTE: |
103
|
|
|
|
|
|
|
# this makes a guess that the user has |
104
|
|
|
|
|
|
|
# told the Plack::Response that they |
105
|
|
|
|
|
|
|
# want to redirect. We do this based |
106
|
|
|
|
|
|
|
# on the fact that the ->redirect method |
107
|
|
|
|
|
|
|
# will set the status, while in almost all |
108
|
|
|
|
|
|
|
# other cases the status of the response |
109
|
|
|
|
|
|
|
# will not be set yet. |
110
|
|
|
|
|
|
|
# - SL |
111
|
10
|
100
|
|
|
|
23
|
return 1 if $response->status; |
112
|
7
|
|
|
|
|
35
|
return; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub _metadata { |
116
|
346
|
|
|
346
|
|
349
|
my ($request) = @_; |
117
|
346
|
|
|
|
|
651
|
return $request->env->{'web.machine.context'}; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
## States |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
$STATE_DESC{'b13'} = 'service_available'; |
123
|
|
|
|
|
|
|
sub b13 { |
124
|
124
|
|
|
124
|
0
|
150
|
my ($resource, $request, $response) = @_; |
125
|
124
|
100
|
|
|
|
522
|
$resource->service_available ? \&b12 : \503; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
$STATE_DESC{'b12'} = 'known_method'; |
129
|
|
|
|
|
|
|
sub b12 { |
130
|
122
|
|
|
122
|
0
|
137
|
my ($resource, $request, $response) = @_; |
131
|
122
|
|
|
|
|
302
|
my $method = $request->method; |
132
|
122
|
100
|
|
|
|
585
|
(grep { $method eq $_ } @{ $resource->known_methods }) ? \&b11 : \501; |
|
956
|
|
|
|
|
1091
|
|
|
122
|
|
|
|
|
466
|
|
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
$STATE_DESC{'b11'} = 'uri_too_long'; |
136
|
|
|
|
|
|
|
sub b11 { |
137
|
121
|
|
|
121
|
0
|
147
|
my ($resource, $request, $response) = @_; |
138
|
121
|
100
|
|
|
|
289
|
$resource->uri_too_long( $request->uri ) ? \414 : \&b10; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
$STATE_DESC{'b10'} = 'method_allowed'; |
142
|
|
|
|
|
|
|
sub b10 { |
143
|
120
|
|
|
120
|
0
|
167
|
my ($resource, $request, $response) = @_; |
144
|
120
|
|
|
|
|
306
|
my $method = $request->method; |
145
|
120
|
|
|
|
|
504
|
my @allowed_methods = @{ $resource->allowed_methods }; |
|
120
|
|
|
|
|
369
|
|
146
|
120
|
100
|
|
|
|
373
|
return \&b9 if grep { $method eq $_ } @allowed_methods; |
|
289
|
|
|
|
|
662
|
|
147
|
1
|
|
|
|
|
5
|
$response->header('Allow' => join ", " => @allowed_methods ); |
148
|
1
|
|
|
|
|
33
|
return \405; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
$STATE_DESC{'b9'} = 'malformed_request'; |
152
|
|
|
|
|
|
|
sub b9 { |
153
|
119
|
|
|
119
|
0
|
194
|
my ($resource, $request, $response) = @_; |
154
|
119
|
100
|
|
|
|
483
|
$resource->malformed_request ? \400 : \&b8; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
$STATE_DESC{'b8'} = 'is_authorized'; |
158
|
|
|
|
|
|
|
sub b8 { |
159
|
118
|
|
|
118
|
0
|
143
|
my ($resource, $request, $response) = @_; |
160
|
118
|
|
|
|
|
294
|
my $result = $resource->is_authorized( $request->header('Authorization') ); |
161
|
|
|
|
|
|
|
# if we get back a status, then use it |
162
|
118
|
100
|
100
|
|
|
297
|
if ( is_status_code( $result ) ) { |
|
|
100
|
|
|
|
|
|
163
|
1
|
|
|
|
|
3
|
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
|
114
|
|
|
|
|
259
|
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
|
|
|
|
7
|
if ( $result ) { |
175
|
1
|
|
|
|
|
3
|
$response->header( 'WWW-Authenticate' => $result ); |
176
|
|
|
|
|
|
|
} |
177
|
3
|
|
|
|
|
40
|
return \401; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
$STATE_DESC{'b7'} = 'forbidden'; |
182
|
|
|
|
|
|
|
sub b7 { |
183
|
114
|
|
|
114
|
0
|
134
|
my ($resource, $request, $response) = @_; |
184
|
114
|
100
|
|
|
|
387
|
$resource->forbidden ? \403 : \&b6; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
$STATE_DESC{'b6'} = 'content_headers_okay'; |
188
|
|
|
|
|
|
|
sub b6 { |
189
|
112
|
|
|
112
|
0
|
135
|
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
|
112
|
|
|
|
|
495
|
my $content_headers = Hash::MultiValue->new; |
200
|
|
|
|
|
|
|
$request->headers->scan(sub { |
201
|
158
|
|
|
158
|
|
2131
|
my ($name, $value) = @_; |
202
|
158
|
100
|
|
|
|
614
|
$content_headers->add( $name, $value ) if (lc $name) =~ /^content-/; |
203
|
112
|
|
|
|
|
2764
|
}); |
204
|
|
|
|
|
|
|
|
205
|
112
|
100
|
|
|
|
2161
|
$resource->valid_content_headers( $content_headers ) ? \&b5 : \501; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
$STATE_DESC{'b5'} = 'known_content_type'; |
209
|
|
|
|
|
|
|
sub b5 { |
210
|
111
|
|
|
111
|
0
|
150
|
my ($resource, $request, $response) = @_; |
211
|
111
|
100
|
|
|
|
240
|
$resource->known_content_type( $request->header('Content-Type') ) ? \&b4 : \415; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
$STATE_DESC{'b4'} = 'request_entity_too_large'; |
215
|
|
|
|
|
|
|
sub b4 { |
216
|
110
|
|
|
110
|
0
|
137
|
my ($resource, $request, $response) = @_; |
217
|
110
|
100
|
|
|
|
276
|
$resource->valid_entity_length( $request->content_length ) ? \&b3 : \413; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
$STATE_DESC{'b3'} = 'method_is_options'; |
221
|
|
|
|
|
|
|
sub b3 { |
222
|
109
|
|
|
109
|
0
|
126
|
my ($resource, $request, $response) = @_; |
223
|
109
|
100
|
|
|
|
219
|
if ( $request->method eq 'OPTIONS' ) { |
224
|
1
|
|
|
|
|
7
|
$response->headers( $resource->options ); |
225
|
1
|
|
|
|
|
50
|
return \200; |
226
|
|
|
|
|
|
|
} |
227
|
108
|
|
|
|
|
568
|
return \&c3 |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
$STATE_DESC{'c3'} = 'accept_header_exists'; |
231
|
|
|
|
|
|
|
sub c3 { |
232
|
108
|
|
|
108
|
0
|
113
|
my ($resource, $request, $response) = @_; |
233
|
108
|
|
|
|
|
195
|
my $metadata = _metadata($request); |
234
|
108
|
100
|
|
|
|
378
|
if ( !$request->header('Accept') ) { |
235
|
96
|
|
|
|
|
1942
|
$metadata->{'Content-Type'} = create_header( MediaType => ( |
236
|
|
|
|
|
|
|
pair_key( $resource->content_types_provided->[0] ) |
237
|
|
|
|
|
|
|
)); |
238
|
96
|
|
|
|
|
117309
|
return \&d4 |
239
|
|
|
|
|
|
|
} |
240
|
12
|
|
|
|
|
1063
|
return \&c4; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
$STATE_DESC{'c4'} = 'acceptable_media_type_available'; |
244
|
|
|
|
|
|
|
sub c4 { |
245
|
12
|
|
|
12
|
0
|
17
|
my ($resource, $request, $response) = @_; |
246
|
12
|
|
|
|
|
18
|
my $metadata = _metadata($request); |
247
|
|
|
|
|
|
|
|
248
|
12
|
|
|
|
|
38
|
my @types = map { pair_key( $_ ) } @{ $resource->content_types_provided }; |
|
13
|
|
|
|
|
85
|
|
|
12
|
|
|
|
|
28
|
|
249
|
|
|
|
|
|
|
|
250
|
12
|
100
|
|
|
|
52
|
if ( my $chosen_type = choose_media_type( \@types, $request->header('Accept') ) ) { |
251
|
11
|
|
|
|
|
1965
|
$metadata->{'Content-Type'} = $chosen_type; |
252
|
11
|
|
|
|
|
35
|
return \&d4; |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
1
|
|
|
|
|
203
|
return \406; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
$STATE_DESC{'d4'} = 'accept_language_header_exists'; |
259
|
|
|
|
|
|
|
sub d4 { |
260
|
107
|
|
|
107
|
0
|
133
|
my ($resource, $request, $response) = @_; |
261
|
107
|
100
|
|
|
|
304
|
(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
|
23
|
my ($resource, $request, $response) = @_; |
268
|
17
|
|
|
|
|
24
|
my $metadata = _metadata($request); |
269
|
|
|
|
|
|
|
|
270
|
17
|
100
|
|
|
|
75
|
if ( my $language = choose_language( $resource->languages_provided, $request->header('Accept-Language') ) ) { |
271
|
15
|
|
|
|
|
1317
|
$metadata->{'Language'} = $language; |
272
|
|
|
|
|
|
|
# handle the short circuit here ... |
273
|
15
|
100
|
|
|
|
59
|
$response->header( 'Content-Language' => $language ) if "$language" ne "1"; |
274
|
15
|
|
|
|
|
471
|
return \&e5; |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
2
|
|
|
|
|
227
|
return \406; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
$STATE_DESC{'e5'} = 'accept_charset_exists'; |
281
|
|
|
|
|
|
|
sub e5 { |
282
|
105
|
|
|
105
|
0
|
125
|
my ($resource, $request, $response) = @_; |
283
|
105
|
100
|
|
|
|
216
|
(not $request->header('Accept-Charset')) ? \&f6 : \&e6; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
$STATE_DESC{'e6'} = 'accept_charset_choice_available'; |
287
|
|
|
|
|
|
|
sub e6 { |
288
|
22
|
|
|
22
|
0
|
27
|
my ($resource, $request, $response) = @_; |
289
|
22
|
|
|
|
|
35
|
my $metadata = _metadata($request); |
290
|
|
|
|
|
|
|
|
291
|
22
|
100
|
|
|
|
97
|
if ( my $charset = choose_charset( $resource->charsets_provided, $request->header('Accept-Charset') ) ) { |
292
|
|
|
|
|
|
|
# handle the short circuit here ... |
293
|
20
|
50
|
|
|
|
4307
|
$metadata->{'Charset'} = $charset if "$charset" ne "1"; |
294
|
20
|
|
|
|
|
53
|
return \&f6; |
295
|
|
|
|
|
|
|
} |
296
|
|
|
|
|
|
|
|
297
|
2
|
|
|
|
|
698
|
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
|
103
|
|
|
103
|
0
|
129
|
my ($resource, $request, $response) = @_; |
304
|
103
|
|
|
|
|
164
|
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
|
103
|
100
|
100
|
|
|
704
|
if ( $resource->default_charset && !$request->header('Accept-Charset') ) { |
309
|
4
|
|
|
|
|
92
|
my $default = $resource->default_charset; |
310
|
4
|
100
|
|
|
|
21
|
$metadata->{'Charset'} = ref $default ? pair_key($default) : $default; |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
|
313
|
103
|
100
|
|
|
|
851
|
if ( my $charset = $metadata->{'Charset'} ) { |
314
|
|
|
|
|
|
|
# Add the charset to the content type now ... |
315
|
24
|
|
|
|
|
86
|
$metadata->{'Content-Type'}->add_param( 'charset' => $charset ); |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
# put the content type in the header now ... |
318
|
103
|
|
|
|
|
639
|
$response->header( 'Content-Type' => $metadata->{'Content-Type'}->as_string ); |
319
|
|
|
|
|
|
|
|
320
|
103
|
100
|
|
|
|
5890
|
if ( $request->header('Accept-Encoding') ) { |
321
|
13
|
|
|
|
|
874
|
return \&f7 |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
else { |
324
|
90
|
100
|
|
|
|
1852
|
if ( my $encoding = choose_encoding( $resource->encodings_provided, "identity;q=1.0,*;q=0.5" ) ) { |
325
|
86
|
100
|
|
|
|
40397
|
$response->header( 'Content-Encoding' => $encoding ) unless $encoding eq 'identity'; |
326
|
86
|
|
|
|
|
612
|
$metadata->{'Content-Encoding'} = $encoding; |
327
|
86
|
|
|
|
|
241
|
return \&g7; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
else { |
330
|
4
|
|
|
|
|
48
|
return \406; |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
$STATE_DESC{'f7'} = 'accept_encoding_choice_available'; |
336
|
|
|
|
|
|
|
sub f7 { |
337
|
13
|
|
|
13
|
0
|
18
|
my ($resource, $request, $response) = @_; |
338
|
13
|
|
|
|
|
17
|
my $metadata = _metadata($request); |
339
|
|
|
|
|
|
|
|
340
|
13
|
100
|
|
|
|
57
|
if ( my $encoding = choose_encoding( $resource->encodings_provided, $request->header('Accept-Encoding') ) ) { |
341
|
9
|
100
|
|
|
|
824
|
$response->header( 'Content-Encoding' => $encoding ) unless $encoding eq 'identity'; |
342
|
9
|
|
|
|
|
240
|
$metadata->{'Content-Encoding'} = $encoding; |
343
|
9
|
|
|
|
|
36
|
return \&g7; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
4
|
|
|
|
|
50
|
return \406; |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
$STATE_DESC{'g7'} = 'resource_exists'; |
350
|
|
|
|
|
|
|
sub g7 { |
351
|
95
|
|
|
95
|
0
|
137
|
my ($resource, $request, $response) = @_; |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
# NOTE: |
354
|
|
|
|
|
|
|
# set Vary header here since we are |
355
|
|
|
|
|
|
|
# done with content negotiation |
356
|
|
|
|
|
|
|
# - SL |
357
|
95
|
|
|
|
|
96
|
my @variances = @{ $resource->variances }; |
|
95
|
|
|
|
|
477
|
|
358
|
|
|
|
|
|
|
|
359
|
95
|
100
|
|
|
|
111
|
push @variances => 'Accept' if scalar @{ $resource->content_types_provided } > 1; |
|
95
|
|
|
|
|
231
|
|
360
|
95
|
100
|
|
|
|
605
|
push @variances => 'Accept-Encoding' if scalar keys %{ $resource->encodings_provided } > 1; |
|
95
|
|
|
|
|
179
|
|
361
|
95
|
100
|
66
|
|
|
477
|
push @variances => 'Accept-Charset' if defined $resource->charsets_provided && scalar @{ $resource->charsets_provided } > 1; |
|
95
|
|
|
|
|
421
|
|
362
|
95
|
100
|
|
|
|
465
|
push @variances => 'Accept-Language' if scalar @{ $resource->languages_provided } > 1; |
|
95
|
|
|
|
|
239
|
|
363
|
|
|
|
|
|
|
|
364
|
95
|
100
|
|
|
|
361
|
$response->header( 'Vary' => join ', ' => @variances ) if @variances; |
365
|
|
|
|
|
|
|
|
366
|
95
|
100
|
|
|
|
714
|
$resource->resource_exists ? \&g8 : \&h7; |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
$STATE_DESC{'g8'} = 'if_match_exists'; |
370
|
|
|
|
|
|
|
sub g8 { |
371
|
59
|
|
|
59
|
0
|
76
|
my ($resource, $request, $response) = @_; |
372
|
59
|
100
|
|
|
|
165
|
$request->header('If-Match') ? \&g9 : \&h10; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
$STATE_DESC{'g9'} = 'if_match_is_wildcard'; |
376
|
|
|
|
|
|
|
sub g9 { |
377
|
3
|
|
|
3
|
0
|
4
|
my ($resource, $request, $response) = @_; |
378
|
3
|
100
|
|
|
|
6
|
_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
|
3
|
my ($resource, $request, $response) = @_; |
384
|
2
|
|
|
|
|
4
|
my @etags = map { _unquote_header( $_ ) } split /\s*\,\s*/ => $request->header('If-Match'); |
|
2
|
|
|
|
|
40
|
|
385
|
2
|
|
|
|
|
5
|
my $etag = $resource->generate_etag; |
386
|
2
|
100
|
|
|
|
6
|
(grep { $etag eq $_ } @etags) ? \&h10 : \412; |
|
2
|
|
|
|
|
9
|
|
387
|
|
|
|
|
|
|
} |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
$STATE_DESC{'h7'} = 'if_match_exists_and_if_match_is_wildcard'; |
390
|
|
|
|
|
|
|
sub h7 { |
391
|
36
|
|
|
36
|
0
|
102
|
my ($resource, $request, $response) = @_; |
392
|
36
|
100
|
100
|
|
|
82
|
($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
|
58
|
|
|
58
|
0
|
79
|
my ($resource, $request, $response) = @_; |
398
|
58
|
100
|
|
|
|
119
|
$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
|
8
|
my ($resource, $request, $response) = @_; |
404
|
6
|
|
|
|
|
10
|
my $metadata = _metadata($request); |
405
|
6
|
50
|
|
|
|
25
|
if ( my $date = $request->header('If-Unmodified-Since') ) { |
406
|
6
|
|
|
|
|
251
|
$metadata->{'If-Unmodified-Since'} = $date; |
407
|
6
|
|
|
|
|
13
|
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
|
8
|
my ($resource, $request, $response) = @_; |
415
|
6
|
|
|
|
|
8
|
my $metadata = _metadata($request); |
416
|
6
|
100
|
66
|
|
|
26
|
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
|
10
|
my ($resource, $request, $response) = @_; |
425
|
8
|
100
|
|
|
|
35
|
if ( my $uri = $resource->moved_permanently ) { |
426
|
2
|
100
|
|
|
|
8
|
if ( is_status_code( $uri ) ) { |
427
|
1
|
|
|
|
|
3
|
return $uri; |
428
|
|
|
|
|
|
|
} |
429
|
1
|
|
|
|
|
3
|
$response->header('Location' => $uri ); |
430
|
1
|
|
|
|
|
29
|
return \301; |
431
|
|
|
|
|
|
|
} |
432
|
6
|
|
|
|
|
14
|
return \&p3; |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
$STATE_DESC{'i7'} = 'method_is_put'; |
436
|
|
|
|
|
|
|
sub i7 { |
437
|
30
|
|
|
30
|
0
|
35
|
my ($resource, $request, $response) = @_; |
438
|
30
|
100
|
|
|
|
69
|
$request->method eq 'PUT' ? \&i4 : \&k7 |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
$STATE_DESC{'i12'} = 'if_none_match_exists'; |
442
|
|
|
|
|
|
|
sub i12 { |
443
|
55
|
|
|
55
|
0
|
76
|
my ($resource, $request, $response) = @_; |
444
|
55
|
100
|
|
|
|
113
|
$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
|
26
|
my ($resource, $request, $response) = @_; |
450
|
19
|
100
|
|
|
|
34
|
$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
|
11
|
my ($resource, $request, $response) = @_; |
456
|
9
|
100
|
100
|
|
|
19
|
$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
|
22
|
my ($resource, $request, $response) = @_; |
464
|
20
|
100
|
|
|
|
93
|
if ( my $uri = $resource->moved_permanently ) { |
465
|
2
|
100
|
|
|
|
8
|
if ( is_status_code( $uri ) ) { |
466
|
1
|
|
|
|
|
3
|
return $uri; |
467
|
|
|
|
|
|
|
} |
468
|
1
|
|
|
|
|
4
|
$response->header('Location' => $uri ); |
469
|
1
|
|
|
|
|
24
|
return \301; |
470
|
|
|
|
|
|
|
} |
471
|
18
|
|
|
|
|
38
|
return \&l5; |
472
|
|
|
|
|
|
|
} |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
$STATE_DESC{'k7'} = 'previously_existed'; |
475
|
|
|
|
|
|
|
sub k7 { |
476
|
22
|
|
|
22
|
0
|
26
|
my ($resource, $request, $response) = @_; |
477
|
22
|
100
|
|
|
|
44
|
$resource->previously_existed ? \&k5 : \&l7; |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
$STATE_DESC{'k13'} = 'etag_in_if_none_match'; |
481
|
|
|
|
|
|
|
sub k13 { |
482
|
13
|
|
|
13
|
0
|
15
|
my ($resource, $request, $response) = @_; |
483
|
13
|
|
|
|
|
29
|
my @etags = map { _unquote_header( $_ ) } split /\s*\,\s*/ => $request->header('If-None-Match'); |
|
13
|
|
|
|
|
246
|
|
484
|
13
|
|
|
|
|
35
|
my $etag = $resource->generate_etag; |
485
|
13
|
100
|
100
|
|
|
53
|
$etag && (grep { $etag eq $_ } @etags) ? \&j18 : \&l13; |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
$STATE_DESC{'l5'} = 'moved_temporarily'; |
489
|
|
|
|
|
|
|
sub l5 { |
490
|
18
|
|
|
18
|
0
|
21
|
my ($resource, $request, $response) = @_; |
491
|
18
|
100
|
|
|
|
87
|
if ( my $uri = $resource->moved_temporarily ) { |
492
|
2
|
100
|
|
|
|
8
|
if ( is_status_code( $uri ) ) { |
493
|
1
|
|
|
|
|
3
|
return $uri; |
494
|
|
|
|
|
|
|
} |
495
|
1
|
|
|
|
|
3
|
$response->header('Location' => $uri ); |
496
|
1
|
|
|
|
|
24
|
return \307; |
497
|
|
|
|
|
|
|
} |
498
|
16
|
|
|
|
|
33
|
return \&m5; |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
$STATE_DESC{'l7'} = 'method_is_post'; |
502
|
|
|
|
|
|
|
sub l7 { |
503
|
2
|
|
|
2
|
0
|
3
|
my ($resource, $request, $response) = @_; |
504
|
2
|
100
|
|
|
|
5
|
$request->method eq 'POST' ? \&m7 : \404 |
505
|
|
|
|
|
|
|
} |
506
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
$STATE_DESC{'l13'} = 'if_modified_since_exists'; |
508
|
|
|
|
|
|
|
sub l13 { |
509
|
46
|
|
|
46
|
0
|
60
|
my ($resource, $request, $response) = @_; |
510
|
46
|
100
|
|
|
|
95
|
$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
|
13
|
my ($resource, $request, $response) = @_; |
516
|
9
|
|
|
|
|
14
|
my $metadata = _metadata($request); |
517
|
9
|
50
|
|
|
|
38
|
if ( my $date = $request->header('If-Modified-Since') ) { |
518
|
9
|
|
|
|
|
371
|
$metadata->{'If-Modified-Since'} = $date; |
519
|
9
|
|
|
|
|
744
|
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
|
12
|
my ($resource, $request, $response) = @_; |
527
|
9
|
|
|
|
|
14
|
my $metadata = _metadata($request); |
528
|
9
|
100
|
|
|
|
37
|
($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
|
2
|
my ($resource, $request, $response) = @_; |
534
|
1
|
|
|
|
|
1
|
my $metadata = _metadata($request); |
535
|
1
|
50
|
33
|
|
|
4
|
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
|
17
|
my ($resource, $request, $response) = @_; |
544
|
16
|
100
|
|
|
|
32
|
$request->method eq 'POST' ? \&n5 : \410 |
545
|
|
|
|
|
|
|
} |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
$STATE_DESC{'m7'} = 'allow_post_to_missing_resource'; |
548
|
|
|
|
|
|
|
sub m7 { |
549
|
1
|
|
|
1
|
0
|
3
|
my ($resource, $request, $response) = @_; |
550
|
1
|
50
|
|
|
|
3
|
$resource->allow_missing_post ? \&n11 : \404 |
551
|
|
|
|
|
|
|
} |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
$STATE_DESC{'m16'} = 'method_is_delete'; |
554
|
|
|
|
|
|
|
sub m16 { |
555
|
45
|
|
|
45
|
0
|
66
|
my ($resource, $request, $response) = @_; |
556
|
45
|
100
|
|
|
|
115
|
$request->method eq 'DELETE' ? \&m20 : \&n16 |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
$STATE_DESC{'m20'} = 'delete_enacted_immediately'; |
560
|
|
|
|
|
|
|
sub m20 { |
561
|
4
|
|
|
4
|
0
|
5
|
my ($resource, $request, $response) = @_; |
562
|
4
|
100
|
|
|
|
10
|
$resource->delete_resource ? \&m20b : \500 |
563
|
|
|
|
|
|
|
} |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
$STATE_DESC{'m20b'} = 'did_delete_complete'; |
566
|
|
|
|
|
|
|
sub m20b { |
567
|
3
|
|
|
3
|
0
|
4
|
my ($resource, $request, $response) = @_; |
568
|
3
|
100
|
|
|
|
7
|
$resource->delete_completed ? \&o20 : \202 |
569
|
|
|
|
|
|
|
} |
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
$STATE_DESC{'n5'} = 'allow_post_to_missing_resource'; |
572
|
|
|
|
|
|
|
sub n5 { |
573
|
15
|
|
|
15
|
0
|
18
|
my ($resource, $request, $response) = @_; |
574
|
15
|
100
|
|
|
|
32
|
$resource->allow_missing_post ? \&n11 : \410 |
575
|
|
|
|
|
|
|
} |
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
sub _n11_create_path { |
578
|
6
|
|
|
6
|
|
7
|
my ($resource, $request, $response) = @_; |
579
|
|
|
|
|
|
|
|
580
|
6
|
|
|
|
|
13
|
my $uri = $resource->create_path; |
581
|
6
|
100
|
|
|
|
141
|
confess "Create Path Nil" unless $uri; |
582
|
5
|
|
66
|
|
|
21
|
my $base_uri = $resource->base_uri || $request->base; |
583
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
# do a little cleanup |
585
|
5
|
50
|
|
|
|
522
|
$base_uri =~ s!/$!! if $uri =~ m!^/!; |
586
|
5
|
100
|
33
|
|
|
19
|
$base_uri .= '/' if $uri !~ m!^/! && $base_uri !~ m!/$!; |
587
|
5
|
|
|
|
|
39
|
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
|
|
|
|
|
442
|
$response->header( 'Location' => $new_uri->path_query ); |
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
$STATE_DESC{'n11'} = 'redirect'; |
599
|
|
|
|
|
|
|
sub n11 { |
600
|
16
|
|
|
16
|
0
|
19
|
my ($resource, $request, $response) = @_; |
601
|
16
|
100
|
|
|
|
43
|
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
|
|
|
|
44
|
_n11_create_path( $resource, $request, $response ) |
608
|
|
|
|
|
|
|
if not $resource->create_path_after_handler; |
609
|
|
|
|
|
|
|
|
610
|
5
|
|
|
|
|
226
|
my $handler = _get_acceptable_content_type_handler( $resource, $request ); |
611
|
5
|
100
|
|
|
|
10
|
return $handler if is_status_code( $handler ); |
612
|
|
|
|
|
|
|
|
613
|
4
|
|
|
|
|
12
|
my $result = $resource->$handler(); |
614
|
4
|
100
|
|
|
|
12
|
return $result if is_status_code( $result ); |
615
|
|
|
|
|
|
|
|
616
|
3
|
50
|
|
|
|
9
|
_n11_create_path( $resource, $request, $response ) |
617
|
|
|
|
|
|
|
if $resource->create_path_after_handler; |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
else { |
620
|
10
|
|
|
|
|
37
|
my $result = $resource->process_post; |
621
|
10
|
100
|
|
|
|
40
|
if ( $result ) { |
622
|
9
|
100
|
|
|
|
17
|
return $result if is_status_code( $result ); |
623
|
7
|
|
|
|
|
23
|
encode_body_if_set( $resource, $response ); |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
else { |
626
|
1
|
|
|
|
|
164
|
confess "Process Post Invalid"; |
627
|
|
|
|
|
|
|
} |
628
|
|
|
|
|
|
|
} |
629
|
|
|
|
|
|
|
|
630
|
10
|
100
|
|
|
|
74
|
if ( _is_redirect( $response ) ) { |
631
|
3
|
100
|
|
|
|
20
|
if ( $response->location ) { |
632
|
2
|
|
|
|
|
39
|
return \303; |
633
|
|
|
|
|
|
|
} |
634
|
|
|
|
|
|
|
else { |
635
|
1
|
|
|
|
|
165
|
confess "Bad Redirect" |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
} |
638
|
|
|
|
|
|
|
|
639
|
7
|
|
|
|
|
15
|
return \&p11; |
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
$STATE_DESC{'n16'} = 'method_is_post'; |
643
|
|
|
|
|
|
|
sub n16 { |
644
|
41
|
|
|
41
|
0
|
53
|
my ($resource, $request, $response) = @_; |
645
|
41
|
100
|
|
|
|
79
|
$request->method eq 'POST' ? \&n11 : \&o16 |
646
|
|
|
|
|
|
|
} |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
$STATE_DESC{'o14'} = 'in_conflict'; |
649
|
|
|
|
|
|
|
sub o14 { |
650
|
3
|
|
|
3
|
0
|
5
|
my ($resource, $request, $response) = @_; |
651
|
3
|
100
|
|
|
|
15
|
return \409 if $resource->is_conflict; |
652
|
|
|
|
|
|
|
|
653
|
2
|
|
|
|
|
5
|
my $handler = _get_acceptable_content_type_handler( $resource, $request ); |
654
|
2
|
50
|
|
|
|
5
|
return $handler if is_status_code( $handler ); |
655
|
|
|
|
|
|
|
|
656
|
2
|
|
|
|
|
6
|
my $result = $resource->$handler(); |
657
|
|
|
|
|
|
|
|
658
|
2
|
100
|
|
|
|
5
|
return $result if is_status_code( $result ); |
659
|
1
|
|
|
|
|
3
|
return \&p11; |
660
|
|
|
|
|
|
|
} |
661
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
$STATE_DESC{'o16'} = 'method_is_put'; |
663
|
|
|
|
|
|
|
sub o16 { |
664
|
39
|
|
|
39
|
0
|
48
|
my ($resource, $request, $response) = @_; |
665
|
39
|
100
|
|
|
|
81
|
$request->method eq 'PUT' ? \&o14 : \&o18; |
666
|
|
|
|
|
|
|
} |
667
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
$STATE_DESC{'o18'} = 'multiple_representations'; |
669
|
|
|
|
|
|
|
sub o18 { |
670
|
40
|
|
|
40
|
0
|
57
|
my ($resource, $request, $response) = @_; |
671
|
40
|
|
|
|
|
73
|
my $metadata = _metadata($request); |
672
|
40
|
100
|
100
|
|
|
153
|
if ( $request->method eq 'GET' || $request->method eq 'HEAD' ) { |
673
|
36
|
|
|
|
|
243
|
_add_caching_headers( $resource, $response ); |
674
|
|
|
|
|
|
|
|
675
|
36
|
|
|
|
|
53
|
my $content_type = $metadata->{'Content-Type'}; |
676
|
|
|
|
|
|
|
my $match = first { |
677
|
36
|
|
|
36
|
|
222
|
my $ct = create_header( MediaType => pair_key( $_ ) ); |
678
|
36
|
|
|
|
|
3062
|
$content_type->match( $ct ) |
679
|
36
|
|
|
|
|
146
|
} @{ $resource->content_types_provided }; |
|
36
|
|
|
|
|
76
|
|
680
|
|
|
|
|
|
|
|
681
|
36
|
|
|
|
|
1345
|
my $handler = pair_value( $match ); |
682
|
36
|
|
|
|
|
157
|
my $result = $resource->$handler(); |
683
|
|
|
|
|
|
|
|
684
|
36
|
100
|
|
|
|
2211
|
return $result if is_status_code( $result ); |
685
|
|
|
|
|
|
|
|
686
|
35
|
100
|
|
|
|
95
|
unless($request->method eq 'HEAD') { |
687
|
34
|
100
|
|
|
|
208
|
if (ref($result) eq 'CODE') { |
688
|
5
|
|
|
|
|
10
|
$request->env->{'web.machine.streaming_push'} = $result; |
689
|
|
|
|
|
|
|
} |
690
|
|
|
|
|
|
|
else { |
691
|
29
|
|
|
|
|
90
|
$response->body( $result ); |
692
|
|
|
|
|
|
|
} |
693
|
34
|
|
|
|
|
292
|
encode_body( $resource, $response ); |
694
|
|
|
|
|
|
|
} |
695
|
35
|
|
|
|
|
479
|
return \&o18b; |
696
|
|
|
|
|
|
|
} |
697
|
|
|
|
|
|
|
else { |
698
|
4
|
|
|
|
|
43
|
return \&o18b; |
699
|
|
|
|
|
|
|
} |
700
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
} |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
$STATE_DESC{'o18b'} = 'multiple_choices'; |
704
|
|
|
|
|
|
|
sub o18b { |
705
|
39
|
|
|
39
|
0
|
54
|
my ($resource, $request, $response) = @_; |
706
|
39
|
100
|
|
|
|
168
|
$resource->multiple_choices ? \300 : \200; |
707
|
|
|
|
|
|
|
} |
708
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
$STATE_DESC{'o20'} = 'response_body_includes_entity'; |
710
|
|
|
|
|
|
|
sub o20 { |
711
|
7
|
|
|
7
|
0
|
10
|
my ($resource, $request, $response) = @_; |
712
|
7
|
100
|
|
|
|
17
|
$response->body ? \&o18 : \204; |
713
|
|
|
|
|
|
|
} |
714
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
$STATE_DESC{'p3'} = 'in_conflict'; |
716
|
|
|
|
|
|
|
sub p3 { |
717
|
6
|
|
|
6
|
0
|
8
|
my ($resource, $request, $response) = @_; |
718
|
6
|
100
|
|
|
|
25
|
return \409 if $resource->is_conflict; |
719
|
|
|
|
|
|
|
|
720
|
5
|
|
|
|
|
11
|
my $handler = _get_acceptable_content_type_handler( $resource, $request ); |
721
|
5
|
100
|
|
|
|
11
|
return $handler if is_status_code( $handler ); |
722
|
|
|
|
|
|
|
|
723
|
4
|
|
|
|
|
13
|
my $result = $resource->$handler(); |
724
|
|
|
|
|
|
|
|
725
|
4
|
100
|
|
|
|
11
|
return $result if is_status_code( $result ); |
726
|
3
|
|
|
|
|
10
|
return \&p11; |
727
|
|
|
|
|
|
|
} |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
$STATE_DESC{'p11'} = 'new_resource'; |
730
|
|
|
|
|
|
|
sub p11 { |
731
|
11
|
|
|
11
|
0
|
12
|
my ($resource, $request, $response) = @_; |
732
|
11
|
100
|
|
|
|
25
|
(not $response->header('Location')) ? \&o20 : \201 |
733
|
|
|
|
|
|
|
} |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
1; |
736
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
__END__ |