Skip to content

Commit

Permalink
fixed a few more portability issues
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Oct 3, 2011
1 parent 0aa18b7 commit fe4da1c
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 97 deletions.
3 changes: 2 additions & 1 deletion Changes
Expand Up @@ -6,7 +6,8 @@ This file documents the revision history for Perl extension Mojolicious.
- Improved message parser performance slightly.
- Improved resolver tests.
- Fixed small formatting bug in Mojo::Headers.
- Fixed Perl 5.12 compatibility.
- Fixed small proxy message generation bug.
- Fixed a few portability issues.

1.99 2011-09-29 00:00:00
- Deprecated direct hash access to the flash in
Expand Down
5 changes: 1 addition & 4 deletions lib/Mojo/HelloWorld.pm
Expand Up @@ -4,12 +4,10 @@ use Mojolicious::Lite;
# "Don't worry, son.
# I'm sure he's up in heaven right now laughing it up with all the other
# celebrities: John Dilinger, Ty Cobb, Joseph Stalin."
use Scalar::Util 'weaken';

# "Does whisky count as beer?"
app->log->level('error');
app->log->path(undef);

# "Does whisky count as beer?"
under '/diag' => sub {
shift->on_finish(sub { $ENV{MOJO_HELLO} = 'world' });
};
Expand Down Expand Up @@ -74,7 +72,6 @@ any '/proxy' => sub {
return $self->render_text('This is a blocking deployment environment!')
unless Mojo::IOLoop->is_running;
$self->render_later;
weaken $self;
$self->ua->get(
$non_blocking => sub {
my $res2 = pop->res;
Expand Down
27 changes: 15 additions & 12 deletions lib/Mojo/IOLoop/Client.pm
Expand Up @@ -2,6 +2,7 @@ package Mojo::IOLoop::Client;
use Mojo::Base 'Mojo::IOLoop::EventEmitter';

use IO::Socket::INET;
use Scalar::Util 'weaken';
use Socket qw/IPPROTO_TCP SO_ERROR TCP_NODELAY/;

# IPv6 support requires IO::Socket::IP
Expand All @@ -25,11 +26,7 @@ has resolver => sub {
sub DESTROY {
my $self = shift;
return if $self->{connected};
return unless my $resolver = $self->{resolver};
return unless my $loop = $resolver->ioloop;
return unless my $watcher = $loop->iowatcher;
$watcher->cancel($self->{timer}) if $self->{timer};
$watcher->remove($self->{handle}) if $self->{handle};
$self->_cleanup;
}

sub connect {
Expand All @@ -52,6 +49,15 @@ sub connect {
}
}

sub _cleanup {
my $self = shift;
return unless my $resolver = $self->{resolver};
return unless my $loop = $resolver->ioloop;
return unless my $watcher = $loop->iowatcher;
$watcher->cancel($self->{timer}) if $self->{timer};
$watcher->remove($self->{handle}) if $self->{handle};
}

sub _connect {
my ($self, $args) = @_;

Expand Down Expand Up @@ -86,6 +92,7 @@ sub _connect {
setsockopt $handle, IPPROTO_TCP, TCP_NODELAY, 1;

# TLS
weaken $self;
if ($args->{tls}) {

# No TLS support
Expand All @@ -97,11 +104,8 @@ sub _connect {
my %options = (
SSL_startHandshake => 0,
SSL_error_trap => sub {
my $handle = delete $self->{handle};
my $watcher = $self->resolver->ioloop->iowatcher;
$watcher->remove($handle);
$watcher->cancel($self->{timer});
close $handle;
$self->_cleanup;
close delete $self->{handle};
$self->emit(error => $_[1]);
},
SSL_cert_file => $args->{tls_cert},
Expand Down Expand Up @@ -147,8 +151,7 @@ sub _connecting {

# Connected
$self->{connected} = 1;
$watcher->cancel($self->{timer}) if $self->{timer};
$watcher->remove($handle);
$self->_cleanup;
$self->emit(connect => $handle);
}

Expand Down
16 changes: 2 additions & 14 deletions lib/Mojo/IOLoop/Stream.pm
Expand Up @@ -6,9 +6,6 @@ use Scalar::Util 'weaken';

use constant CHUNK_SIZE => $ENV{MOJO_CHUNK_SIZE} || 131072;

# Windows
use constant WINDOWS => $^O eq 'MSWin32' || $^O =~ /cygwin/ ? 1 : 0;

has iowatcher => sub {
require Mojo::IOLoop;
Mojo::IOLoop->singleton->iowatcher;
Expand Down Expand Up @@ -69,12 +66,6 @@ sub write {
# Prepare chunk for writing
$self->{buffer} .= $chunk;

# UNIX only quick write
unless (WINDOWS) {
local $self->{quick} = 1 if $cb;
$self->_write;
}

# Write with roundtrip
if ($cb) { $self->once(drain => $cb) }
else { return unless length $self->{buffer} }
Expand Down Expand Up @@ -114,7 +105,7 @@ sub _write {
my $self = shift;

# Handle drain
$self->emit('drain') if !length $self->{buffer} && !$self->{quick};
$self->emit('drain') if !length $self->{buffer};

# Write as much as possible
my $handle = $self->{handle};
Expand All @@ -140,10 +131,7 @@ sub _write {
}

# Stop writing
return
if length $self->{buffer}
|| $self->{quick}
|| @{$self->subscribers('drain')};
return if length $self->{buffer} || @{$self->subscribers('drain')};
$self->iowatcher->not_writing($handle);
}

Expand Down
16 changes: 9 additions & 7 deletions lib/Mojo/Message/Request.pm
Expand Up @@ -218,13 +218,6 @@ sub _build_start_line {
$path .= "?$query" if $query;
$path = "/$path" unless $path =~ /^\//;

# Proxy
if ($self->proxy) {
my $clone = $url = $url->clone;
$clone->userinfo(undef);
$path = $clone;
}

# CONNECT
my $method = uc $self->method;
if ($method eq 'CONNECT') {
Expand All @@ -233,6 +226,15 @@ sub _build_start_line {
$path = "$host:$port";
}

# Proxy
elsif ($self->proxy) {
my $clone = $url = $url->clone;
$clone->userinfo(undef);
$path = $clone
unless ($self->headers->upgrade || '') eq 'websocket'
|| ($url->scheme || '') eq 'https';
}

# HTTP 0.9
my $version = $self->version;
return "$method $path\x0d\x0a" if $version eq '0.9';
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/UserAgent.pm
Expand Up @@ -216,11 +216,11 @@ sub _connect {
my ($self, $tx, $cb) = @_;

# Keep alive connection
weaken $self;
my $loop = $self->_loop;
my $id = $tx->connection;
my ($scheme, $host, $port) = $self->transactor->peer($tx);
$id ||= $self->_cache("$scheme:$host:$port");
weaken $self;
if ($id && !ref $id) {
warn "KEEP ALIVE CONNECTION ($scheme:$host:$port)\n" if DEBUG;
$self->{connections}->{$id} = {cb => $cb, transaction => $tx};
Expand Down
9 changes: 2 additions & 7 deletions lib/Mojolicious/Plugin/EPRenderer.pm
Expand Up @@ -40,14 +40,9 @@ sub register {
unless ($cache->get($key)) {
my $mt = Mojo::Template->new($template);

# Self
my $prepend = 'my $self = shift;';

# Weaken
$prepend .= q/use Scalar::Util 'weaken'; weaken $self;/;

# Be a bit more relaxed for helpers
$prepend .= q/no strict 'refs'; no warnings 'redefine';/;
my $prepend = q/my $self = shift; use Scalar::Util 'weaken';/
. q/weaken $self; no strict 'refs'; no warnings 'redefine';/;

# Helpers
$prepend .= 'my $_H = $self->app->renderer->helpers;';
Expand Down
74 changes: 62 additions & 12 deletions t/mojo/message.t
Expand Up @@ -3,7 +3,7 @@ use Mojo::Base -strict;

use utf8;

use Test::More tests => 1176;
use Test::More tests => 1203;

use File::Spec;
use File::Temp;
Expand Down Expand Up @@ -162,7 +162,7 @@ $req->parse("Host: example.com\x0d\x0a");
$req->parse("Connection: Upgrade\x0d\x0a");
$req->parse("Sec-WebSocket-Key: abcdef=\x0d\x0a");
$req->parse("Sec-WebSocket-Protocol: sample\x0d\x0a");
$req->parse("Upgrade: WebSocket\x0d\x0a\x0d\x0a");
$req->parse("Upgrade: websocket\x0d\x0a\x0d\x0a");
ok $req->is_done, 'request is done';
is $req->method, 'GET', 'right method';
is $req->version, '1.1', 'right version';
Expand All @@ -173,7 +173,7 @@ is $req->headers->host, 'example.com', 'right "Host" value';
is $req->headers->connection, 'Upgrade', 'right "Connection" value';
is $req->headers->sec_websocket_protocol, 'sample',
'right "Sec-WebSocket-Protocol" value';
is $req->headers->upgrade, 'WebSocket', 'right "Upgrade" value';
is $req->headers->upgrade, 'websocket', 'right "Upgrade" value';
is $req->headers->sec_websocket_key, 'abcdef=',
'right "Sec-WebSocket-Key" value';
is $req->body, '', 'no content';
Expand Down Expand Up @@ -833,7 +833,7 @@ $req->headers->host('example.com');
$req->headers->connection('Upgrade');
$req->headers->sec_websocket_accept('abcdef=');
$req->headers->sec_websocket_protocol('sample');
$req->headers->upgrade('WebSocket');
$req->headers->upgrade('websocket');
$req = Mojo::Message::Request->new->parse($req->to_string);
ok $req->is_done, 'request is done';
is $req->method, 'GET', 'right method';
Expand All @@ -843,7 +843,7 @@ is $req->at_least_version('1.2'), undef, 'not version 1.2';
is $req->url, '/demo', 'right URL';
is $req->url->to_abs, 'http://example.com/demo', 'right absolute URL';
is $req->headers->connection, 'Upgrade', 'right "Connection" value';
is $req->headers->upgrade, 'WebSocket', 'right "Upgrade" value';
is $req->headers->upgrade, 'websocket', 'right "Upgrade" value';
is $req->headers->host, 'example.com', 'right "Host" value';
is $req->headers->content_length, 0, 'right "Content-Length" value';
is $req->headers->sec_websocket_accept, 'abcdef=',
Expand All @@ -862,7 +862,7 @@ $req->headers->host('example.com');
$req->headers->connection('Upgrade');
$req->headers->sec_websocket_accept('abcdef=');
$req->headers->sec_websocket_protocol('sample');
$req->headers->upgrade('WebSocket');
$req->headers->upgrade('websocket');
$clone = $req->clone;
$req = Mojo::Message::Request->new->parse($req->to_string);
ok $req->is_done, 'request is done';
Expand All @@ -873,7 +873,7 @@ is $req->at_least_version('1.2'), undef, 'not version 1.2';
is $req->url, '/demo', 'right URL';
is $req->url->to_abs, 'http://example.com/demo', 'right absolute URL';
is $req->headers->connection, 'Upgrade', 'right "Connection" value';
is $req->headers->upgrade, 'WebSocket', 'right "Upgrade" value';
is $req->headers->upgrade, 'websocket', 'right "Upgrade" value';
is $req->headers->host, 'example.com', 'right "Host" value';
is $req->headers->content_length, 0, 'right "Content-Length" value';
is $req->headers->sec_websocket_accept, 'abcdef=',
Expand All @@ -891,7 +891,7 @@ is $clone->at_least_version('1.2'), undef, 'not version 1.2';
is $clone->url, '/demo', 'right URL';
is $clone->url->to_abs, 'http://example.com/demo', 'right absolute URL';
is $clone->headers->connection, 'Upgrade', 'right "Connection" value';
is $clone->headers->upgrade, 'WebSocket', 'right "Upgrade" value';
is $clone->headers->upgrade, 'websocket', 'right "Upgrade" value';
is $clone->headers->host, 'example.com', 'right "Host" value';
is $clone->headers->content_length, 0, 'right "Content-Length" value';
is $clone->headers->sec_websocket_accept, 'abcdef=',
Expand All @@ -901,6 +901,36 @@ is $clone->headers->sec_websocket_protocol, 'sample',
is $clone->body, '', 'no content';
ok $clone->is_done, 'request is done';

# Build WebSocket handshake proxy request
$req = Mojo::Message::Request->new;
$req->method('GET');
$req->url->parse('http://example.com/demo');
$req->headers->host('example.com');
$req->headers->connection('Upgrade');
$req->headers->sec_websocket_accept('abcdef=');
$req->headers->sec_websocket_protocol('sample');
$req->headers->upgrade('websocket');
$req->proxy('http://127.0.0.2:8080');
$req = Mojo::Message::Request->new->parse($req->to_string);
ok $req->is_done, 'request is done';
is $req->method, 'GET', 'right method';
is $req->version, '1.1', 'right version';
is $req->at_least_version('1.0'), 1, 'at least version 1.0';
is $req->at_least_version('1.2'), undef, 'not version 1.2';
is $req->url, '/demo', 'right URL';
is $req->url->to_abs, 'http://example.com/demo', 'right absolute URL';
is $req->headers->connection, 'Upgrade', 'right "Connection" value';
is $req->headers->upgrade, 'websocket', 'right "Upgrade" value';
is $req->headers->host, 'example.com', 'right "Host" value';
is $req->headers->content_length, 0, 'right "Content-Length" value';
is $req->headers->sec_websocket_accept, 'abcdef=',
'right "Sec-WebSocket-Key" value';
is $req->headers->sec_websocket_protocol, 'sample',
'right "Sec-WebSocket-Protocol" value';
is $req->body, '', 'no content';
ok $finished, 'finish callback was called';
ok $req->is_done, 'request is done';

# Build full HTTP 1.1 proxy request
$req = Mojo::Message::Request->new;
$req->method('GET');
Expand All @@ -921,6 +951,26 @@ is $req->headers->host, '127.0.0.1', 'right "Host" value';
is $req->headers->content_length, '13', 'right "Content-Length" value';
is $req->body, "Hello World!\n", 'right content';

# Build full HTTP 1.1 proxy request (HTTPS)
$req = Mojo::Message::Request->new;
$req->method('GET');
$req->url->parse('https://127.0.0.1/foo/bar');
$req->headers->expect('100-continue');
$req->body("Hello World!\n");
$req->proxy('http://127.0.0.2:8080');
$req = Mojo::Message::Request->new->parse($req->to_string);
ok $req->is_done, 'request is done';
is $req->method, 'GET', 'right method';
is $req->version, '1.1', 'right version';
is $req->at_least_version('1.0'), 1, 'at least version 1.0';
is $req->at_least_version('1.2'), undef, 'not version 1.2';
is $req->url, '/foo/bar', 'right URL';
is $req->url->to_abs, 'http://127.0.0.1/foo/bar', 'right absolute URL';
is $req->headers->expect, '100-continue', 'right "Expect" value';
is $req->headers->host, '127.0.0.1', 'right "Host" value';
is $req->headers->content_length, '13', 'right "Content-Length" value';
is $req->body, "Hello World!\n", 'right content';

# Build full HTTP 1.1 proxy request with basic authorization
$req = Mojo::Message::Request->new;
$req->method('GET');
Expand Down Expand Up @@ -1966,7 +2016,7 @@ is $res->cookie('foo')->path, '/test', 'right path';
# Parse WebSocket handshake response
$res = Mojo::Message::Response->new;
$res->parse("HTTP/1.1 101 Switching Protocols\x0d\x0a");
$res->parse("Upgrade: WebSocket\x0d\x0a");
$res->parse("Upgrade: websocket\x0d\x0a");
$res->parse("Connection: Upgrade\x0d\x0a");
$res->parse("Sec-WebSocket-Accept: abcdef=\x0d\x0a");
$res->parse("Sec-WebSocket-Protocol: sample\x0d\x0a\x0d\x0a");
Expand All @@ -1976,7 +2026,7 @@ is $res->message, 'Switching Protocols', 'right message';
is $res->version, '1.1', 'right version';
is $res->at_least_version('1.0'), 1, 'at least version 1.0';
is $res->at_least_version('1.2'), undef, 'not version 1.2';
is $res->headers->upgrade, 'WebSocket', 'right "Upgrade" value';
is $res->headers->upgrade, 'websocket', 'right "Upgrade" value';
is $res->headers->connection, 'Upgrade', 'right "Connection" value';
is $res->headers->sec_websocket_accept, 'abcdef=',
'right "Sec-WebSocket-Accept" value';
Expand All @@ -1988,7 +2038,7 @@ is $res->body, '', 'no content';
$res = Mojo::Message::Response->new;
$res->code(101);
$res->headers->date('Sun, 17 Aug 2008 16:27:35 GMT');
$res->headers->upgrade('WebSocket');
$res->headers->upgrade('websocket');
$res->headers->connection('Upgrade');
$res->headers->sec_websocket_accept('abcdef=');
$res->headers->sec_websocket_protocol('sample');
Expand All @@ -2001,7 +2051,7 @@ is $res->at_least_version('1.0'), 1, 'at least version 1.0';
is $res->at_least_version('1.2'), undef, 'not version 1.2';
is $res->headers->connection, 'Upgrade', 'right "Connection" value';
is $res->headers->date, 'Sun, 17 Aug 2008 16:27:35 GMT', 'right "Date" value';
is $res->headers->upgrade, 'WebSocket', 'right "Upgrade" value';
is $res->headers->upgrade, 'websocket', 'right "Upgrade" value';
is $res->headers->content_length, 0, 'right "Content-Length" value';
is $res->headers->sec_websocket_accept, 'abcdef=',
'right "Sec-WebSocket-Accept" value';
Expand Down

0 comments on commit fe4da1c

Please sign in to comment.