13

我正在寻找有关 RESTful API 的 URI 设计的方向。我将有几个嵌套的链接资源,目前我的 URI 设计类似于这篇文章:Hierarchical RESTful URL design

以下示例不是我正在构建的,但我认为很好地说明了我的情况。(假设一个节目只能属于一个网络)。

/networks [GET,POST]
/networks/{network_id} [GET,PUT]
/networks/{network_id}/shows [GET,POST]
/networks/{network_id}/shows/{show_id} [GET,PUT]
/networks/{network_id}/shows/{show_id}/episodes [GET,POST]
/networks/{network_id}/shows/{show_id}/episodes/{episode_id} [GET,PUT]

我的情况将通过关联进一步发展两个层次,但所有关联都是一对多的。我正在考虑将其切换为类似于以下内容:

/networks [GET,POST]
/networks/{network_id} [GET,PUT]
/networks/{network_id}/shows [GET,POST]

/shows [GET]
/shows/{id} [GET,PUT]
/shows/{id}/episodes [GET,POST]

/episodes [GET]
/episodes/{id} [GET,PUT]

我的问题是:

  1. 第二个示例是有效的 REST 设计吗?
  2. 我应该考虑实现这两条路径吗?
4

6 回答 6

6

第二个例子对我来说很好。URL 是对资源的描述,并且使用了正确的 HTTP 动词。

如果有意义的话,让多个 URL 指向同一个资源是完全可以的。但更重要的是,确保资源包含<link />将节目与网络、剧集与节目等相关联的元素。

于 2012-10-23T20:51:33.540 回答
3

这里真正的问题是:您的第二个示例是否满足 URI 标准?URI 标准规定,路径包含分层部分,查询包含非分层部分,但是 afaik。它没有说明如何在您的情况下设计 URI 结构。REST 统一接口约束有一个 HATEOAS 部分,这意味着您应该在您的情况下发回指向上层和下层资源的链接。您应该使用元数据注释这些链接,这些元数据可以由客户端处理,因此它会知道链接是关于什么的。所以在实践中URI结构并不重要......

GET /shows/123

{
    "label": "The actual show",
    "_embedded": {
        "episodes": [
            {
                "label":  "The first episode of the actual show",
                "_embedded": {
                    "associations": [
                        //...
                    ]
                },
                "_links": {
                    "self": {
                        "label": "Link to the first episode of the actual show",
                        "href": "/episodes/12345"
                    },
                    "first": {
                        "href": "/episodes/12345"
                    },
                    "duplicate": {
                        "href": "/networks/3/shows/123/episodes/12345"
                    },
                    "up": {
                        "label": "Link to the actual show",
                        "href": "/shows/123"
                    },
                    "next": {
                        "label": "Link to the next episode of the actual show"
                        "href": "/episodes/12346"
                    },
                    "previous": null,
                    "last": {
                        "href": "/episodes/12350"
                    }
                }
            }//,
            //...
        ]
    },
    "_links": {
        "self": {
            "label": "Link to the actual show",
            "href": "/shows/123"
        },
        "duplicate": {
            "href": "/networks/3/shows/123"
        },
        "up": {
            "label": "Link to the actual network",
            "href": "/networks/3"
        },
        "collection": {
            "label": "Link to the network tree",
            "href": "/networks"
        },
        "next": {
            "label": "Link to the next show in the actual network",
            "href": "/shows/124"
        },
        "previous": {
            "label": "Link to the previous show in the actual network",
            "href": "/shows/122"
        }
    }
}

现在这只是 HAL+JSON 中带有 IANA 链接关系的测试版,但您也可以将 JSON-LD 与 RDF 词汇表(例如 schema.org+hydra)一起使用。这个例子只是关于层次结构(上,第一个,下一个,上一个,最后一个,集合,项目等...),但您应该添加更多元数据,例如哪个链接指向网络,哪个链接指向一个节目,以及哪个链接一集,等等......所以您的客户将从元数据中知道内容是关于什么的,例如,他们可以使用链接自动导航。这就是 REST 的工作方式。所以 URI 结构对客户端来说并不重要。(如果你想让你的响应更紧凑,你也可以使用紧凑的 URI 和 URI 模板。)

于 2015-01-09T15:30:59.020 回答
1

URI 是“可以命名的任何信息”

您的问题是与域相关的问题,只有知道您使用 URI 命名的资源的人才能真正回答。

尝试猜测您的域时想到的问题是,“节目”真的依赖于“网络”吗?

您的域中的网络是什么?节目和网络是什么关系?只是单纯的播过节目的人吗?还是更多地与生产信息有关?

我相信您的示例 2 更合适。

于 2012-10-23T21:17:37.937 回答
1

考虑到您在以下层次结构中有一对多关系:

network --> shows --> episodes

我认为第二种设计没有向服务器端提供足够的信息来处理您的请求。例如,如果您有以下数据:

Network id  show_id episode_id
    1         1        1
    1         2        1
    1         1        2

第一个详细的设计将在 HTTP 请求中提供足够的信息来获取数据:/networks/1/shows/1/episodes/1

相反,第二种设计将具有:

/episodes/1 

在第二种设计中,服务器端无法知道您是指数据中的第 1 行还是第 2 行

要回答您的问题:

  1. 恕我直言,第二个设计对于您的示例可能不是有效的 REST 设计。一种解决方法可能是传递查询参数

  2. 我认为设计 1 是自给自足的

更新:请忽略我上面的回答

  1. 第二种设计是您示例的有效 REST 设计
  2. 只有设计2就足够了

此外:

/networks
/networks/{id}

/shows
/shows/{id}

/episodes
/episodes/{id}

应该有足够数量的 REST URL

或者换句话说,以下 URL 将是多余的:

/networks/{network_id} [GET,PUT]
/networks/{network_id}/shows [GET,POST]

/shows/{id}/episodes [GET,POST]
于 2012-10-23T21:03:00.310 回答
0

我认为第二个选项是好的,但如果你想验证关系,我会考虑第一个选项。例如,当您使用不同的网络获得一集时,这可能意味着该集在您的请求之前已被修改,因此您可能需要使用 422 响应,对于其他服务也是如此。有了这个,您可以确定您想要工作的实体涉及其父级。

PD:对不起我的英语。

于 2015-01-09T17:32:23.347 回答
0

我认为我们应该尽可能简单地保持 REST API URL。

例如https://www.yoursite.com/api/xml/1.0/

这里我以 1.0 版的 XML API 为例。请记住为将来的更新使用 API 的版本。

您可以检查客户端请求的方法。

e.g. tag

<method>getEpisodes</method>
于 2012-10-23T21:21:07.810 回答