简洁的REST抽象

0.0.4 2020-05-26 15:48 UTC

This package is auto-updated.

Last update: 2024-09-27 01:54:04 UTC


README

Lingo是一个为Laravel提供的包,它为任何REST服务提供了一层抽象。因此,可以将http通信的概念封装在更接近面向对象的设计中,从而提高开发者的体验。

安装

使用包管理器 composer 安装Lingo。

composer require galafeno/lingo

用法

使用命令 make:lingo 在您的应用程序中初始化一个新的Lingo。

    php artisan make:lingo AwesomeApi --base_url=https://awesome.api/v1

该命令在 App\Lingos 文件夹中创建一个名为 AwesomeApiLingo 的类。

要建模API,您应该在 AwesomeApiLingo 类中的 sync 部分添加端点。

    protected $sync = [
        'base_url' => 'https://awesome.api/v1',
        'commands' => [
            'getMovie' => [
                'verb' => 'get',
                'url' => "/movies/{:?}"
            ],
        ]
    ];

之后,您可以在应用程序中使用您的Lingo如下所示

    $movie = Lingo::awesomeApi()->command('getMovie',1)->send();

    echo $movie->name; // Batman v Superman: Dawn of Justice

command 方法应至少接受一个参数(命令名称)。在这种情况下,它接收了2个参数,因为 getMovie 命令有一个绑定值(用 {:?} 通配符标记)。

自定义头部

Lingo被设计来处理json数据类型,因此它将始终将 Content-Type: application/jsonAccept: application/json 添加到默认头部。要定义其他头部,在您的Lingo类中创建一个 headers 属性。

    protected $headers = [
        'DomainId' => 15,
        'SafeMode' => 'Unguarded'
    ];

这将生成以下头部,用于每个请求

{
    "Content-Type": "application/json",
    "Accept": "application/json",
    "DomainId": "15",
    "SafeMode": "Unguarded"
}

您还可以在运行时定义额外的头部如下所示

    Lingo::awesomeApi()
    ->command('getMovie',1)
    ->withHeaders(['Scope' => 'readOnly'])
    ->send();

查询参数

要定义查询参数,在您的Lingo类中创建一个 params 属性

    protected $params = [
        'start' => '2020-02-02',
        'end' => '2020-04-04'
    ];

这将插入以下查询参数到每个请求中

    GET https://awesome.api/v1/movies/1?start=2020-02-02&end=2020-04-04

您还可以在运行时定义额外的查询参数如下所示

    Lingo::awesomeApi()
    ->command('getMovie',1)
    ->withParams(['user_id' => 1])
    ->send();

正文参数

要定义正文参数,在您的Lingo类中创建一个 data 属性

    protected $data = [
        'username' => 'superuser',
        'email' => 'superuser@super.user'
    ];

这将插入以下正文参数到每个请求中

    POST https://awesome.api/v1/movies
    {
        "username": "superuser",
        "email": "superuser@super.user"
    }

您还可以在运行时定义额外的正文参数如下所示

    Lingo::awesomeApi()
    ->command('getMovie',1)
    ->withData(['user_id' => 1])
    ->send();

闭包命令

通常您应该将Lingo用作将端点映射到命令的方式。但是,使用闭包命令语法,您可以触发一个函数而不是真实的HTTP请求。这是一个方便的方式来添加有关您的API的元数据。要这样做,在您的命令配置中使用关键字function。然后只需在您的Lingo类中添加引用的函数。

    'commands' => [
        ...
        'list' => [
            'function' => 'getCommandList'
        ],
        ...
    ];

    ...

    protected function getCommandList($bindings)
    {
        foreach ($this->sync['commands'] as $command) {
            if ( isset($command['verb']) && isset($command['url']) ){
                echo strtoupper($command['verb']) . " " . $command['url'] . PHP_EOL;
            }
        }
    }
    ...
    Lingo::awesomeApi()->command('list')->send();
    // GET /peoples
    // POST /peoples
    // GET peoples/{:?}
    // PUT peoples/{:?}
    // DELETE  peoples/{:?}

处理身份验证

在现实世界应用中,REST服务实现了一些类型的身份验证方案。如果您正在处理一个简单的方案,如请求头中的签名或密钥,您应该简单地使用 withHeaders 命令将您的身份验证配置附加到Lingo。但某些服务使用特定的方案。要处理它,您应该在您的lingo类中定义一个 auth 配置。当前,此包支持 apiKeysoauth2 身份验证方法。

apiKeys

该方法将密钥配置作为查询参数附加。

    protected $sync = [
        'base_url' => 'https://protected.rest/v1',
        'auth' => [
            'apiKeys' => [
                'my-key' => 'my-secret'
            ]
        ],
        'commands' => [
            ...
        ]
    ];
    GET https://protected.rest/v1/someurl?my-key=my-secret
oauth2

该方法将处理oauth2流程以检索jwt并将其缓存到您的应用程序缓存配置。

    protected $sync = [
        'base_url' => 'https://protected.rest',
        'auth' => [
            'oauth2' => [
                'url' => '/oauth/token',
                'grant_type' => 'client_credentials',
                'client_id' => 'my-client-id',
                'client_secret' => 'my-client-secret'
            ]
        ],
        'commands' => [
            ...
        ]
    ];

模拟模式

在测试您的应用程序时,您必须在您的 .env 中定义 APP_ENV=testing 以激活Lingo模拟模式。在此模式下,该包将绕过任何真实请求,使用模拟的静态数据。您应该在命令配置部分使用 shouldReturn 键定义这些数据。

    protected $sync = [
        'base_url' => 'https://service.rest/v1',
        'commands' => [
            'getMovie' => [
                'verb' => 'get',
                'url' => "/movies/{:?}",
                'shouldReturn' => [
                    'id' => 1
                    'name' => 'static name',
                    'genre' => 'drama',
                    'length' => 97
                ]
            ],
        ]
    ];

    ...

    $movie = Lingo::awesomeApi()->command('getMovie',1)->send();
    echo $movie->name; // static name

您还可以在运行时设置模拟模式如下所示

    $movie = Lingo::awesomeApi()->command('getMovie',1)->withMockup(true)->send();
    echo $movie->name; // static name

Lingo默认使用static作为mockup数据模式。但您可以使用mockup关键字设置为function模式。这样,Lingo将依赖于一个函数来生成mockup数据。

    protected $sync = [
        'base_url' => 'https://service.rest/v1',
        'commands' => [
            'getMovie' => [
                'verb' => 'get',
                'url' => "/movies/{:?}",
                'mockup' => 'function',
                'shouldReturn' => 'makeMovie'
            ],
        ]
    ];

    ...

    protected function makeMovie($bindings)
    {
        $faker = \Faker\Factory::create();
        return (object)[
            'id' => $bindings[0],
            'name' => $faker->name,
            'length' => $faker->numberBetween(90,180)
        ];
    }

    ...

    $movie = Lingo::awesomeApi()->command('getMovie',1)->send();
    echo $movie->name; // name generated by faker    

异步通信

如果您的应用程序使用AWS基础设施,您可以在Lingo类中配置异步消息。为此,您必须配置您的async部分。

    protected $async = [
        'queue' => 'myqueue',
        'commands' => [
            'sendEmail' => [
                'action' => 'SendEmail'
            ]
        ]
    ];

要发送异步消息,必须使用async方法。

Lingo::awesomeApi()->command('sendEmail')
    ->withData($data)
    ->async()
    ->send();

这将把有效载荷推送到您的sqs队列

    [
        'action' => 'sendEmail',
        'data' => $data
    ]

路线图

  • 单元和功能测试
  • sync部分导出到swagger文件
  • shouldReturn部分接受一个闭包,这样您就可以处理动态生成的mockup数据
  • make:lingo中添加一个多态选项。这将很棒,例如创建一个作为接口的PaymentLingo,以及一个作为实现PaymentLingo的具体类StripeLingo
  • 允许同步命令触发一个闭包或类方法,而不是HTTP请求。
  • 自定义异常
  • 内置日志系统

贡献

欢迎提交拉取请求。对于重大更改,请首先提交一个问题以讨论您想要更改的内容。

请确保根据需要更新测试。

许可

MIT