Newer Older
328 lines | 7.828kb
copy gitweblite soruce code
root authored on 2012-11-23
1
package Mojo::Transaction::HTTP;
2
use Mojo::Base 'Mojo::Transaction';
3

            
4
use Mojo::Transaction::WebSocket;
5

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
6
has 'previous';
7

            
copy gitweblite soruce code
root authored on 2012-11-23
8
sub client_read {
9
  my ($self, $chunk) = @_;
10

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
11
  # Skip body for HEAD request
copy gitweblite soruce code
root authored on 2012-11-23
12
  my $res = $self->res;
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
13
  $res->content->skip_body(1) if uc $self->req->method eq 'HEAD';
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
14
  return unless $res->parse($chunk)->is_finished;
15

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
16
  # Unexpected 1xx response
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
17
  return $self->{state} = 'finished'
18
    if !$res->is_status_class(100) || $res->headers->upgrade;
19
  $self->res($res->new)->emit(unexpected => $res);
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
20
  return unless length(my $leftovers = $res->content->leftovers);
21
  $self->client_read($leftovers);
copy gitweblite soruce code
root authored on 2012-11-23
22
}
23

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
24
sub client_write { shift->_write(0) }
copy gitweblite soruce code
root authored on 2012-11-23
25

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
26
sub is_empty { !!(uc $_[0]->req->method eq 'HEAD' || $_[0]->res->is_empty) }
27

            
copy gitweblite soruce code
root authored on 2012-11-23
28
sub keep_alive {
29
  my $self = shift;
30

            
31
  # Close
32
  my $req      = $self->req;
33
  my $res      = $self->res;
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
34
  my $req_conn = lc(defined $req->headers->connection ? $req->headers->connection : '');
35
  my $res_conn = lc(defined $res->headers->connection ? $res->headers->connection : '');
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
36
  return undef if $req_conn eq 'close' || $res_conn eq 'close';
copy gitweblite soruce code
root authored on 2012-11-23
37

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
38
  # Keep-alive
copy gitweblite soruce code
root authored on 2012-11-23
39
  return 1 if $req_conn eq 'keep-alive' || $res_conn eq 'keep-alive';
40

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
41
  # No keep-alive for 1.0
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
42
  return !($req->version eq '1.0' || $res->version eq '1.0');
copy gitweblite soruce code
root authored on 2012-11-23
43
}
44

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
45
sub redirects {
46
  my $previous = shift;
47
  my @redirects;
48
  unshift @redirects, $previous while $previous = $previous->previous;
49
  return \@redirects;
50
}
51

            
copy gitweblite soruce code
root authored on 2012-11-23
52
sub server_read {
53
  my ($self, $chunk) = @_;
54

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
55
  # Parse request
copy gitweblite soruce code
root authored on 2012-11-23
56
  my $req = $self->req;
57
  $req->parse($chunk) unless $req->error;
58
  $self->{state} ||= 'read';
59

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
60
  # Generate response
61
  return unless $req->is_finished && !$self->{handled}++;
62
  $self->emit(upgrade => Mojo::Transaction::WebSocket->new(handshake => $self))
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
63
    if lc(defined $req->headers->upgrade ? $req->headers->upgrade : '') eq 'websocket';
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
64
  $self->emit('request');
copy gitweblite soruce code
root authored on 2012-11-23
65
}
66

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
67
sub server_write { shift->_write(1) }
copy gitweblite soruce code
root authored on 2012-11-23
68

            
69
sub _body {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
70
  my ($self, $msg, $finish) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
71

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
72
  # Prepare body chunk
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
73
  my $buffer = $msg->get_body_chunk($self->{offset});
copy gitweblite soruce code
root authored on 2012-11-23
74
  my $written = defined $buffer ? length $buffer : 0;
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
75
  $self->{write} = $msg->content->is_dynamic ? 1 : ($self->{write} - $written);
copy gitweblite soruce code
root authored on 2012-11-23
76
  $self->{offset} = $self->{offset} + $written;
77
  if (defined $buffer) { delete $self->{delay} }
78

            
79
  # Delayed
80
  else {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
81
    if   (delete $self->{delay}) { $self->{state} = 'paused' }
82
    else                         { $self->{delay} = 1 }
copy gitweblite soruce code
root authored on 2012-11-23
83
  }
84

            
85
  # Finished
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
86
  $self->{state} = $finish ? 'finished' : 'read'
copy gitweblite soruce code
root authored on 2012-11-23
87
    if $self->{write} <= 0 || (defined $buffer && !length $buffer);
88

            
89
  return defined $buffer ? $buffer : '';
90
}
91

            
92
sub _headers {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
93
  my ($self, $msg, $head) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
94

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
95
  # Prepare header chunk
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
96
  my $buffer = $msg->get_header_chunk($self->{offset});
copy gitweblite soruce code
root authored on 2012-11-23
97
  my $written = defined $buffer ? length $buffer : 0;
98
  $self->{write}  = $self->{write} - $written;
99
  $self->{offset} = $self->{offset} + $written;
100

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
101
  # Switch to body
copy gitweblite soruce code
root authored on 2012-11-23
102
  if ($self->{write} <= 0) {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
103
    $self->{offset} = 0;
copy gitweblite soruce code
root authored on 2012-11-23
104

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
105
    # Response without body
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
106
    if ($head && $self->is_empty) { $self->{state} = 'finished' }
copy gitweblite soruce code
root authored on 2012-11-23
107

            
108
    # Body
109
    else {
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
110
      $self->{http_state} = 'body';
111
      $self->{write} = $msg->content->is_dynamic ? 1 : $msg->body_size;
copy gitweblite soruce code
root authored on 2012-11-23
112
    }
113
  }
114

            
115
  return $buffer;
116
}
117

            
118
sub _start_line {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
119
  my ($self, $msg) = @_;
copy gitweblite soruce code
root authored on 2012-11-23
120

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
121
  # Prepare start line chunk
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
122
  my $buffer = $msg->get_start_line_chunk($self->{offset});
copy gitweblite soruce code
root authored on 2012-11-23
123
  my $written = defined $buffer ? length $buffer : 0;
124
  $self->{write}  = $self->{write} - $written;
125
  $self->{offset} = $self->{offset} + $written;
126

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
127
  # Switch to headers
copy gitweblite soruce code
root authored on 2012-11-23
128
  if ($self->{write} <= 0) {
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
129
    $self->{http_state} = 'headers';
130
    $self->{write}      = $msg->header_size;
131
    $self->{offset}     = 0;
copy gitweblite soruce code
root authored on 2012-11-23
132
  }
133

            
134
  return $buffer;
135
}
136

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
137
sub _write {
138
  my ($self, $server) = @_;
139

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
140
  # Client starts writing right away
141
  $self->{state} ||= 'write' unless $server;
142
  return '' unless $self->{state} eq 'write';
143

            
144
  # Nothing written yet
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
145
  $self->{$_} ||= 0 for qw(offset write);
146
  my $msg = $server ? $self->res : $self->req;
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
147
  unless ($self->{http_state}) {
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
148

            
149
    # Connection header
150
    my $headers = $msg->headers;
151
    $headers->connection($self->keep_alive ? 'keep-alive' : 'close')
152
      unless $headers->connection;
153

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
154
    # Switch to start line
155
    $self->{http_state} = 'start_line';
156
    $self->{write}      = $msg->start_line_size;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
157
  }
158

            
159
  # Start line
160
  my $chunk = '';
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
161
  $chunk .= $self->_start_line($msg) if $self->{http_state} eq 'start_line';
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
162

            
163
  # Headers
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
164
  $chunk .= $self->_headers($msg, $server) if $self->{http_state} eq 'headers';
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
165

            
166
  # Body
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
167
  $chunk .= $self->_body($msg, $server) if $self->{http_state} eq 'body';
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
168

            
169
  return $chunk;
170
}
171

            
copy gitweblite soruce code
root authored on 2012-11-23
172
1;
173

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
174
=encoding utf8
175

            
copy gitweblite soruce code
root authored on 2012-11-23
176
=head1 NAME
177

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
178
Mojo::Transaction::HTTP - HTTP transaction
copy gitweblite soruce code
root authored on 2012-11-23
179

            
180
=head1 SYNOPSIS
181

            
182
  use Mojo::Transaction::HTTP;
183

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
184
  # Client
copy gitweblite soruce code
root authored on 2012-11-23
185
  my $tx = Mojo::Transaction::HTTP->new;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
186
  $tx->req->method('GET');
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
187
  $tx->req->url->parse('http://example.com');
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
188
  $tx->req->headers->accept('application/json');
189
  say $tx->res->code;
190
  say $tx->res->headers->content_type;
191
  say $tx->res->body;
192
  say $tx->remote_address;
193

            
194
  # Server
195
  my $tx = Mojo::Transaction::HTTP->new;
196
  say $tx->req->method;
197
  say $tx->req->url->to_abs;
198
  say $tx->req->headers->accept;
199
  say $tx->remote_address;
200
  $tx->res->code(200);
201
  $tx->res->headers->content_type('text/plain');
202
  $tx->res->body('Hello World!');
copy gitweblite soruce code
root authored on 2012-11-23
203

            
204
=head1 DESCRIPTION
205

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
206
L<Mojo::Transaction::HTTP> is a container for HTTP transactions as described
207
in RFC 2616.
copy gitweblite soruce code
root authored on 2012-11-23
208

            
209
=head1 EVENTS
210

            
211
L<Mojo::Transaction::HTTP> inherits all events from L<Mojo::Transaction> and
212
can emit the following new ones.
213

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
214
=head2 request
copy gitweblite soruce code
root authored on 2012-11-23
215

            
216
  $tx->on(request => sub {
217
    my $tx = shift;
218
    ...
219
  });
220

            
221
Emitted when a request is ready and needs to be handled.
222

            
223
  $tx->on(request => sub {
224
    my $tx = shift;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
225
    $tx->res->headers->header('X-Bender' => 'Bite my shiny metal ass!');
226
  });
227

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
228
=head2 unexpected
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
229

            
230
  $tx->on(unexpected => sub {
231
    my ($tx, $res) = @_;
232
    ...
233
  });
234

            
235
Emitted for unexpected C<1xx> responses that will be ignored.
236

            
237
  $tx->on(unexpected => sub {
238
    my $tx = shift;
239
    $tx->res->on(finish => sub { say 'Followup response is finished.' });
copy gitweblite soruce code
root authored on 2012-11-23
240
  });
241

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
242
=head2 upgrade
copy gitweblite soruce code
root authored on 2012-11-23
243

            
244
  $tx->on(upgrade => sub {
245
    my ($tx, $ws) = @_;
246
    ...
247
  });
248

            
249
Emitted when transaction gets upgraded to a L<Mojo::Transaction::WebSocket>
250
object.
251

            
252
  $tx->on(upgrade => sub {
253
    my ($tx, $ws) = @_;
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
254
    $ws->res->headers->header('X-Bender' => 'Bite my shiny metal ass!');
copy gitweblite soruce code
root authored on 2012-11-23
255
  });
256

            
257
=head1 ATTRIBUTES
258

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
259
L<Mojo::Transaction::HTTP> inherits all attributes from L<Mojo::Transaction>
260
and implements the following new ones.
261

            
262
=head2 previous
263

            
264
  my $previous = $tx->previous;
265
  $tx          = $tx->previous(Mojo::Transaction->new);
266

            
267
Previous transaction that triggered this followup transaction.
268

            
269
  # Paths of previous requests
270
  say $tx->previous->previous->req->url->path;
271
  say $tx->previous->req->url->path;
copy gitweblite soruce code
root authored on 2012-11-23
272

            
273
=head1 METHODS
274

            
275
L<Mojo::Transaction::HTTP> inherits all methods from L<Mojo::Transaction> and
276
implements the following new ones.
277

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
278
=head2 client_read
copy gitweblite soruce code
root authored on 2012-11-23
279

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
280
  $tx->client_read($bytes);
copy gitweblite soruce code
root authored on 2012-11-23
281

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
282
Read data client-side, used to implement user agents.
copy gitweblite soruce code
root authored on 2012-11-23
283

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
284
=head2 client_write
copy gitweblite soruce code
root authored on 2012-11-23
285

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
286
  my $bytes = $tx->client_write;
copy gitweblite soruce code
root authored on 2012-11-23
287

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
288
Write data client-side, used to implement user agents.
copy gitweblite soruce code
root authored on 2012-11-23
289

            
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
290
=head2 is_empty
291

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
292
  my $bool = $tx->is_empty;
update Mojolicious 4.07
Yuki Kimoto authored on 2013-06-03
293

            
294
Check transaction for C<HEAD> request and C<1xx>, C<204> or C<304> response.
295

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
296
=head2 keep_alive
copy gitweblite soruce code
root authored on 2012-11-23
297

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
298
  my $bool = $tx->keep_alive;
copy gitweblite soruce code
root authored on 2012-11-23
299

            
300
Check if connection can be kept alive.
301

            
update Mojolicious to 4.57
Yuki Kimoto authored on 2013-12-02
302
=head2 redirects
303

            
304
  my $redirects = $tx->redirects;
305

            
306
Return a list of all previous transactions that preceded this followup
307
transaction.
308

            
309
  # Paths of all previous requests
310
  say $_->req->url->path for @{$tx->redirects};
311

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
312
=head2 server_read
copy gitweblite soruce code
root authored on 2012-11-23
313

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
314
  $tx->server_read($bytes);
copy gitweblite soruce code
root authored on 2012-11-23
315

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
316
Read data server-side, used to implement web servers.
copy gitweblite soruce code
root authored on 2012-11-23
317

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
318
=head2 server_write
copy gitweblite soruce code
root authored on 2012-11-23
319

            
update Mojolicious and added...
Yuki Kimoto authored on 2013-03-20
320
  my $bytes = $tx->server_write;
copy gitweblite soruce code
root authored on 2012-11-23
321

            
upgraded Mojolicious to v3.7...
Yuki Kimoto authored on 2013-01-28
322
Write data server-side, used to implement web servers.
copy gitweblite soruce code
root authored on 2012-11-23
323

            
324
=head1 SEE ALSO
325

            
326
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
327

            
328
=cut