Search code examples
haxehashlink

Reading a HTTP request with sockets on HashLink


I'm trying to make a HTTP server using haxe (4) with HashLink (1.9.0) and sockets doesn't seems to work very well.

import haxe.io.Error;
import sys.net.Host;
import sys.net.Socket;

class Main {
    static public function main() {

        var _aSocketDistant = new List<Socket>();

        var _oSocketMaster = new Socket();
        _oSocketMaster.bind( new Host( 'localhost' ), 8000);
        _oSocketMaster.setBlocking( false );
        _oSocketMaster.listen( 9999 );

        while(true) {

            // Accepting socket
            var oSocketDistant = _oSocketMaster.accept();
            if ( oSocketDistant != null ) {
                trace( 'opening : ' + oSocketDistant.peer() );
                oSocketDistant.setBlocking( false );
                _aSocketDistant.add( oSocketDistant );
            }

            // Trying to read from each socket 
            for ( oSocketDistant in _aSocketDistant ) {
                try {
                    trace( oSocketDistant.read() );
                } catch ( e :Dynamic ) {
                    if ( e != Error.Blocked )
                        throw e;
                }
            }

        }
    }
}

Running this bit of code and then calling http://localhost:8000/ using firefox gets me the following :

Main.hx:27: opening : {host : 127.0.0.1, port : 65154}

The distant socket never have any message to be read. Shouldn't it send the request?


Solution

  • The problem seems to be the use of read(). It seems this is not meant to be used on non-blocking sockets:

    Your actual issue is that read() will read the whole data. On a blocking socket that would block until the connection is closed. On a non blocking socket that will always raise Blocking. You instead have to use input.readBytes which will return the number of bytes read, and then make sure you correctly manage your buffer data.

    In this case, using input.readLine() is probably the easiest solution:

    trace(oSocketDistant.input.readLine());
    

    With that, I can see the HTTP request as expected:

    Main.hx:20: opening : {host : 127.0.0.1, port : 50231}
    Main.hx:29: GET / HTTP/1.1
    Main.hx:29: Host: localhost:8008
    Main.hx:29: Connection: keep-alive
    Main.hx:29: Upgrade-Insecure-Requests: 1
    Main.hx:29: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36
    Main.hx:29: DNT: 1
    Main.hx:29: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
    Main.hx:29: Accept-Encoding: gzip, deflate, br
    Main.hx:29: Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
    Main.hx:29: Cookie: Idea-369662de=0cbb3289-7f2c-4f82-a094-7409dba8cfb0
    Main.hx:29: