NAME

Net::API::REST::Endpoint - Endpoint object for Net::APi::REST

SYNOPSIS

my $ep = Net::API::REST::Endpoint->new(
    handler => $code_ref,
    # could be also restricted.
    access => 'public',
    methods => [qw( GET POST )],
    path_info => '/some/extra/path',
    variables => { person_id => 123 },
    params => { some_data => $some_value },
);

Then, in the method mapped to the endpoint called from Net::API::REST::handler():

my $self = shift( @_ );
my $ep = $self->endpoint;
my $vars = $ep->variables;
# For example /users/123/name and assuming an endpoint map with _vars => { _name => user_id }
# my $user_id = $vars->{user_id};

The route could look something like the following:

$self->{routes} =
{
    # API version 1
    1 =>
    {
        # special case ?
        '.well-known' => $self->curry::well_known,
        # This inherits the public access
        csrf_check => $self->curry::csrf_check,
        users =>
        {
            # Nope, cannot stop there, sends back noop
            _handler => $self->curry::noop,
            # From now on, all endpoints below will be restricted
            _access_control => 'restricted',
            # For example: https://api.example.com/users/123
            _var =>
            {
                _name => 'user_id',
                # Return the user information
                _handler => $self->curry::user_info,
                # This is a read-only endpoint, query string will be discarded and no POST or PUT allowed
                _allowed_methods => [qw( GET )],
                # discretionary hash of key-value pairs
                _params => { some_data => $some_value },
                # https://api.example.com/users/123/first_name
                first_name =>
                {
                    _handler => $self->curry::user_first_name,
                    _allowed_methods => [qw( GET POST )],
                },
                payment_method =>
                {
                    # Create, Retrieve, Update, Delete
                    _allowed_methods => [qw( PUT GET POST DELETE )],
                    _var =>
                    {
                        _handler => $self->curry::user_pm,
                        _name => 'pm_id',
                    },
                },
                # etc...
            },
        },
    },
    # api version 2, etc.
    # 2 => {},
};

As you can see endpoints below https://api.example.com/users would be restricted, which would mean that your api would check the value provided "access" and check for user credentials before granting execution of the query.

Note that the api version number is not necessarily part of the path, although it could.

It can also be provided in the Accept header. See "accept" in Net::API::REST::Request for more details.

For example:

https://api.example.com/v1/users/123/payment_method/456
https://api.example.com/v1.2/users/123/payment_method/456
https://api.example.com/1/users/123/payment_method/456
https://api.example.com/users/123/payment_method/456

with an http Accept field value of: application/json; charset=utf-8; version=1

If no api version is specified either way, then the latest one provided by "api_version" in Net::API::REST is used.

See "api_version" in Net::API::REST for more details.

METHODS

access

Sets or gets the accessibility of the endpoint, such as public, or restricted or anything else you want to use.

The access level you set has a cascading effect on all the endpoints below itself as shown in the example in the "SYNOPSIS" above.

This defaults to public.

handler

Set or gets the code reference that is called for a given endpoint.

For example, if you have an endpoint route defined as:

{
    version => $self->curry::version,
}

Then the "handler" will be a code reference to version.

For handler, curry is very handy and much better than to write a bunch of anonymous routines like:

{
    _handler => sub{ $self->user_pm( @_ ) },
}

is_method_allowed

Provided with an HTTP method name, such as POST or GET, and this will return true, if this method is allowed for this endpoint, or false otherwise.

methods

Sets or gets the array reference of allowed methods for this endpoint. For example GET, POST, PUT, DELETE

params

Sets or gets a discretionary hash reference of key-value pairs to be accessed and used in your code.

path

The path URI for this endpoint. This sets or gets an URI object.

path_info

Sets or gets possible path info specified when the user made the api call.

For example, assuming an endpoint /create/file, and user calling /create/file/some/where/file.txt, then /some/where/file.txt would be set as path info assuming there is nothing below the endpoint /create/file declared in the api route, otherwise, of course, this would trigger a 404 Not found error.

variables

Sets or gets the hash reference containing the variables and their values.

For example, assuming and endpoint call like /users/123/last_name, then the route hash reference would look like:

{
    users =>
    {
        _handler => $self->curry::users,
        _var =>
        {
            _handler => $self->curry::users,
            _name => 'user_id',
            first_name => $self->curry::user_first_name,
            last_name => $self->curry::user_last_name,
        }
    }
}

Then, "route" in Net::API::REST would set the variable user_id to 123.

If a same variable is declared and found twice in the path, it is automatically switched to an array reference. Thus, if the value of a given variable is an array reference, you know instantly there was more than one value provided in the query.

WHAT ABOUT QUERY STRING

You can always get the query string, if any, by using "params" in Net::API::REST::Request:

    my $self = shift( @_ );
    # $q is not an hash reference
    my $q = $self->request->params;
    # or maybe the user sent you a json payload?
	$q = $self->request->payload if( !scalar( keys( %$q ) ) && $self->request->payload );

AUTHOR

Jacques Deguest <jack@deguest.jp>

SEE ALSO

Net::API::REST, Net::API::REST::Request, Net::API::REST::Response, Net::API::REST::Query

COPYRIGHT & LICENSE

Copyright (c) 2018-2023 DEGUEST Pte. Ltd.

You can use, copy, modify and redistribute this package and associated files under the same terms as Perl itself.