JSON-RPC 服务器

0.6.5 2014-02-25 21:40 UTC

This package is auto-updated.

Last update: 2024-09-20 23:54:10 UTC


README

     _                 _                 _
 ___(_)_ __ ___  _ __ | | ___  _ __     (_)_ __
/ __| | '_ ` _ \| '_ \| |/ _ \| '_ \    | | '__|
\__ \ | | | | | | |_) | | (_) | | | |   | | |
|___/_|_| |_| |_| .__/|_|\___/|_| |_|  _/ |_|
                |_|                   |__/

简化版/Jr

一个 JSON-RPC 服务器

当前版本:0.6.5

1. 简介

1.1. 什么是 JSON?

JSON(JavaScript 对象表示法)是一种轻量级的数据交换格式。它易于人类阅读和编写。它易于机器解析和生成。请继续阅读[更多内容]

1.2. 什么是 RPC?

在计算机科学中,远程过程调用(RPC)是一种进程间通信,允许计算机程序在没有程序员明确编码远程交互细节的情况下,在其他地址空间(通常在共享网络上的另一台计算机上)执行子程序或过程。可以实现这一概念的不同(通常是兼容性差)技术。请继续阅读[更多内容]

1.3. 规范

JSON-RPC 是一种无状态的、轻量级的远程过程调用(RPC)协议。本规范主要定义了几个数据结构及其处理规则。它是传输无关的,因为可以在同一进程内、通过套接字、通过 HTTP 或在许多不同的消息传递环境中使用这些概念。它使用 JSON(RFC 4627)作为数据格式。请继续阅读[更多内容]

1.4. 请求/响应示例

客户端请求

{"jsonrpc": "2.0", "method": "subtract", "params": {"subtrahend": 23, "minuend": 42}, "id": 3}

服务器响应

{"jsonrpc": "2.0", "result": 19, "id": 3}

2. 示例设置

以下步骤应该演示简化版/Jr 的标准工作示例。示例设置位于测试文件夹中,这是本存储库的一部分。

2.1. 依赖项

简化版/Jr 是基于 PHP 依赖管理器 Composer 构建的。如果您还没有安装 composer,请现在安装。熟悉 Composer 非常重要。因此,请花些时间查看 composer 的文档

使用您的终端并切换到测试文件夹。输入 ls -la 应该会显示类似于以下的内容

drwxr-xr-x   6 fightbulc  staff   204 11 Mär 15:09 .
drwxr-xr-x  12 fightbulc  staff   408 11 Mär 11:05 ..
drwxr-xr-x   3 fightbulc  staff   102 11 Mär 14:39 client
-rw-r--r--   1 fightbulc  staff   251 11 Mär 12:00 composer.json
drwxr-xr-x   4 fightbulc  staff   136 11 Mär 11:39 server

《code>composer.json 文件揭示了某些包详细信息,更重要的是,它告诉 Composer 关于我们的依赖项

{
  "name": "simplon/jr_testing",
  "description": "JSON-RPC Server testing",

  "require": {
    "php": ">=5.4",
    "simplon/jr": "0.5.2",
    "fightbulc/jsonrpc_curl": "0.5.1"
  },

  "autoload": {
    "psr-0": {
      "App": "server/"
    }
  }
}

好,我们已经说够了。让我们通过 composer install 安装依赖项。这应该在您的屏幕上产生一些动作,进而留下我们的依赖项和 composer 自动加载类的映射(所有这些都位于 vendor 文件夹中)

drwxr-xr-x   8 fightbulc  staff   272 11 Mär 15:18 .
drwxr-xr-x  12 fightbulc  staff   408 11 Mär 11:05 ..
drwxr-xr-x   3 fightbulc  staff   102 11 Mär 14:39 client
-rw-r--r--   1 fightbulc  staff   251 11 Mär 12:00 composer.json
-rw-r--r--   1 fightbulc  staff  5571 11 Mär 15:18 composer.lock
drwxr-xr-x   4 fightbulc  staff   136 11 Mär 11:39 server
drwxr-xr-x   6 fightbulc  staff   204 11 Mär 15:18 vendor

2.2. 服务器

很好,现在我们应该有了我们的依赖项,让我们开始构建我们的服务器。为了完成这项任务,我们需要执行三个步骤,如果我们要包含身份验证,则需要四个步骤。请按照以下步骤进行

2.2.1. 网关

首先,让我们创建一个 Gateway 类。网关类定义了服务设置的所有要求。服务是通过给定的域名分开的。在我们的示例中,我们将选择域名 Web。因此,我们的网关类位于 /server/App/Api/Web/Gateway.php

namespace App\Api\Web;

use Simplon\Jr\Interfaces\InterfaceGateway;

class Gateway extends \Simplon\Jr\Gateway implements InterfaceGateway
{
  /**
   * @return bool
   */
  public function isEnabled()
  {
    return TRUE;
  }

  // ##########################################

  /**
   * @return bool|string
   */
  public function getNamespace()
  {
    return __NAMESPACE__;
  }

  // ##########################################

  /**
   * @return bool
   */
  public function hasAuth()
  {
    return FALSE;
  }

  // ##########################################

  /**
   * @return array|bool
   */
  public function getValidServices()
  {
    return array(
      'Web.Base.hello',
      'Web.Base.getUsernameById',
    );
  }
}

暂且不提继承和接口实现:我们看到什么?

我们通过 isEnabled() 函数声明服务已启用,只需简单地返回 TRUE 即可。否则,将拒绝任何对服务的请求。另一个有趣的方法是 hasAuth()。与先前的函数类似,它是通过返回 TRUE || FALSE 来开启或关闭身份验证。现在让我们假设我们没有身份验证,来看看 getValidServices() 方法。此方法返回允许的服务请求数组。每个字符串由一个 API 域(例如 Web)、一个 服务类名称(例如 Base)和一个 服务类方法名称 组成。所有部分都由点分隔。

2.2.2. 身份验证

回到上面提到的身份验证。如果 hasAuth() 返回 TRUE,则服务器期望在网关自身所在的同一目录下有一个身份验证类 /server/App/Api/Web/Auth.php

namespace App\Api\Web;

class Auth
{
  public function init($user, $pass)
  {
    if($user === 'admin' && $pass == '123456')
    {
      return TRUE;
    }

    return FALSE;
  }
}

身份验证类至少需要一个名为 init() 的方法。它可以包含任意数量的参数,只要它们是请求参数的一部分。在此方法中可以运行任何类型的验证。服务器期望返回 TRUE 以授权访问,返回 FALSE 以表示身份验证失败。

2.2.3. 服务类

如果网关已启用,我们将身份验证(如果有)和传入的服务 API 请求与我们的有效服务列表匹配,则请求将进入请求的服务类。

假设以下请求已发送 Web.Base.hello,这将到达以下服务类 /server/App/Api/V1/Web/Service/BaseService.php

namespace App\Api\Web\Service;

use App\Manager\UserManager;

class BaseService
{
  /**
   * @return string
   */
  public function hello()
  {
    return 'Hello!';
  }

  // ##########################################

  /**
   * @param $userId
   * @return string
   */
  public function getUsernameById($userId)
  {
    $username = (new UserManager())->getUsername($userId);

    return $username;
  }
}

服务类标志着我们的 JSON-RPC 服务器结束。现在我们的服务器等待从调用的服务类方法返回响应,以便将其返回给客户端。在我们的例子中,服务器运行 hello() 方法,返回一个字符串。我们的客户端接收 Hello! 作为响应。

所有其他工作,例如对数据库的调用,应在另一个类中处理 - 所说的 Manager 类。只有结果应返回给服务类,以便它可以返回给客户端。《服务类》应保持 瘦而简单,而《Manager 类》则在幕后 做所有工作和魔法。这应该始终记住,以支持代码的可重用性。

第二个示例展示了描述的技术。服务器接收到一个带有 userId 参数的请求 Web.Base.getUsernameById。该方法接受参数并将其传递给 UserManager 类以获取 username。所有这一切如何发生对 Service 类来说并不重要。重要的是用户名。

这里是一个提到的 UserManager 的示例骨架

namespace App\Manager;

class UserManager
{
  /**
   * @param $id
   * @return string
   */
  public function getUsername($id)
  {
    $username = NULL;

    // do some work and return ...
    // return $username;

    // fake return
    return 'Hansi';
  }
}

2.2.4. 服务引导

那么还有什么?

为了完成我们的服务器,我们还需要一个引导文件,它用作域服务的单入口点。我们需要的只是一个公开可用的文件,它连接到我们先前创建的服务网关 /server/public/api/web/index.php

require __DIR__ . '/../../../../vendor/autoload.php';
$gtw = new App\Api\Web\Gateway();

这个文件做什么?它加载 composer 的自动加载器,这使得我们可以自动加载我们的网关类。一旦加载了网关,服务器就会读取传入的请求,并开始执行上述处理。

2.3. 客户端

现在服务器已经完成,我们需要一个可以与我们的服务通信的客户端。我编写了一个名为 JSONRPC_CURL 的小类,它使得请求变得非常简单。您已经在开始时安装了它,因为它是我们的测试文件夹包的一部分。

我们的客户端文件可以在这里找到 /client/request_server_testing.php

为了与我们的描述示例保持一致,以下代码将调用我们的服务 Web.Base.hello。请确保 $urlServiceGateway 包含正确的服务器 URL

// url to server gateway
$urlServiceGateway = 'http://localhost/opensource/server/simplon/simplon_jr/test/server/public';

// ############################################

// send request
$response = (new JsonRpcCurl())
  ->setUrl($urlServiceGateway . '/api/web/')    // server url
  ->setId(1)                                    // request ID (important for batch/async)
  ->setMethod('Web.Base.hello')                 // requested service
  ->send();                                     // send request

// dump response
var_dump($response); // should print: string(6) "Hello!"

并且既然我们提到了 UserManager 类,这里有一个示例

// url to server gateway
$urlServiceGateway = 'http://localhost/opensource/server/simplon/simplon_jr/test/server/public';

// ############################################

// send request
$response = (new JsonRpcCurl())
  ->setUrl($urlServiceGateway . '/api/web/')
  ->setId(1)
  ->setMethod('Web.Base.getUsernameById')
  ->setData(['id' => 35])
  ->send();

// dump response
var_dump($response); // prints: Hansi

2.4. 身份验证请求

最后,这里有一个认证请求的示例。请确保在您的网关类中的hasAuth()函数返回TRUE。这应该将每个请求通过我们的认证类

现在让我们向客户端添加必要的用户数据

// url to server gateway
$urlServiceGateway = 'http://localhost/opensource/server/simplon/simplon_jr/test/server/public';

// ############################################

// auth data
$data = [
  'user' => 'admin',
  'pass' => '123456',
];

// send request
$response = (new JsonRpcCurl())
  ->setUrl($urlServiceGateway . '/api/web/')    // server url
  ->setId(1)                                    // request ID (important for batch/async)
  ->setMethod('Web.Base.hello')                 // requested service
  ->setData($data)                              // holds auth data
  ->send();                                     // send request

// dump response
var_dump($response); // should print: string(6) "Hello!"

缺少所需的认证数据或传递错误的数据都不会有任何帮助。试试看。

许可证

Cirrus可以在MIT许可证的条款下自由分发。

版权(c)2014 Tino Ehrich (opensource@efides.com

特此授予任何获得此软件及其相关文档副本(“软件”)的个人免费使用软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本,并允许向软件提供者提供软件的人这样做,前提是遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

软件按“现状”提供,不提供任何明示或暗示的保证,包括但不限于适销性、适用于特定目的和侵权保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任承担责任,无论该责任是基于合同、侵权或其他原因,无论该责任产生于、因之而存在或与此有关,包括但不限于软件或软件的使用或其它处置。

Bitdeli Badge