


=encoding UTF-8

=head1 NAME

JSON::Server - JSON-only server

=head1 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 L<F<synopsis.pl>|https://fastapi.metacpan.org/source/BKB/JSON-Server-0.00_07/examples/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.


=head1 VERSION

This documents version 0.00_07 of JSON-Server
corresponding to L<git commit 429d7e6f03824227c7c13f36ce8cda9025887c47|https://github.com/benkasminbullock/json-server/commit/429d7e6f03824227c7c13f36ce8cda9025887c47> released on Tue Feb 9 10:21:16 2021 +0900.

=head1 DESCRIPTION

This sets up an internet socket through which JSON passes.

=head1 METHODS

=head2 new

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

=over

=item data

Your data which you want to pass to the handler. This can be omitted,
in which case the handler will be sent an undefined value as its first
argument.

=item 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 L</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
serialize or deserialize anything, usually it would take a hash
reference as an argument and return a hash reference as result.

If you do not supply a handler, the server substitutes an echo
function which merely returns your input back to you, and prints a
warning.

=item port

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

=back

=head2 serve

    $js->serve ();

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

=head1 JSON

=head2 Booleans

Unlike many programming languages, Perl doesn't have C<true> and
C<false>, which means that boolean literals (C<true> and C<false>) can
become something of an issue when using JSON. In L<JSON::Create> there
are all kinds of options for using booleans, but JSON::Server doesn't
give access to the underlying module. 

However, as a way to get booleans, if you need them, JSON::Server uses
the CPAN module L</boolean>. If you need C<true> or C<false> in your
JSON output, add

    use boolean;

in your code and then

    my $value = true;

etc. to get C<true> and C<false> literals in the JSON.

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

Boolean support is planned for a future version of JSON::Parse, and
the use of the L</boolean> module will no longer be necessary.

=head2 Unicode

Perl doesn't allow character-encoded strings through sockets, so
character input is automatically downgraded on output using
L<JSON::Create/downgrade_utf8>, and since JSON is a UTF-8 only format,
all input is upgraded to character input. L</JSON::Parse> currently
doesn't have the facility to do this, so L</Unicode::UTF8> is used for
that task.

Optional character-string upgrading is planned for a future version of
JSON::Parse, and use of the Unicode::UTF8 module will no longer be
necessary.

=head1 CONTROLS

=head2 Controlling the server

There is a "backdoor" for controlling the server. To access this, you
need to send an object (a hash reference) with the key
C<JSON::Server::control>,

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

It accepts the following commands:

=over

=item stop

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

=back

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

=head2 JSON::Client

There is an example client module called JSON::Client in the
distribution. At the moment, this is used for testing the
server. There is no documentation, so please see the files in the
F<t/> directory of this distribution for examples of use.

In the practical case for which I'm using this module, I use it to
communicate from a Perl server to a Go (golang) client, so most of the
examples I have of actual use of the module don't involve a Perl
client at all, only a Perl server. It's difficult to include a useful
Go example in the module since, unlike Perl, Go is strongly typed and
"standard library" JSON parsing in Go involves advanced knowledge of
the data structure to be received.

=head1 DEPENDENCIES

=over

=item L<boolean>

C<boolean> is used as the compatibility module for putting C<true> or
C<false> values into the JSON. See L</Booleans> for details.

=item L<IO::Socket>

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

=item L<JSON::Create>

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

=item L<JSON::Parse>

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

=item Unicode::UTF8

L<Unicode::UTF8/decode_utf8> is used to convert the received JSON from
the socket before it is passed to L</JSON::Parse>. See L</Unicode> for
details.

=back

=head1 SEE ALSO

=over

=item L<JRPC>

=item L<JSON::RPC::Dispatcher>

=item L<JSON::RPC>

=item L<RPC::JSON>

=back



=head1 AUTHOR

Ben Bullock, <bkb@cpan.org>

=head1 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.



