构建Restful API时选择哪种HTTP方法

时间:2017-10-17 22:54:28

标签: node.js rest http-method

我是node.js的新手,拥有我的第一个node.js在hapi.js框架中构建的Restful API。所有的服务基本上都是做数据库查询。服务的一个例子是这样的:

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. 大多数Restful API示例(例如https://www.codementor.io/olatundegaruba/nodejs-restful-apis-in-10-minutes-q0sgsfhbd)使用不同HTTP方法的相同URL在同一“资源”上执行不同的操作,在我看来,这通常是数据库表。与我的实践相比,这种架构有什么好处,其中一个URL只有一个HTTP方法,只进行一种操作?

  3. 我知道这个问题不是指问题而是具体问题。有些人可能会给它一个投票。但作为初学者,我真的想知道什么是典型的Restful API,并确保我的API是“最佳实践”。请帮忙!

3 个答案:

答案 0 :(得分:2)

如果资源已经存在,因此您拥有该精确资源的特定URI,并且您想要更新它,那么请使用PUT。

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

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

您不必同时支持两者。你可以决定让api以你只使用其中一种的方式工作。

在您的特定情况下,数据库中已存在的特定行的更新几乎总是PUT,因为它已经存在,因此您正在对表示该行的特定URI执行PUT。

  

与我的实践相比,这种架构有什么好处,其中一个URL只有一个HTTP方法,只进行一种操作?

由您决定如何展示您的API。 REST背后的一般概念是你有几个组件:

resource identifier
data
method

在某些情况下,该方法可以通过GET,PUT,POST或DELETE包含,因此您只需要资源标识符,数据和GET,PUT,POST或DELETE。

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

例如,某个动作可能是“购买”。虽然您可以在POST中捕获该文件,其中该方法由URL的其余部分隐含,但您可能希望实际POST到具有其中方法的URL:/buy为了清楚起见然后您可以使用相同的使用其他方法(如/addToCart等)的端点前缀...这实际上取决于REST设计中的对象以及要在其上显示的操作。有时候,对象只能使用GET,PUT,POST和DELETE,有时候,你想在URL中获得更多关于在该资源上执行的特定操作的信息。

答案 1 :(得分:1)

如果您想要符合Rest,则可以使用PostGet。 如果你想成为Restfull,你需要将你的方法建立在CRUD上

  • 创建 - &gt;发布
  • 阅读 - &gt;获得
  • 更新 - &gt;放或补丁
  • 删除 - &gt;删除

关于构建完整的API,使用相同URL上的方法可以更容易构建/理解。关于您user的所有问题都将出现在user网址上,而不是user/getuser/adduser/update ...它会让您拥有相同的功能,太多不同的网址。

构建API时,您需要一些日志,统计分析和其他内容。这样,如果您使用方法拆分,则可以使用过滤器来记录发布请求的数量或获取请求的数量。

实际上,您也可以仅使用Get请求构建API。但是,使用方法和URL进行拆分是避免复杂URL(或具有过多操作名称的URL)的最佳方法,并且能够以最简单的方式记录通过API发出的每个请求

enter image description here   - 列出项目

  • 1级是休息

  • 第2级是Restfull

  • 3级是Hateoas

您应该在Martin Fowler撰写的一些书籍或文章中找到更多信息

答案 2 :(得分:0)

我通常使用“POST”创建新资源,并使用“PUT”更新现有资源。

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