Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
add support for WebSockets over UNIX domain sockets
  • Loading branch information
kraih committed Feb 23, 2017
1 parent d49db3c commit 00625bc
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 6 deletions.
4 changes: 2 additions & 2 deletions lib/Mojo/UserAgent.pm
Expand Up @@ -413,8 +413,8 @@ Mojo::UserAgent - Non-blocking I/O HTTP and WebSocket user agent
}
)->wait;
# WebSocket connection sending and receiving JSON messages
$ua->websocket('ws://example.com/echo.json' => sub {
# WebSocket connection sending and receiving JSON via UNIX domain socket
$ua->websocket('ws+unix://%2Ftmp%2Fmyapp.sock/echo.json' => sub {
my ($ua, $tx) = @_;
say 'WebSocket handshake failed!' and return unless $tx->is_websocket;
$tx->on(json => sub {
Expand Down
4 changes: 3 additions & 1 deletion lib/Mojo/UserAgent/Transactor.pm
Expand Up @@ -145,7 +145,9 @@ sub websocket {
$req->headers->sec_websocket_protocol(join ', ', @$sub) if @$sub;
my $url = $req->url;
my $proto = $url->protocol;
$url->scheme($proto eq 'wss' ? 'https' : 'http') if $proto;
$url->scheme(
$proto eq 'ws+unix' ? 'http+unix' : $proto eq 'wss' ? 'https' : 'http')
if $proto;

# Handshake
return client_handshake $tx;
Expand Down
45 changes: 42 additions & 3 deletions t/mojo/daemon_unix.t
Expand Up @@ -21,7 +21,10 @@ use Mojolicious::Lite;
# Silence
app->log->level('fatal');

get '/' => {text => 'works!'};
get '/' => sub {
my $c = shift;
$c->render(text => $c->req->url);
};

get '/info' => sub {
my $c = shift;
Expand All @@ -32,6 +35,11 @@ get '/info' => sub {
$c->render(text => "$local_address:$local_port:$remote_address:$remote_port");
};

websocket '/echo' => sub {
my $c = shift;
$c->on(message => sub { shift->send(shift)->finish });
};

# UNIX domain socket server
my $test = $dir->child('test.sock');
my $encoded = url_escape "$test";
Expand All @@ -49,14 +57,45 @@ like $ENV{MOJO_REUSE}, qr/^unix:\Q$test\E:\Q$fd\E/,
# Root
my $ua = Mojo::UserAgent->new(ioloop => $daemon->ioloop);
my $tx = $ua->get("http+unix://$encoded/");
is $tx->res->code, 200, 'right status';
is $tx->res->body, 'works!', 'right content';
ok !$tx->kept_alive, 'connection was not kept alive';
is $tx->res->code, 200, 'right status';
is $tx->res->body, '/', 'right content';
$tx = $ua->get("http+unix://$encoded/");
ok $tx->kept_alive, 'connection was kept alive';
is $tx->res->code, 200, 'right status';
is $tx->res->body, '/', 'right content';

# Connection information
$tx = $ua->get("http+unix://$encoded/info");
is $tx->res->code, 200, 'right status';
is $tx->res->body, 'None:None:None:None', 'right content';

# WebSocket
my $result;
$ua->websocket(
"ws+unix://$encoded/echo" => sub {
my ($ua, $tx) = @_;
$tx->on(finish => sub { Mojo::IOLoop->stop });
$tx->on(message => sub { shift->finish; $result = shift });
$tx->send('roundtrip works!');
}
);
Mojo::IOLoop->start;
is $result, 'roundtrip works!', 'right result';

# WebSocket again
$result = undef;
$ua->websocket(
"ws+unix://$encoded/echo" => sub {
my ($ua, $tx) = @_;
$tx->on(finish => sub { Mojo::IOLoop->stop });
$tx->on(message => sub { shift->finish; $result = shift });
$tx->send('roundtrip works!');
}
);
Mojo::IOLoop->start;
is $result, 'roundtrip works!', 'right result';

# Cleanup
undef $daemon;
ok !$ENV{MOJO_REUSE}, 'environment is clean';
Expand Down
14 changes: 14 additions & 0 deletions t/mojo/transactor.t
Expand Up @@ -558,6 +558,20 @@ ok $tx->req->headers->sec_websocket_version,
'has "Sec-WebSocket-Version" value';
is $tx->req->headers->upgrade, 'websocket', 'right "Upgrade" value';

# WebSocket handshake with UNIX domain socket
$tx = $t->websocket('ws+unix://%2Ftmp%2Fmyapp.sock/echo' => {DNT => 1});
is $tx->req->url->to_abs, 'http+unix://%2Ftmp%2Fmyapp.sock/echo', 'right URL';
is $tx->req->method, 'GET', 'right method';
is $tx->req->headers->dnt, 1, 'right "DNT" value';
is $tx->req->headers->connection, 'Upgrade', 'right "Connection" value';
is length(b64_decode $tx->req->headers->sec_websocket_key), 16,
'16 byte "Sec-WebSocket-Key" value';
ok !$tx->req->headers->sec_websocket_protocol,
'no "Sec-WebSocket-Protocol" header';
ok $tx->req->headers->sec_websocket_version,
'has "Sec-WebSocket-Version" value';
is $tx->req->headers->upgrade, 'websocket', 'right "Upgrade" value';

# Proxy CONNECT
$tx = $t->tx(GET => 'HTTPS://sri:secr3t@mojolicious.org');
$tx->req->proxy(Mojo::URL->new('http://sri:secr3t@127.0.0.1:3000'));
Expand Down

0 comments on commit 00625bc

Please sign in to comment.