The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

JSON::Server - JSON-only server

SYNOPSIS

    use JSON::Server;
    my $js = JSON::Server->new (handler => \& hello, port => '7777', data => 'OK');
    $js->serve ();
    
    sub hello
    {
        my ($data, $input) = @_;
        return {%$input, hello => 'world', data => $data};
    }
    

(This example is included as synopsis.pl in the distribution.)

Then test your server:

    $ perl examples/synopsis.pl &
    $ telnet localhost 7777
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    {"I'm feeling lucky":"punk"}
    {
            "I'm feeling lucky":"punk",
            "data":"OK",
            "hello":"world"
    }
    Connection closed by foreign host.

VERSION

This documents version 0.02 of JSON-Server corresponding to git commit 3002d95df18b014ba750d9c37f1ea44027d29fe5 released on Wed May 12 12:04:15 2021 +0900.

DESCRIPTION

This sets up an internet socket through which JSON passes. Each complete JSON message must be followed by a zero byte.

METHODS

new

    my $js = JSON::Server->new (handler => \& something, data => $my_data,
                                port => '3737');

The possible options are as follows.

data

Data to pass the handler. If omitted, the handler will get an undefined value as its first argument.

handler

Your handler (callback).

    sub handler
    {
        my ($data, $input) = @_;
        return {error => "I don't like this input"};
    }
    my $js = JSON::Server->new (handler => \&handler);

The handler function should accept two arguments, the first is the user data which is supplied to "new" and the second is the parsed input from the socket. It should return one value which is then passed back through the socket as JSON. The user handler function does not need to serialize or deserialize, that is done by this module.

Usually a handler would take a hash reference as an argument and return a hash reference as result, but it can accept and return either an array reference or a scalar, depending on what your client sends.

If you do not supply a handler, the server prints a warning about the lack of a handler and substitutes an echo function which merely returns your input back to you. This is useful for testing. The echo server is not exported, but if you want to get the echo server directly without a warning being printed, use

    my $server = JSON::Server->new (
        port => '1234',
        handler => \&JSON::Server::echo,
    );
port

The port to serve on. This needs to be specified, there is no default value.

verbose

If set to a true value, print debugging messages to standard output.

serve

    $js->serve ();

Serves JSON on the specified port. Input is JSON followed by a zero byte, output is JSON followed by a zero byte. Non-JSON input results in a response of the form {"error":"invalid JSON"} being returned. What is or is not valid JSON is decided by "valid_json" in JSON::Parse.

Messages to the server need to be terminated with a zero byte (a byte containing a zero). The return message is also terminated with a zero byte. This will need to be removed before parsing the JSON at your end. The need for a zero byte might be removed at some point, but it removes the necessity for having to parse and re-parse the input to find the end of the JSON, since a zero byte is invalid as JSON.

In early trial versions of this module the server was closing the connection after each message, but since version 0.01 it keeps the connection open indefinitely. You can make the server close the connection with a control message.

If the connection is closed remotely, serve returns, so if you want to keep your server running, you need to enclose it in some kind of loop:

    while (1) {
        $js->serve ();
    }

This behaviour may be changed in future versions.

JSON

Booleans

Unlike many programming languages, Perl doesn't have true and false, which means that boolean literals (true and false) can become something of an issue when using JSON.

If you need booleans, one easy way to do it is to import JSON::Create::Bool from the JSON::Create distribution.

    use JSON::Create::Bool;

in your code and then

    my $value = true;

etc. to get true and false literals in the JSON.

Perl's built-in undef will produce JSON null.

Unicode

Perl doesn't allow character-encoded strings through sockets, so character input is automatically downgraded on output using "downgrade_utf8" in JSON::Create, and since JSON is a UTF-8 only format, all input is upgraded to character input using "upgrade_utf8" in JSON::Parse.

CONTROLS

Controlling the server

To control the server, send an object (a hash reference) with the key JSON::Server::control:

    send_to_server ({'JSON::Server::control' => 'stop'});

The server accepts the following commands:

close

{"JSON::Server::control":"close"} causes the server to close the connection. It prints a response {"JSON::Server::response":"closing"} to acknowledge the control message.

stop

{"JSON::Server::control":"stop"} causes the server to return from its event loop. It prints a response {"JSON::Server::response":"stopping"} to acknowledge the control message.

Whatever else is sent in the object with the control message is discarded.

JSON::Client

There is an example client module called JSON::Client in the distribution. See this distribution's t/ (test) directory for examples of use.

DEPENDENCIES

IO::Select

At the moment JSON::Server is non-forking and reads from multiple sockets, so it uses IO::Select to choose the socket to read from.

IO::Socket

This is used to communicate the information to and from the client.

JSON::Create

This is used to encode the response JSON from a native structure.

JSON::Parse

This is used to decode the received JSON into a native structure.

SEE ALSO

JSON RPC
JRPC
JSON::RPC::Dispatcher
JSON::RPC
JSON::RPC2::TwoWay
RPC::JSON

AUTHOR

Ben Bullock, <bkb@cpan.org>

COPYRIGHT & LICENCE

This package and associated files are copyright (C) 2021 Ben Bullock.

You can use, copy, modify and redistribute this package and associated files under the Perl Artistic Licence or the GNU General Public Licence.