Skip to content

How to use the stream api over a socket connection

codefail edited this page Nov 8, 2012 · 6 revisions

The Stream API is for more advanced users.

The Stream API is pretty simple technology wise. It is a vanilla TCP port that treats every line sent to it as a faux-HTTP request. What does this mean? Once you connect to the socket you can make all the same API calls that you can over HTTP. However, you only write the part of URL after the port. In psuedocode (aka, a language I wish existed):

tcp_connection = tcp_connect('localhost', 20060)

// the server will always send responses on one line.
tcp_connection.on('line', function (line) {
    json = json.decode(line)
    if(json.result == "success") {
        // etc, etc, etc.
    }
})

// note the \r\n at the end, it is very important!
// this format is identical to a standard API request: [[Analyzing-the-jsonapi-request-and-response-format]] tcp_connection.write("/api/call?method=methodName&args=jsonEncodedAndRFC1738EncodedArgs&key=properKey&show_previous=trueOrFalse\n")

Note that although the server will always send responses on one line, they may not be in the same order that you called the methods in.

Now to subscribe to a stream, you use the format as described by "Stream API request" on Analyzing-the-jsonapi-request-and-response-format

tcp_connection.write("/api/subscribe?source={sourceName}&key={key}&show_previous={true|false}")

Say you subscribe to the "console" source (to view more information on the different kinds of stream sources, visit Stream-sources). The last 50 lines (unless you specify show_previous=false) that fall under that event will be sent to you as soon as you subscribe. This is so you can view a history in addition to real-time events. Everytime something is printed to the console, a line will be written to the TCP socket as a JSON message.

You can also stream over HTTP, but you can only make 1 stream subscription. To see a very simple example try this (the output will be the same on a TCP socket, the key generated is for the username "admin", the password "demo" and a salt of "". (Also notice that the port is 20059, not 20060 because this is on the HTTP server not the socket server):

$ curl -i "http://localhost:20059/api/subscribe?source=console&key=ebe26c33022316dc838c4320aee154cc8bdd611d78727090bebe38bd8f4aadc7"

HTTP/1.0 200 OK 
Content-Type: text/plain
Date: Tue, 3 May 2011 23:31:35 GMT

{"result":"success","source":"console","success":{"time":1304479894,"line":"2011-05-03 19:31:34 [INFO] Done (0.066s)! For help, type \\"help\\" or \\"?\\"\n"}}
{"result":"success","source":"console","success":{"time":1304479898,"line":"2011-05-03 19:31:38 [INFO] Unknown console command. Type \\"help\\" for help.\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO] To run the server without a gui, start it like this:\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    java -Xmx1024M -Xms1024M -jar minecraft_server.jar nogui\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO] Console commands:\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    help  or  ?               shows this message\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    kick <player>             removes a player from the server\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    ban <player>              bans a player from the server\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    pardon <player>           pardons a banned player so that they can connect again\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    ban-ip <ip>               bans an IP address from the server\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    pardon-ip <ip>            pardons a banned IP address so that they can connect again\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    op <player>               turns a player into an op\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    deop <player>             removes op status from a player\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    tp <player1> <player2>    moves one player to the same location as another player\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    give <player> <id> [num]  gives a player a resource\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    tell <player> <message>   sends a private message to a player\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    stop                      gracefully stops the server\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    save-all                  forces a server-wide level save\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    save-off                  disables terrain saving (useful for backup scripts)\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    save-on                   re-enables terrain saving\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    list                      lists all currently connected players\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    say <message>             broadcasts a message to all players\n"}}
{"result":"success","source":"console","success":{"time":1304479900,"line":"2011-05-03 19:31:40 [INFO]    time <add|set> <amount>   adds to or sets the world time (0-24000)\n"}}

An important thing to notice is that you do not see the input, just the output. I ran the commands "test" and "help". Obviously "test" triggered the "Unknown console command".