MtGox websockets api devolviendo "400 Bad Request"

Quiero comenzar con la API de websockets de Mt. Gox, pero parece que no puedo obtener una buena respuesta del servidor.

Estoy enviando lo siguiente (capturado con Wireshark):

GET /mtgox HTTP/1.1
User-Agent: websocket-sharp/1.0
Upgrade: websocket
Connection: Upgrade
Host: websocket.mtgox.com
Sec-WebSocket-Key: LtH+YFgnW1N8KDLDbocsUQ==
Sec-WebSocket-Version: 13

y el servidor responde:

HTTP/1.1 400 Bad Request

Intenté enviar el protocolo de enlace a través de telnet y con este código C# y sigo recibiendo un error de solicitud incorrecta 400:

class Program
{
    static void Main(string[] args)
    {
        ClientWebSocket ws = new ClientWebSocket();
        Task connectionTask = ws.ConnectAsync(new Uri("ws://websocket.mtgox.com/mtgox"), CancellationToken.None);
        Console.Write("Connecting");
        while (!connectionTask.IsCompleted)
        {
            Console.Write(".");
            Thread.Sleep(100);
        }
        Console.WriteLine(ws.State);
    }
}

(La última línea impresa es "Cerrado" y cuando inspecciono el apretón de manos con Wireshark veo las mismas 400 Bad Request)

¿Alguna idea de lo que estoy haciendo mal? No puedo ver mucha documentación o muestras usando la API de websockets, así que realmente no tengo nada con lo que comparar :(

En respuesta a la sugerencia de sta, probé esto (usando WebsocketSharp):

static void Main(string[] args)
{
    WebSocket ws = new WebSocket("ws://websocket.mtgox.com/mtgox");
    ws.Origin = "http://websocket.mtgox.com";
    ws.Connect();
    ws.OnMessage += (sender, e) =>
    {
        if (!String.IsNullOrEmpty(e.Data))
        {
            Console.WriteLine("{0}", e.Data);
        }
    };
    Console.WriteLine("{0}", ws.IsAlive);
    Console.ReadLine();
}

Esto muestra FALSEque todavía hay algo que estoy haciendo mal: / Sin embargo, aún no he tenido la oportunidad de profundizar en WebSocketSharp

Actualización: con WebsocketSharp configurando el encabezado Origin correctamente, Wireshark muestra que el servidor mtgox acepta la actualización de websocket:

HTTP/1.1 101 Switching Protocols\r\n
Upgrade: websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Accept: 2+1ghzJ/Itt6w1aBdUteghcsJHk=\r\n
\r\n

Pero WebSocketSharp aún informa que la conexión está cerrada :(

Es gracioso, acabo de notar lo mismo, pero estoy escribiendo un cliente websocket para node.js.
Parece haber una gran diferencia entre el servidor websocket.mtgox.com/mtgox y socketio.mtgox.com/mtgox... La muestra que Loourr publicó a continuación funciona para socketio (apretón de manos ligeramente diferente) pero todavía no estoy seguro de por qué no se puede conectar al websocket one (con C# WebSockets o esta implementación de websockets para el nodo: github.com/Worlize/WebSocket-Node )
¿Puedo intentar hacerlo con otro canal? ticker.BTCEUR,ticker.BTCAUD... etc. Saludos cordiales.

Respuestas (2)

Parece que el cliente debería enviar el encabezado Origin al abrir el protocolo de enlace al servidor MtGox.

Si usa websocket-sharp actual, debe hacer lo siguiente antes de conectarse.

ws.Origin = "http://websocket.mtgox.com";

¿Podrías intentarlo?

Actualizar:

¿Podrías intentar de nuevo con el siguiente código?

static void Main(string[] args)
{
    var ws = new WebSocket("ws://websocket.mtgox.com/mtgox?Currency=USD");
    ws.Origin = "http://websocket.mtgox.com";
    ws.OnOpen += (sender, e) =>
    {
      ws.Send(
@"{
    ""op"": ""unsubscribe"",
    ""channel"": ""d5f06780-30a8-4a48-a2f8-7ed181b4a13f""
}"
      );
    };
    ws.OnMessage += (sender, e) =>
    {
        if (!String.IsNullOrEmpty(e.Data))
        {
            Console.WriteLine("{0}", e.Data);
        }
    };
    ws.Connect();
    Console.ReadLine();
    ws.Close();
}

Parece que se ha producido una excepción cuando el cliente recibe datos de tipo ticker desde hace un tiempo.

Investigaré un poco más.

Actualizar:

Descubrí la causa de la excepción y arreglé websocket-sharp.

¿Podría probar su código con websocket-sharp actual?

Acabo de probar esto y WebsocketSharp informa que la conexión está cerrada: (agregué el código a la pregunta)
¡Esto usando wss:// funciona!

Para uno, la URL debe ser websocket.mtgox.com/mtgox. Aquí hay un proyecto de muestra que usa la biblioteca node.js socket.io.

No tengo mucha experiencia en C#, pero aquí hay una implementación en node.js

var io = require('socket.io-client');
var socket = io.connect( 'https://socketio.mtgox.com/mtgox' );

var message = {
  "op": "subscribe",
  "channel": "24e67e0d-1cad-4cc0-9e7a-f8523ef460fe" // this is the market depth channel
};

socket.send(JSON.stringify(message));

socket.on('message', function(message) { console.log(message); });

Esto registrará los cambios de profundidad del mercado en la consola.

No tengo reputación para votar :( ¡Sin embargo, gracias! Voy a tratar de descubrir cómo el apretón de manos de ejemplo de Node.JS es diferente... Cambiando mi código para conectarme a socketio.mtgox.com/mtgox en lugar de lo que yo tuvo como resultado que el servidor cerrara inmediatamente la conexión (ni siquiera envía una respuesta de solicitud incorrecta)
Me alegro de que haya ayudado. Sin embargo, puede aceptar una respuesta como correcta ;-)
Me gustaría usar la API websocket sin procesar. Socket.io crea malas abstracciones.