NAME
    Sub::Spec::HTTP::Server - Serve subroutine calls via HTTP/HTTPS

VERSION
    version 0.03

SYNOPSIS
    In your program:

     use Sub::Spec::HTTP::Server;
     use My::Module1;
     use My::Module2;

     my $server = Sub::Spec::HTTP::Server->new(
         sock_path   => '/var/run/apid.sock',  # activate listening to Unix socket
         #http_port  => 949,                   # default is 80
         #https_port => 1234,                  # activate https
         #ssl_key_file => '/path/to/key.pem',  # need this for https
         #ssl_cert_file => '/path/to/crt.pem', # need this for https
         #max_requests_per_child => 100,       # default is 1000
         #start_servers => 0,                  # default is 3, 0 means don't prefork
         #daemonize => 0,                      # do not go to background
     );
     $server->run;

    After running the program, accessing:

     http://localhost:949/My/Module2/func?arg1=1&arg2=2

    You will be getting a JSON response:

     [200,"OK",{"the":"result data"}]

DESCRIPTION
    This class is a preforking HTTP (TCP and Unix socket)/HTTPS (TCP) daemon
    for serving function call requests (usually for API calls). All
    functions should have Sub::Spec specs.

    This module uses Log::Any for logging.

    This module uses Moo for object system.

ATTRIBUTES
  name => STR
    Name of server, for display in process table ('ps ax'). Default is
    basename of $0.

  daemonize => BOOL
    Whether to daemonize (go into background). Default is true.

  sock_path => STR
    Location of Unix socket. Default is none, which means not listening to
    Unix socket.

  pid_path => STR
    Location of PID file. Default is /var/run/<name>.pid.

  error_log_path => STR
    Location of error log. Default is /var/log/<name>-error.log. It will be
    opened in append mode.

  access_log_path => STR
    Location of access log. Default is /var/log/<name>-access.log. It will
    be opened in append mode.

  access_log_max_args_len => INT
    Maximum number of characters to log args (in JSON format). Default is
    1024. Over this length, only the first 1024 characters are logged.

  access_log_max_resp_len => INT
    Maximum number of characters to log response (in JSON format). Default
    is 1024. Over this length, only the first 1024 characters are logged.

  http_port => INT
    Port to listen to HTTP requests. Default is 80. Undef means not
    listening for HTTP requests. Note that in Unix environment, binding to
    ports 1024 and below requires superuser privileges.

  http_bind_host => STR
    If you only want to bind to a specific interface for HTTP, specify it
    here, for example 'localhost' or '1.2.3.4'. Setting to undef or '' means
    to bind to all interface ('*'). Default is 'localhost'.

  https_port => INT
    Port to listen to HTTPS requests. Default is undef. Undef means not
    listening for HTTPS requests. Note that in Unix environment, binding to
    ports 1024 and below requires superuser privileges.

  https_bind_host => STR
    If you only want to bind to a specific interface for HTTPS, specify it
    here, for example 'localhost' or '1.2.3.4'. Setting to undef or '' means
    to bind to all interface ('*'). Default is 'localhost'.

  ssl_key_file => STR
    Path to SSL key file, to be passed to HTTP::Daemon::SSL. If you enable
    HTTPS, you need to supply this.

  ssl_cert_file => STR
    Path to SSL cert file, to be passed to HTTP::Daemon::SSL. If you enable
    HTTPS, you need to supply this.

  start_servers
    Number of children to fork at the start of run. Default is 3. If you set
    this to 0, the server becomes a nonforking one.

    Tip: You can set start_servers to 0 and 'daemonize' to false for
    debugging.

  max_requests_per_child
    Number of requests each child will serve until it exists. Default is
    1000.

  module_prefix
    Prefix for module. Default is none. Affects get_sub_name().

  req
    The request object, will be set at the start of each request (before
    handle_request() is run). Currently this is a barebones hash, but will
    be a proper object.

  resp
    The response, should be in the form of [HTTP_STATUS_CODE, MESSAGE,
    DATA].

METHODS
  new()
    Create a new server object.

  $server->stop()
    Stop running server.

  $server->run()
    Run server.

  $server->restart()
    Restart server.

  $server->is_running() => BOOL
    Check whether server is running

  $server->before_prefork()
    Override this hook to do stuffs before preforking. For example, you can
    preload all modules. This is more efficient than each children loading
    modules separately.

    The default implementation does nothing.

  $server->handle_request()
    The main routine to handle request, will be called by run(). Below is
    the order of processing. At any time during the request, you can set
    $server->resp() and die to exit early and directly go to access_log().

    *   before_parse_http_request()

    *   parse_http_request()

    *   get_sub_name()

    *   get_sub_args()

    *   auth()

    *   get_sub_spec()

    *   authz()

    *   call_sub()

    *   send_http_response()

    *   after_send_http_response()

    *   access_log()

  $server->before_parse_http_request()
    Override this to add action before HTTP request is parsed.

  $server->parse_http_request()
    Parse HTTP request (result in $server->req->{http_req}). Will be called
    by handle_request().

  $server->get_sub_name()
    Parse sub's fully qualified name from HTTP request object. Result should
    be put in $server->req->{sub_module} and $server->req->{sub_name}.

    You can override this method to provide other URL syntax. The default
    implementation parses URI using this syntax:

     /MODULE/SUBMODULE/FUNCTION

    which will result in sub_module being 'MODULE::SUBMODULE' and sub_name
    'FUNCTION'. In addition, some options are allowed:

     /MODULE/SUBMODULE/FUNCTION;OPTS

    OPTS are a string of one or more option letters. 'j' means to ask server
    to return response in JSON format. 'r' (the default) means return in
    pretty formatted text (e.g. tables). 'R' means return in
    non-pretty/plain text. 'y' means return in YAML. 'p' means return in PHP
    serialization format.

    For example:

     /My/Module/my_func;j

    If 'module_prefix' attribute is set, it will be prepended to
    $server->req->{sub_module}. For example, if 'module_prefix' is
    'Our::Project', then with the above URI, the final sub_module will
    become 'Our::Project::My::Module'.

  $server->get_sub_args()
    Parse sub's args from HTTP request object. Result should be put in
    $server->req->{sub_args}. It should be a hashref.

    The default implementation can get args from request body in PHP
    serialization format (if "Content-Type" HTTP request header is set to
    "application/vnd.php.serialized") or JSON ("application/json") or YAML
    ("text/yaml").

    Alternatively, it can get args from URL query parameters. Each query
    parameter corresponds to an argument name. If you add ":j" suffix to
    query parameter name, it means query parameter value is in JSON format.
    If ":y" suffix, YAML format. If ":p", PHP serialization format.

    You can override this method to provide other ways to parse arguments
    from HTTP request.

  $server->get_sub_args()
    Get sub's spec. Result should be put in $server->req->{sub_spec}.

    The default implementation will simply looks for the spec in %SPEC in
    the package specified in $server->req->{sub_module}.

  $server->auth()
    Authenticate client. Override this if needed. The default implementation
    does nothing. Authenticated client should be put in
    $server->req->{auth_user}.

  $server->authz()
    Authorize client. Override this if needed. The default implementation
    does nothing.

  $server->call_sub()
    Call function specified in $server->req->{module} and
    $server->req->{sub}) using arguments specified in $server->req->{args}.
    Set $server->resp() with the return value of function.

  $server->send_http_response()
    Send HTTP response to client. Called by handle_request().

  $server->after_send_http_response()
    Hook to do stuffs before logging. The default implementation does
    nothing. You can override this e.g. to mask some arguments from being
    logged or limit its size.

  $server->access_log()
    Log request. The default implementation logs like this (all in one
    line):

     [Fri Feb 18 22:05:38 2011] "GET /v1/MyModule/my_func;j?arg1=1&arg2=2"
     [127.0.0.1:949] [-] [mod MyModule] [sub my_func]
     [args 14 {"name":"val"}] [resp 12 [200,"OK",1]] [subt 2.123ms] [reqt 5.947ms]

    where subt is time spent in the subroutine, and reqt is time spent for
    the whole request (from connect until response is sent, which includes
    reqt).

FAQ
BUGS/TODOS
    I would like to use Plack/PSGI, but the current implementation of this
    module (using HTTP::Daemon + HTTP::Daemon::SSL) conveniently supports
    HTTPS out of the box.

SEE ALSO
    Sub::Spec

    Sub::Spec::HTTP::Client

AUTHOR
    Steven Haryanto <stevenharyanto@gmail.com>

COPYRIGHT AND LICENSE
    This software is copyright (c) 2011 by Steven Haryanto.

    This is free software; you can redistribute it and/or modify it under
    the same terms as the Perl 5 programming language system itself.

