使用 Hapi 开发 RESTful API 的最佳实践

阅读时长 11 分钟读完

什么是 Hapi?

Hapi 是一种 Node.js 后端框架,它旨在提供一种简单、高度可扩展和安全的方式来构建 Web 应用程序。它特别适用于构建 RESTful API,是一个非常流行的 Node.js 框架。

为什么要使用 Hapi?

Hapi 有很多优点,这里列举几个:

  1. Hapi 很易于学习和使用,同时提供了完善的文档和例子。
  2. Hapi 可以非常快速地创建 REST API。Hapi 内置了许多功能,如路由、验证等。
  3. Hapi 能够很容易地扩展,支持插件机制,在功能上可以进行无缝扩展。
  4. Hapi 对安全非常重视,提供了很好的安全性保证,包括设置请求频率限制、防止 CSRF 攻击、强密码验证和 XSS 防护等。

Hapi 的基本使用

先通过 npm 安装 Hapi:

创建一个简单的 RESTful API,使用 Hapi 代码如下:

-- -------------------- ---- -------
----- ---- - ----------------

----- ------ - --- ------------- ----- ---- ---

--------------
    ------- ------
    ----- ---------
    -------- --------- -- -- -
        ------ ------- --------
    -
---

------ -- -- -
    ----- ---------------
    ------------------- ------- --- ---------------------
-----
展开代码
  • Hapi.Server 表示创建一个 Hapi 服务器,指定端口号 3000
  • server.route 表示定义一组路由,其中包括调用 GET 方法的 /hello 路径,请求来了之后返回 Hello, World!
  • server.start 将服务器启动。

当你运行该程序后,你访问 http://localhost:3000/hello 就能够看到 Hello, World。这是一个简单的 RESTful API 的例子,下面我们将从一些实际应用的场景进行说明。

路由表的组成

在介绍如何使用 Hapi 开发 RESTful API 的最佳实践之前,我们需要先了解路由表的组成。在使用 Hapi 时,您需要创建路由并将其添加到日志 servers 的路由表中,路由表是处理传入请求的第一关口。

路由选项

  • method 表示请求 HTTP 方法。
  • path 表示路由路径。
  • handler 表示处理请求的函数,可以是同步也可以是异步,通常都是一个根据请求返回响应的函数。如果你使用了异步的 handler,你必须将其封装在一个 async 函数中。
-- -------------------- ---- -------
----- ---- - ----------------

----- ---- - ----- -- -- -
    ----- ------ - --- -------------
        ----- -----
        ----- -----------
    ---

    --------------
        ------- ------
        ----- ----
        -------- --------- -- -- -
            ------ ------- --------
        -
    ---

    ----- ---------------
    ------------------- ------- --- ---------------------
--
-------
展开代码

RESTful API

现在我们来学习如何使用 Hapi 创建 RESTful API。使用 RESTful API 是实现 web 应用程序的最佳方式,因为它可以减少代码复杂性,并提高代码结构的可维护性。RESTful API 的实现基于一组原则,例如资源标识、统一接口、自我描述消息等。

在 Hapi 中,可以使用 server.route 方法来创建路由,但存在一些有限制的情况,例如 server.route 只支持 HTTP 动词:GET、POST、PUT、DELETE、PATCH、OPTIONS 和 TRACE。

下面我们来看一个示例,该示例使用类似于“状态码”的方式来处理不同的 HTTP 动词:

-- -------------------- ---- -------
----- ---- - ----------------

----- ------ - --- ------------- ----- ---- ---

--- ----- - -
    - --- -- ------ -------------- ------- ------ --------- --
    - --- -- ------ ----------------- ------- ------ --------- --
    - --- -- ------ --------------- ------- ----- -
--

--------------
    ------- ------
    ----- ---------
    -------- --------- -- -- -
        ------ ------
    -
---

--------------
    ------- ------
    ----- --------------
    -------- --------- -- -- -
        ----- -- - ----------------------------
        ----- ---- - --------------- -- ------- --- ----
        -- ------ -
            ------ -----
        - ---- -
            ------ ---------------- ---- -- -------------------- --- ------------------
        -
    -
---

--------------
    ------- -------
    ----- ---------
    -------- --------- -- -- -
        ----- ---- - ----------------
        ------- - ------------ - --
        -----------------
        ------ ---------------------------
    -
---

--------------
    ------- ------
    ----- --------------
    -------- --------- -- -- -
        ----- -- - ----------------------------
        ----- --------- - -------------------- -- ------- --- ----
        -- ---------- -- -- -
            ----- ----------- - ----------------
            -------------- - ---
            ---------------- - ------------
            ------ ------------------------
        - ---- -
            ------ ---------------- ---- -- -------------------- --- ------------------
        -
    -
---

--------------
    ------- ---------
    ----- --------------
    -------- --------- -- -- -
        ----- -- - ----------------------------
        ----- --------- - -------------------- -- ------- --- ----
        -- ---------- -- -- -
            ----------------------- ---
            ------ -----------------
        - ---- -
            ------ ---------------- ---- -- -------------------- --- ------------------
        -
    -
---

------ -- -- -
    ----- ---------------
    ------------------- ------- --- ---------------------
-----
展开代码

在上面的代码中,我们使用了一个名为 books 的数组来存储所有的书籍。我们定义了以下路由:

  • GET /books: 获取所有书籍。
  • GET /books/{id}: 获取具有给定 ID 的书籍。
  • POST /books: 在 books 数组中添加新书籍。
  • PUT /books/{id}: 更新具有给定 ID 的书籍。
  • DELETE /books/{id}: 删除具有给定 ID 的书籍。

在这个例子中,我们使用了一些特定的状态码 (201 和 204)。201 表示对象创建成功,204 表示成功删除对象。

身份验证和授权

HTTP 是一个基于请求和响应的协议,没有身份验证和授权机制。但是,由于真实应用程序需要身份验证和授权,因此我们需要在 RESTful API 中实现身份验证和授权机制。

Hapi 应用程序可以使用插件来集成身份验证和授权机制。Hapi 附带了一些身份验证插件,例如 Basic、JWT 和 OAuth2。

类型的身份验证

用于 RESTful API 的身份验证类型包括:当前用户、终端用户和应用程序用户。

  • 当前用户:你正在共享机器的情况。例如,你正在编写一个桌面应用程序,它基于 OAuth2 协议对资源进行身份验证。OAuth2 在该情况下通过请求资源来解决访问标识。
  • 终端用户:该角色属于实际使用 API 的用户。当应用程序向社交媒体网站发出请求时,终端用户是向该网站注册的每个人。
  • 应用程序用户:该角色属于使用 API 的应用程序。你可能正在与从代码运行的脚本或其他应用程序集成的服务进行通信。因此,你想确保你的请求来自正确的应用程序,而不是来自用户或其他应用程序。在这种情况下,API 可以使用身份验证令牌。

使用 JWT 进行身份验证

JSON Web Tokens (JWT)是一种安全传输信息的方法。在身份验证中,JWT 通常用于实现授权信息的传输。

在 Hapi 中,我们可以使用 hapi-auth-jwt2 插件来实现 JWT 身份验证。

先安装 hapi-auth-jwt2 插件:

然后在应用程序中注册插件:

-- -------------------- ---- -------
----- ---- - ----------------------
----- ------- - --------------------------

----- ---------------- - ----- -- -- -
    ----- ------ - -------------
        ----- -----
        ----- -----------
    ---

    ----- -------------------------
    --------------------------- ------ -
        ---- ------------------
        --------- -- -- -- -------- ---- --
    ---

    ---------------------------

    --------------
      ------- -------
      ----- ---------
      ------- -
        ----- -----
      --
      -------- ----- --------- -- -- -

        ----- - --------- -------- - - ----------------

        -- ------------ --- ----

        ----- ----- - ----- ---------- --------- -------- -- -------------------

        ------ ------
      -
    ---

    --------------
      ------- ------
      ----- ----
      -------- --------- -- -- -

        ------ ------- --------
      -
    ---

    ----- ---------------

    ------------------- ------- ----- -----------------
--

-------------------
展开代码

在上面的代码中,我们通过 await server.register(HapiJwt); 注册了 hapi-auth-jwt2 插件,然后创建了一个身份验证策略 jwt。在 jwt 策略中,我们使用 your-secret-key 作为密钥,并将 validate 函数设置为始终返回 isValid: true,表示所有请求都可以通过身份验证。

auth.default('jwt') 表示我们将 jwt 作为默认身份验证策略。

/login 路由中,我们使用 hapi-auth-jwt2 插件创建并返回 JWT。在 / 路由中,我们强制要求必须进行身份验证才能访问该路由。

最后,我们使用 server.start() 启动服务器。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67c045fc314edc26846921ed

纠错
反馈

纠错反馈