2017-10-17 73 views
0

我是node.js的新手,并在hapi.js框架中创建了我的第一个node.js Restful API。所有的服务基本上都在做数据库查询。该服务的一个例子是这样的:构建Restful API时选择哪种HTTP方法

let myservice = { 
    method: "POST", 
    path: "/updateRule", 
    config: { 
     handler: (request, reply) => { 
      updateRule(request.payload) 
      .then((result) => { 
       reply(successResponse(request, result)); 
      }) 
      .catch((err) => reply(failResponse(request, err)).code(500)); 
     }, 
     validate: { 
      payload: { 
       ruleId: joi.number().required(), 
       ruleName: joi.string().required(), 
       ruleDesc: joi.string().required() 
      } 
     }, 
     auth: "jwt", 
     tags: ["api", "a3i"] 
    }, 
} 

updateRule(input): Promise<any> { 
     return new Promise((resolve, reject) => { 
      let query = `select a3i.update_rule(p_rul_id := ${input.ruleId}, p_rul_name := '${input.ruleName}', p_rul_desc := '${input.ruleDesc}')`; 
      postgresQuery(lbPostgres, query, (data, commit, rollback) => { 
       try { 
        let count = data.rows[0].update_rule.count; 
        if (count === 1) { 
         let ruleId = data.rows[0].update_rule.result[0]; 
         let payload: SuccessPayload = { 
          type: "string", 
          content: `Rule ${ruleId} has been updated` 
         }; 
         commit(); 
         resolve(payload); 
        } else { 
         let thisErr = new Error("No rule can be found."); 
         thisErr.name = "4003"; 
         throw thisErr; 
        } 
       } 
       catch (err) { 
        rollback(); 
        if (err.name === "4003") { 
         reject(detailError(4003, err.message)); 
        } else { 
         reject(detailError(4001, err.message)); 
        } 
       } 
      }, reject); 
     }); 
    } 

正如你所看到的,当服务被调用时,它唤起数据库调用(查询)和更新指定行中的数据库表。同样,我还有其他名为createRule/deleteRule的服务在数据库表中创建/删除记录。 在我看来,服务之间的区别是做不同的数据库查询。我看了这篇文章PUT vs. POST in REST,但在我的情况下看不到任何POST和PUT的区别。

这里是我的问题:

  1. 我应该在这种情况下使用什么HTTP方法?

  2. 大部分宁静的API的例子(例如https://www.codementor.io/olatundegaruba/nodejs-restful-apis-in-10-minutes-q0sgsfhbd)使用不同的HTTP方法相同的URL上相同的“资源”,这在我看来是通常一个数据库表做不同的操作。与我的惯例相比,这种体系结构的好处是什么?其中一个URL只有一个HTTP方法,只能执行一种类型的操作?

我知道这个问题没有提到问题,也没有具体说明。有些人可能会给它一个倒票。但作为初学者,我真的很想知道什么是典型的Restful API,并确保我的API是“最佳实践”。请帮忙!

回答

2

如果资源已经存在,因此你有一个特定的URI到那个确切的资源,你想更新它,然后使用PUT。

如果资源尚不存在,并且您想要创建它,并且您将让服务器选择代表该新资源的URI,那么使用POST并且POST URI将是一个通用的“创建新资源”URI,不是特定资源的URI,它将创建表示该资源的URI。

如果调用者要创建表示新资源的资源URI,还可以使用PUT创建新资源。在这种情况下,您只需将PUT添加到该新资源中,并且如果具有该URI的资源已经存在,则该资源将被更新,否则将被创建。

您不必同时支持两者。你可以决定让你的api工作,你只需要使用一个或另一个。


在您的特定情况下,在你的数据库中的特定行已经存在将几乎永远是一个PUT因为它已经存在,所以你在做一个PUT到特定URI表示该行的更新。

与我的惯例相比,这种体系结构的好处是什么?其中一个URL只有一个HTTP方法并且只执行一种类型的操作?

这真的取决于你如何呈现你的API。背后REST的一般概念是,你有几个组成部分:

resource identifier 
data 
method 

在某些情况下,该方法可以通过GET被纳入,PUT,POST或DELETE,所以你只需要资源标识符,数据和GET,PUT, POST或DELETE。

在其他情况下或其他设计中,该方法比仅在PUT或POST中可以表示的方法更详细,因此实际上在URL中有一个方法,在这种情况下,您可能不需要区分PUT和POST尽可能多。

例如,一个动作可能是“买”。虽然您可以在POST中捕获该方法,但该方法由URL的其余部分隐含,但您可能希望实际发布到其中包含方法的URL:/buy以便清晰起见,然后您可以使用与其他方法相同的端点前缀方法,如/addToCart等......它的确取决于REST设计中的对象以及您想要在其上展示哪些操作。有时候,这些对象只适用于GET,PUT,POST和DELETE,有时候,您希望URL中有更多的信息可以在该资源上执行特定的操作。

+0

看来我不得不向服务路径添加一个参数,因此每个资源(数据库表中的一行)都有相应的url。例如,当我想要对记录执行操作时,我需要将唯一ID作为url中的参数传递。这是正确的吗? – zhangjinzhou

+0

@ zhangjinzhou - 这将是RESTful的方式。 GET,PUT或DELETE的每个URI应代表一个唯一的资源。 – jfriend00

+0

是的,这是正确的。这被定义为URL中的可选参数。 – Silencer310

1

如果你想成为休息兼容,你可以使用PostGet。 如果你想成为问题的REST,你需要基础的方法对CRUD

  • 创建 - >发表
  • 阅读 - >获取
  • 更新 - >把或补丁
  • 删除 - >删除

关于构建完整的API,在相同的URL上使用方法可能更容易建立/理解。所有关于您的user的查询将位于user网址上,而不是user/getuser/add, user/update ......它让您拥有相同的功能,没有太多不同的URL。

当你建立一个API时,你会想要一些日志,进行统计分析和其他的东西。这样,如果您使用方法进行分割,则可以只使用筛选器记录多少Post请求或Get请求。

实际上,您也可以只使用Get请求来构建API。但随着方法和URL劈裂是避免复合URL(或URL有太大的动作名称),并有每一个请求,通过你的API去记录一个最简单的方法最好的办法

enter image description here - 列表项

  • 级别1是休息

  • 级别2是REST风格

  • 级别3是HATEOAS

你应该找一些书籍或由Martin Fowler

+0

感谢您的发布。不同的级别是非常有帮助的!我知道GET通常不足以构建API,因为您可能想要上传文件或传递流或其他内容。但是,使用POST/PUT创建/更新资源时,我没有看到任何区别。 – zhangjinzhou

+0

不能像使用POST一样使用PUT创建新资源,而不指定标识符? – zhangjinzhou

+0

是的,你可以使用这种方式 – sheplu

0

写的文章里面更多的信息我最常做的是使用“POST”创建一个新的资源,并使用“PUT”用于更新现有资源。

对于第二个问题,是的,大多数API使用相同的URL在同一资源上执行不同的操作。这可能是因为您不希望公开您在URL中做什么(例如/删除)的安全性。此外,许多框架为资源(对象类)生成一个自动URL,然后在请求方法上区分它。人们不会倾向于使用自定义网址。