add files
|
1 |
package Mojo::Content::Single; |
2 |
use Mojo::Base 'Mojo::Content'; |
|
3 | ||
4 |
use Mojo::Asset::Memory; |
|
5 |
use Mojo::Content::MultiPart; |
|
6 | ||
7 |
has asset => sub { Mojo::Asset::Memory->new(auto_upgrade => 1) }; |
|
8 |
has auto_upgrade => 1; |
|
9 | ||
10 |
sub new { |
|
11 |
my $self = shift->SUPER::new(@_); |
|
12 |
$self->{read} |
|
13 |
= $self->on(read => sub { $_[0]->asset($_[0]->asset->add_chunk($_[1])) }); |
|
14 |
return $self; |
|
15 |
} |
|
16 | ||
17 |
sub body_contains { shift->asset->contains(shift) >= 0 } |
|
18 | ||
19 |
sub body_size { |
|
20 |
my $self = shift; |
|
21 |
return ($self->headers->content_length || 0) if $self->{dynamic}; |
|
22 |
return $self->asset->size; |
|
23 |
} |
|
24 | ||
25 |
sub clone { |
|
26 |
my $self = shift; |
|
27 |
return undef unless my $clone = $self->SUPER::clone(); |
|
28 |
return $clone->asset($self->asset); |
|
29 |
} |
|
30 | ||
31 |
sub get_body_chunk { |
|
32 |
my ($self, $offset) = @_; |
|
33 |
return $self->generate_body_chunk($offset) if $self->{dynamic}; |
|
34 |
return $self->asset->get_chunk($offset); |
|
35 |
} |
|
36 | ||
37 |
sub parse { |
|
38 |
my $self = shift; |
|
39 | ||
40 |
# Parse headers |
|
41 |
$self->_parse_until_body(@_); |
|
42 | ||
43 |
# Parse body |
|
44 |
return $self->SUPER::parse |
|
45 |
unless $self->auto_upgrade && defined $self->boundary; |
|
46 | ||
47 |
# Content needs to be upgraded to multipart |
|
48 |
$self->unsubscribe(read => $self->{read}); |
|
49 |
my $multi = Mojo::Content::MultiPart->new(%$self); |
|
50 |
$self->emit(upgrade => $multi); |
|
51 |
return $multi->parse; |
|
52 |
} |
|
53 | ||
54 |
1; |
|
55 | ||
56 |
=encoding utf8 |
|
57 | ||
58 |
=head1 NAME |
|
59 | ||
60 |
Mojo::Content::Single - HTTP content |
|
61 | ||
62 |
=head1 SYNOPSIS |
|
63 | ||
64 |
use Mojo::Content::Single; |
|
65 | ||
66 |
my $single = Mojo::Content::Single->new; |
|
67 |
$single->parse("Content-Length: 12\x0d\x0a\x0d\x0aHello World!"); |
|
68 |
say $single->headers->content_length; |
|
69 | ||
70 |
=head1 DESCRIPTION |
|
71 | ||
72 |
L<Mojo::Content::Single> is a container for HTTP content as described in RFC |
|
73 |
2616. |
|
74 | ||
75 |
=head1 EVENTS |
|
76 | ||
77 |
L<Mojo::Content::Single> inherits all events from L<Mojo::Content> and can |
|
78 |
emit the following new ones. |
|
79 | ||
80 |
=head2 upgrade |
|
81 | ||
82 |
$single->on(upgrade => sub { |
|
83 |
my ($single, $multi) = @_; |
|
84 |
... |
|
85 |
}); |
|
86 | ||
87 |
Emitted when content gets upgraded to a L<Mojo::Content::MultiPart> object. |
|
88 | ||
89 |
$single->on(upgrade => sub { |
|
90 |
my ($single, $multi) = @_; |
|
91 |
return unless $multi->headers->content_type =~ /multipart\/([^;]+)/i; |
|
92 |
say "Multipart: $1"; |
|
93 |
}); |
|
94 | ||
95 |
=head1 ATTRIBUTES |
|
96 | ||
97 |
L<Mojo::Content::Single> inherits all attributes from L<Mojo::Content> and |
|
98 |
implements the following new ones. |
|
99 | ||
100 |
=head2 asset |
|
101 | ||
102 |
my $asset = $single->asset; |
|
103 |
$single = $single->asset(Mojo::Asset::Memory->new); |
|
104 | ||
105 |
The actual content, defaults to a L<Mojo::Asset::Memory> object with |
|
106 |
C<auto_upgrade> enabled. |
|
107 | ||
108 |
=head2 auto_upgrade |
|
109 | ||
110 |
my $upgrade = $single->auto_upgrade; |
|
111 |
$single = $single->auto_upgrade(0); |
|
112 | ||
113 |
Try to detect multipart content and automatically upgrade to a |
|
114 |
L<Mojo::Content::MultiPart> object, defaults to C<1>. |
|
115 | ||
116 |
=head1 METHODS |
|
117 | ||
118 |
L<Mojo::Content::Single> inherits all methods from L<Mojo::Content> and |
|
119 |
implements the following new ones. |
|
120 | ||
121 |
=head2 new |
|
122 | ||
123 |
my $single = Mojo::Content::Single->new; |
|
124 | ||
125 |
Construct a new L<Mojo::Content::Single> object and subscribe to L</"read"> |
|
126 |
event with default content parser. |
|
127 | ||
128 |
=head2 body_contains |
|
129 | ||
130 |
my $bool = $single->body_contains('1234567'); |
|
131 | ||
132 |
Check if content contains a specific string. |
|
133 | ||
134 |
=head2 body_size |
|
135 | ||
136 |
my $size = $single->body_size; |
|
137 | ||
138 |
Content size in bytes. |
|
139 | ||
140 |
=head2 clone |
|
141 | ||
142 |
my $clone = $single->clone; |
|
143 | ||
144 |
Clone content if possible, otherwise return C<undef>. |
|
145 | ||
146 |
=head2 get_body_chunk |
|
147 | ||
148 |
my $bytes = $single->get_body_chunk(0); |
|
149 | ||
150 |
Get a chunk of content starting from a specific position. |
|
151 | ||
152 |
=head2 parse |
|
153 | ||
154 |
$single = $single->parse("Content-Length: 12\x0d\x0a\x0d\x0aHello World!"); |
|
155 |
my $multi |
|
156 |
= $single->parse("Content-Type: multipart/form-data\x0d\x0a\x0d\x0a"); |
|
157 | ||
158 |
Parse content chunk and upgrade to L<Mojo::Content::MultiPart> object if |
|
159 |
necessary. |
|
160 | ||
161 |
=head1 SEE ALSO |
|
162 | ||
163 |
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>. |
|
164 | ||
165 |
=cut |