Apache Emulation Part 5

So in the previous post we were able to proxy and http request to mod-jaxer by mimicking the format that Apache uses to pass to modules. And we were able to get the point to where we get a response from Jaxer. And Jaxer uses the same format to return a response that we use to pass in.

And it response type looks very similar to the request that we pass into it with a few exceptions. The response starts with the byte 0x02 and then jumps to 0x04. So I think that the leading byte might indicate the type of content that is contained with in each block. 0x01 seems to headers from the client, 0x02 seems to be headers relating to the response, 0x03 seem to be server-side parameters and 0x04 seems to be used for the body.

All of this is probably heavily documented somewhere if I knew the right keywords to use. At this point I’m beginning to think that this might simply be a raw look at the raw http protocol. In most cases I’ve only had the experience of interacting with http through either the browser or Nodejs, so I’m not familiar with the exact sequence of bytes being exchanged over tcp. Assuming it is http, that might allow us to greatly simply our program in the future, but for now our franken-code is working and functional.

function json_binary(src) {

    const header = {
        "client" : {},
        "file" : {},
        "server" : {},
        "body" : null
    };


    const types = Object.keys(header);
    let pos = 0;

    console.log("Converting response from jaxer");
    console.log("Source length: 0x%s", src.length.toString(16));

    while(pos < src.length) {

        let byte = src.readUInt8(pos);
        let len = src.readUInt16BE(pos + 1);

        console.log("aaa");
        console.log(byte);

        if(byte === 7) {
            break;
        }

        pos += 3;
        let snap = pos + len;
        const type = types[byte - 1];

        console.log("Found type: %s", type);

        switch(type) {
        case "client":
        case "file":
        case "server":

            let pairs = src.readUInt8(pos + 1);
            console.log("There are %s pairs", pairs);
            pos += 3;

            for(let i = 0; i < pairs; i++) {

                let key = "";
                let value = "";

                let key_len = src.readUInt8(pos++);
                for(let k = 0; k < key_len; k++) {
                    byte = src.readUInt8(pos++);
                    key += String.fromCharCode(byte);
                }
                pos++;

                let val_len = src.readUInt8(pos++);
                for(let k = 0; k < val_len; k++) {
                    byte = src.readUInt8(pos++);
                    value += String.fromCharCode(byte);
                }
                pos++;

                header[type][key] = value;
            }

            break;
        case "body":

            header.body = src.subarray(pos, pos + len);
            break;
        }

        console.log("Setting potision to 0x%s", snap.toString(16));
        console.log("bbb");
        pos = snap;

    }

    return header;

}

The code for taking the response back from mod-Jaxer and then converting it into a list of key-value headers and content body are shown above. If it is a http response that could mean that the easiest approach might be to proxy the response directly back to the client, but this is what we have to work with in terms of working with the createServer http function. So while it’s not pretty or optimized it does work, and right now the priority is one simplifying our Aptana Jaxer code to work towards a simple modular runtime environment.

Which means now that we have a method of interacting with and passing information between the client browser and the Aptana Jaxer mod-jaxer process via a self-written Nodejs http server. So now that we’re able to handle basic requests and get a response from Jaxer, the next step will be to look into the server-callback uri where requests Ajax requests are sent from the client to be handled by Jaxer.