Newer Older
165 lines | 3.689kb
add files
Yuki Kimoto authored on 2014-03-26
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