400 - Bad request in firefox and chrome for websockets

2,486 views
Skip to first unread message

vlad....@gmail.com

unread,
Aug 9, 2014, 4:32:03 PM8/9/14
to ratch...@googlegroups.com
The only issue is the websocket connect - i'm not able to make one. The http and the socket connection work without any issues.

Headers sent by firefox for websocket:
(Request-Line) GET / HTTP/1.1
Host localhost:9999
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language en-US,en;q=0.5
Accept-Encoding gzip, deflate
Sec-WebSocket-Version 13
Origin http://localhost:8080
Sec-WebSocket-Key qFgapj5i/4X84InTFx1/KQ==
Connection keep-alive, Upgrade
Pragma no-cache
Cache-Control no-cache
Upgrade websocket

Got back from php code
(Status-Line) HTTP/1.1 400 Bad Request
X
-Powered-By Ratchet/0.3.2


Headers sent by chrome
    Provisional headers are shown
    Cache-Control: no-cache
    Connection:Upgrade
    Host: localhost:9999
    Origin: http://localhost:8080
    Pragma: no-cache
    Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame
    Sec-WebSocket-Key: dkUN6SpXshMhANfKnEXrxg==
    Sec-WebSocket-Version: 13
    Upgrade: websocket
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36

Frames in chrome network debugger window
Error during WebSocket handshake: Unexpected response code: 400

Small modification to IoServer.php - added a new parameter $loop to be able to start multiple servers at once 

public static function factory(MessageComponentInterface $component, $port = 80, $address = '0.0.0.0',$loop=false) {
 
if($loop===false){
   $loop  
= LoopFactory::create();
 
}
 
//rest of normal code
}

code
<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;


//use MyApp\WebApp;


require ('./vendor/autoload.php');


$Config
=array();


//http
$Config
['HttpInterface' ]= '0.0.0.0';
$Config
['HttpPort' ]= 8080;


//web socket
$Config
['WebsocketInterface']= '0.0.0.0';
$Config
['WebsocketPort' ]= 9999;


//raw socket
$Config
['SocketInterface' ]= '0.0.0.0';
$Config
['SocketPort' ]= 8888;


//loop
$loop
= React\EventLoop\Factory::create();


class Chat implements Ratchet\MessageComponentInterface {
   
protected $clients;


   
public function __construct() {
        $this
->clients = new \SplObjectStorage;
   
}


   
public function onOpen(Ratchet\ConnectionInterface $conn) {
       
// Store the new connection to send messages to later
        $this
->clients->attach($conn);


        echo
"New connection! ({$conn->resourceId})\n";
   
}


   
public function onMessage(Ratchet\ConnectionInterface $from, $msg) {
        $numRecv
= count($this->clients) - 1;
        echo sprintf
('Connection %d sending message "%s" to %d other connection%s' . "\n"
           
, $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');


       
foreach ($this->clients as $client) {
           
if ($from !== $client) {
               
// The sender is not the receiver, send to each client connected
                $client
->send($msg);
           
}
       
}
   
}


   
public function onClose(Ratchet\ConnectionInterface $conn) {
       
// The connection is closed, remove it, as we can no longer send it messages
        $this
->clients->detach($conn);


        echo
"Connection {$conn->resourceId} has disconnected\n";
   
}


   
public function onError(Ratchet\ConnectionInterface $conn, \Exception $e) {
        echo
"An error has occurred: {$e->getMessage()}\n";


        $conn
->close();
   
}
}




$HttpApp
= function ($request, $response) use ($Config){
 $response
->writeHead(200,array('Content-Type'=>'text/html'));
 $response
->end(
"<script type=\"text/javascript\">
console.log('starting...');
setTimeout(function(){
console.log('starting connection...');
var conn = new WebSocket('ws://localhost:"
.$Config['WebsocketPort']."');
conn.onopen = function(e) {
    console.log(\"Connection established!\");
};
conn.onopen = function(e){
 console.log(e);
}
conn.onmessage = function(e) {
    console.log(e.data);
};
conn.onerror = function(err){
 console.log(err);
}
},1000);
</script>
"

);
};


//Servers
$Servers
=array();


//Server: WebSocket
$Servers
['WebSocket']=array();
$Servers
['WebSocket']['Server']=IoServer::factory(
   
new HttpServer(
       
new WsServer(
           
new Chat()
       
)
   
)
   
,$Config['WebsocketPort']
   
,$Config['WebsocketInterface']
   
,$loop
);


//Server: TCP Socket
$Servers
['TCP']=array();
$Servers
['TCP']['Server'] = IoServer::factory(
     
new Chat()
   
,$Config['SocketPort']
   
,$Config['SocketInterface']
   
,$loop
);


//Server: Http
$Servers
['HTTP']=array();
$Servers
['HTTP']['Socket'] = new React\Socket\Server($loop);
$Servers
['HTTP']['Http'] = new React\Http\Server($Servers['HTTP']['Socket'], $loop);
$Servers
['HTTP']['Http'] ->on('request', $HttpApp);
$Servers
['HTTP']['Socket'] ->listen($Config['HttpPort']);




$loop
->run();


OS: Windows 7
Php information:
PHP 5.5.4 (cli) (built: Sep 18 2013 13:04:23)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies

No libevent/etc installed

vb

unread,
Aug 11, 2014, 1:44:45 AM8/11/14
to ratch...@googlegroups.com

 Did the default example with websockets, with a fresh install from composer - same issue...

<?php
use Ratchet\Server\IoServer;

require './vendor/autoload.php';


class Chat implements Ratchet\MessageComponentInterface {
   
protected $clients;

   
public function __construct() {
        $this
->clients = new \SplObjectStorage;
   
}

   
public function onOpen(Ratchet\ConnectionInterface $conn) {
       
// Store the new connection to send messages to later
        $this
->clients->attach($conn);

        echo
"New connection! ({$conn->resourceId})\n";
   
}

   
public function onMessage(Ratchet\ConnectionInterface $from, $msg) {
        $numRecv
= count($this->clients) - 1;
        echo sprintf
('Connection %d sending message "%s" to %d other connection%s' . "\n"
           
, $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

       
foreach ($this->clients as $client) {
           
if ($from !== $client) {
               
// The sender is not the receiver, send to each client connected
                $client
->send($msg);
           
}
       
}
   
}

   
public function onClose(Ratchet\ConnectionInterface $conn) {
       
// The connection is closed, remove it, as we can no longer send it messages
        $this
->clients->detach($conn);

        echo
"Connection {$conn->resourceId} has disconnected\n";
   
}

   
public function onError(Ratchet\ConnectionInterface $conn, \Exception $e) {
        echo
"An error has occurred: {$e->getMessage()}\n";

        $conn
->close();
   
}
}


$server
= IoServer::factory(
       
new Ratchet\Http\HttpServer(
           
new Ratchet\WebSocket\WsServer(
               
new Chat()
           
)
       
),
       
8080
   
);

$server
->run();


vb

unread,
Aug 11, 2014, 3:13:29 AM8/11/14
to ratch...@googlegroups.com
Seems the issue on the websocket example is only on windows. Switched to my ubuntu pc and all code runs fine.



   
public function onError(Ratchet\ConnectionInterface $conn,<span style="colo
...

cboden

unread,
Aug 16, 2014, 9:09:41 AM8/16/14
to ratch...@googlegroups.com
Unfortunately I don't have Windows to test this, but my best guess is one of the assertions in the Handshake Verifier are failing. If one of the conditions fails the server responds with a 400 error. 

Vlad Babii

unread,
Aug 16, 2014, 9:12:05 AM8/16/14
to ratch...@googlegroups.com

I will try to debug this.

Did you know these work on open wrt?

--

---
You received this message because you are subscribed to a topic in the Google Groups "Ratchet" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ratchet-php/IjFBcsWJa8A/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ratchet-php...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

cboden

unread,
Aug 16, 2014, 9:18:02 AM8/16/14
to ratch...@googlegroups.com, e...@vladbabii.com
Excellent, thank you! I'm not sure, in theory if wrt supports TCP, UTF-8 and PHP it should be ok.
To unsubscribe from this group and all its topics, send an email to ratchet-php+unsubscribe@googlegroups.com.

Vlad Babii

unread,
Aug 16, 2014, 9:24:47 AM8/16/14
to ratch...@googlegroups.com

I'm building a open wrt mesh with mr3020s for home automation and control everything with a distributed php framework.  Switching from nodes got me from 20 MB ram to 3 so I have a lot more room to work with.  If you're interested I could post the code when the prototype is ready....

To unsubscribe from this group and all its topics, send an email to ratchet-php...@googlegroups.com.

cboden

unread,
Aug 17, 2014, 7:48:29 AM8/17/14
to ratch...@googlegroups.com, e...@vladbabii.com
That sounds awesome! Yes, please post stuff when you can!

vb

unread,
Aug 28, 2014, 6:56:32 AM8/28/14
to ratch...@googlegroups.com, e...@vladbabii.com
This check fails:

public function verifyKey($val) {
        var_dump
($val);   // string(24) "zyaDPNPpaGmi8BM5VUzTaQ=="                                
        var_dump
(base64_decode((string)$val)); // string(16) "╧&â<╙Θhió≡‼9UL╙i"
        var_dump
(strlen(base64_decode((string)$val))); // int(10)
       
return (16 === strlen(base64_decode((string)$val)));
   
}

Any hints?

php --version
PHP
5.5.15 (cli) (built: Jul 23 2014 15:05:09)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
To unsubscribe from this group and all its topics, send an email to ratchet-php...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--

---
You received this message because you are subscribed to a topic in the Google Groups "Ratchet" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ratchet-php/IjFBcsWJa8A/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ratchet-php...@googlegroups.com.

vb

unread,
Aug 28, 2014, 7:00:57 AM8/28/14
to ratch...@googlegroups.com, e...@vladbabii.com
It's from mbstring.If i set mbstring.func_overload = 0 then it works. 
Can i just check if sltren($val) == 24 ?

vb

unread,
Aug 28, 2014, 7:29:32 AM8/28/14
to ratch...@googlegroups.com
I changed the function to

public function verifyKey($val) {
       
return (16 === strlen(base64_decode((string)$val)) || ( (int)ini_get('mbstring.func_overload') & 2 && 16 === mb_strlen(utf8_encode(base64_decode((string)$val)))));
}

and it works (tested over 10.000 connections). Hopefully it's something you can apply to head revision. If it wasn't for your hint it would have taken me a lot more to find it, so thank you again!

cboden

unread,
Aug 29, 2014, 7:49:17 AM8/29/14
to ratch...@googlegroups.com
Oh no! func_overload MUST be set to 0 to use Ratchet. I initially supported it until I got further into it and understanding UTF-8 better. func_overload is evil and should never ever be used (IMHO).

Vlad Babii

unread,
Aug 29, 2014, 8:10:02 AM8/29/14
to ratch...@googlegroups.com
It works fine with that change. I'm running the same code on windows
7/8, linux (4 flavors), openwrt (~9 different router models), freebsd
and few others small systems (raspberry, etc) with different
configurations that I cannot easily change because of legacy software.
If I find anymore issues i will post in this thread.

scorpi...@gmail.com

unread,
Jan 11, 2016, 9:37:40 AM1/11/16
to Ratchet
Try to check your final request. I have the same problem with CloudFlare firewall, it removes Update and Connection fields. The only way to override WsServer::onOpen and add the fields manually
...
Reply all
Reply to author
Forward
0 new messages