source: main/trunk/greenstone2/perllib/cpan/Mojo/Message/Response.pm@ 32205

Last change on this file since 32205 was 32205, checked in by ak19, 6 years ago

First set of commits to do with implementing the new 'paged_html' output option of PDFPlugin that uses using xpdftools' new pdftohtml. So far tested only on Linux (64 bit), but things work there so I'm optimistically committing the changes since they work. 2. Committing the pre-built Linux binaries of XPDFtools for both 32 and 64 bit built by the XPDF group. 2. To use the correct bitness variant of xpdftools, setup.bash now exports the BITNESS env var, consulted by gsConvert.pl. 3. All the perl code changes to do with using xpdf tools' pdftohtml to generate paged_html and feed it in the desired form into GS(3): gsConvert.pl, PDFPlugin.pm and its parent ConvertBinaryPFile.pm have been modified to make it all work. xpdftools' pdftohtml generates a folder containing an html file and a screenshot for each page in a PDF (as well as an index.html linking to each page's html). However, we want a single html file that contains each individual 'page' html's content in a div, and need to do some further HTML style, attribute and structure modifications to massage the xpdftool output to what we want for GS. In order to parse and manipulate the HTML 'DOM' to do this, we're using the Mojo::DOM package that Dr Bainbridge found and which he's compiled up. Mojo::DOM is therefore also committed in this revision. Some further changes and some display fixes are required, but need to check with the others about that.

File size: 8.4 KB
Line 
1package Mojo::Message::Response;
2use Mojo::Base 'Mojo::Message';
3
4use Mojo::Cookie::Response;
5use Mojo::Date;
6
7has [qw(code message)];
8has max_message_size => sub { $ENV{MOJO_MAX_MESSAGE_SIZE} // 2147483648 };
9
10# Umarked codes are from RFC 7231
11my %MESSAGES = (
12 100 => 'Continue',
13 101 => 'Switching Protocols',
14 102 => 'Processing', # RFC 2518 (WebDAV)
15 103 => 'Early Hints', # RFC 8297
16 200 => 'OK',
17 201 => 'Created',
18 202 => 'Accepted',
19 203 => 'Non-Authoritative Information',
20 204 => 'No Content',
21 205 => 'Reset Content',
22 206 => 'Partial Content',
23 207 => 'Multi-Status', # RFC 2518 (WebDAV)
24 208 => 'Already Reported', # RFC 5842
25 226 => 'IM Used', # RFC 3229
26 300 => 'Multiple Choices',
27 301 => 'Moved Permanently',
28 302 => 'Found',
29 303 => 'See Other',
30 304 => 'Not Modified',
31 305 => 'Use Proxy',
32 307 => 'Temporary Redirect',
33 308 => 'Permanent Redirect', # RFC 7538
34 400 => 'Bad Request',
35 401 => 'Unauthorized',
36 402 => 'Payment Required',
37 403 => 'Forbidden',
38 404 => 'Not Found',
39 405 => 'Method Not Allowed',
40 406 => 'Not Acceptable',
41 407 => 'Proxy Authentication Required',
42 408 => 'Request Timeout',
43 409 => 'Conflict',
44 410 => 'Gone',
45 411 => 'Length Required',
46 412 => 'Precondition Failed',
47 413 => 'Request Entity Too Large',
48 414 => 'Request-URI Too Long',
49 415 => 'Unsupported Media Type',
50 416 => 'Request Range Not Satisfiable',
51 417 => 'Expectation Failed',
52 418 => "I'm a teapot", # RFC 2324 :)
53 421 => 'Misdirected Request', # RFC 7540
54 422 => 'Unprocessable Entity', # RFC 2518 (WebDAV)
55 423 => 'Locked', # RFC 2518 (WebDAV)
56 424 => 'Failed Dependency', # RFC 2518 (WebDAV)
57 425 => 'Unordered Colection', # RFC 3648 (WebDAV)
58 426 => 'Upgrade Required', # RFC 2817
59 428 => 'Precondition Required', # RFC 6585
60 429 => 'Too Many Requests', # RFC 6585
61 431 => 'Request Header Fields Too Large', # RFC 6585
62 451 => 'Unavailable For Legal Reasons', # RFC 7725
63 500 => 'Internal Server Error',
64 501 => 'Not Implemented',
65 502 => 'Bad Gateway',
66 503 => 'Service Unavailable',
67 504 => 'Gateway Timeout',
68 505 => 'HTTP Version Not Supported',
69 506 => 'Variant Also Negotiates', # RFC 2295
70 507 => 'Insufficient Storage', # RFC 2518 (WebDAV)
71 508 => 'Loop Detected', # RFC 5842
72 509 => 'Bandwidth Limit Exceeded', # Unofficial
73 510 => 'Not Extended', # RFC 2774
74 511 => 'Network Authentication Required' # RFC 6585
75);
76
77sub cookies {
78 my $self = shift;
79
80 # Parse cookies
81 my $headers = $self->headers;
82 return [@{Mojo::Cookie::Response->parse($headers->set_cookie)}] unless @_;
83
84 # Add cookies
85 $headers->add('Set-Cookie' => "$_")
86 for map { ref $_ eq 'HASH' ? Mojo::Cookie::Response->new($_) : $_ } @_;
87
88 return $self;
89}
90
91sub default_message { $MESSAGES{$_[1] || $_[0]->code // 404} || '' }
92
93sub extract_start_line {
94 my ($self, $bufref) = @_;
95
96 # We have a full response line
97 return undef unless $$bufref =~ s/^(.*?)\x0d?\x0a//;
98 return !$self->error({message => 'Bad response start-line'})
99 unless $1 =~ m!^\s*HTTP/(\d\.\d)\s+(\d\d\d)\s*(.+)?$!;
100
101 my $content = $self->content;
102 $content->skip_body(1) if $self->code($2)->is_empty;
103 defined $content->$_ or $content->$_(1) for qw(auto_decompress auto_relax);
104 $content->expect_close(1) if $1 eq '1.0';
105 return !!$self->version($1)->message($3);
106}
107
108sub fix_headers {
109 my $self = shift;
110 $self->{fix} ? return $self : $self->SUPER::fix_headers(@_);
111
112 # Date
113 my $headers = $self->headers;
114 $headers->date(Mojo::Date->new->to_string) unless $headers->date;
115
116 # RFC 7230 3.3.2
117 $headers->remove('Content-Length') if $self->is_empty;
118
119 return $self;
120}
121
122sub get_start_line_chunk {
123 my ($self, $offset) = @_;
124 $self->_start_line->emit(progress => 'start_line', $offset);
125 return substr $self->{start_buffer}, $offset, 131072;
126}
127
128sub is_client_error { shift->_status_class(400) }
129
130sub is_empty {
131 my $self = shift;
132 return undef unless my $code = $self->code;
133 return $self->is_info || $code == 204 || $code == 304;
134}
135
136sub is_error { shift->_status_class(400, 500) }
137sub is_info { shift->_status_class(100) }
138sub is_redirect { shift->_status_class(300) }
139sub is_server_error { shift->_status_class(500) }
140
141sub is_success { shift->_status_class(200) }
142
143sub start_line_size { length shift->_start_line->{start_buffer} }
144
145sub _start_line {
146 my $self = shift;
147
148 return $self if defined $self->{start_buffer};
149 my $code = $self->code || 404;
150 my $msg = $self->message || $self->default_message;
151 $self->{start_buffer} = "HTTP/@{[$self->version]} $code $msg\x0d\x0a";
152
153 return $self;
154}
155
156sub _status_class {
157 my ($self, @classes) = @_;
158 return undef unless my $code = $self->code;
159 return !!grep { $code >= $_ && $code < ($_ + 100) } @classes;
160}
161
1621;
163
164=encoding utf8
165
166=head1 NAME
167
168Mojo::Message::Response - HTTP response
169
170=head1 SYNOPSIS
171
172 use Mojo::Message::Response;
173
174 # Parse
175 my $res = Mojo::Message::Response->new;
176 $res->parse("HTTP/1.0 200 OK\x0d\x0a");
177 $res->parse("Content-Length: 12\x0d\x0a");
178 $res->parse("Content-Type: text/plain\x0d\x0a\x0d\x0a");
179 $res->parse('Hello World!');
180 say $res->code;
181 say $res->headers->content_type;
182 say $res->body;
183
184 # Build
185 my $res = Mojo::Message::Response->new;
186 $res->code(200);
187 $res->headers->content_type('text/plain');
188 $res->body('Hello World!');
189 say $res->to_string;
190
191=head1 DESCRIPTION
192
193L<Mojo::Message::Response> is a container for HTTP responses, based on
194L<RFC 7230|http://tools.ietf.org/html/rfc7230> and
195L<RFC 7231|http://tools.ietf.org/html/rfc7231>.
196
197=head1 EVENTS
198
199L<Mojo::Message::Response> inherits all events from L<Mojo::Message>.
200
201=head1 ATTRIBUTES
202
203L<Mojo::Message::Response> inherits all attributes from L<Mojo::Message> and
204implements the following new ones.
205
206=head2 code
207
208 my $code = $res->code;
209 $res = $res->code(200);
210
211HTTP response status code.
212
213=head2 max_message_size
214
215 my $size = $res->max_message_size;
216 $res = $res->max_message_size(1024);
217
218Maximum message size in bytes, defaults to the value of the
219C<MOJO_MAX_MESSAGE_SIZE> environment variable or C<2147483648> (2GiB). Setting
220the value to C<0> will allow messages of indefinite size.
221
222=head2 message
223
224 my $msg = $res->message;
225 $res = $res->message('OK');
226
227HTTP response status message.
228
229=head1 METHODS
230
231L<Mojo::Message::Response> inherits all methods from L<Mojo::Message> and
232implements the following new ones.
233
234=head2 cookies
235
236 my $cookies = $res->cookies;
237 $res = $res->cookies(Mojo::Cookie::Response->new);
238 $res = $res->cookies({name => 'foo', value => 'bar'});
239
240Access response cookies, usually L<Mojo::Cookie::Response> objects.
241
242 # Names of all cookies
243 say $_->name for @{$res->cookies};
244
245=head2 default_message
246
247 my $msg = $res->default_message;
248 my $msg = $res->default_message(418);
249
250Generate default response message for status code, defaults to using
251L</"code">.
252
253=head2 extract_start_line
254
255 my $bool = $res->extract_start_line(\$str);
256
257Extract status-line from string.
258
259=head2 fix_headers
260
261 $res = $res->fix_headers;
262
263Make sure response has all required headers.
264
265=head2 get_start_line_chunk
266
267 my $bytes = $res->get_start_line_chunk($offset);
268
269Get a chunk of status-line data starting from a specific position. Note that
270this method finalizes the response.
271
272=head2 is_client_error
273
274 my $bool = $res->is_client_error;
275
276Check if this response has a C<4xx> status L</"code">.
277
278=head2 is_empty
279
280 my $bool = $res->is_empty;
281
282Check if this response has a C<1xx>, C<204> or C<304> status L</"code">.
283
284=head2 is_error
285
286 my $bool = $res->is_error;
287
288Check if this response has a C<4xx> or C<5xx> status L</"code">.
289
290=head2 is_info
291
292 my $bool = $res->is_info;
293
294Check if this response has a C<1xx> status L</"code">.
295
296=head2 is_redirect
297
298 my $bool = $res->is_redirect;
299
300Check if this response has a C<3xx> status L</"code">.
301
302=head2 is_server_error
303
304 my $bool = $res->is_server_error;
305
306Check if this response has a C<5xx> status L</"code">.
307
308=head2 is_success
309
310 my $bool = $res->is_success;
311
312Check if this response has a C<2xx> status L</"code">.
313
314=head2 start_line_size
315
316 my $size = $req->start_line_size;
317
318Size of the status-line in bytes. Note that this method finalizes the response.
319
320=head1 SEE ALSO
321
322L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
323
324=cut
Note: See TracBrowser for help on using the repository browser.