RESTful API URI设计

问题描述 投票:13回答:6

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

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

/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. 我应该考虑实施两条路径吗?
rest uri restful-url restful-architecture
6个回答
6
投票

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

如果有意义的话,将多个URL指向同一资源是完全正常的。 但更重要的是,确保资源包含将节目连接到网络,剧集到节目等的<link />元素。


2
投票

这里真正的问题是:你的第二个例子是否符合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"
        }
    }
}

现在,这只是具有IANA链接关系的HAL + JSON中的测试版,但您也可以使用带有RDF词汇表的JSON-LD(例如schema.org + hydra)。 这个例子只是关于层次结构(up,first,next,previous,last,collection,item等),但是你应该添加更多的元数据,例如哪个链接指向网络,哪个链接指向节目,哪个链接指向一集等等......因此,您的客户将从元数据中了解内容的内容,例如,他们可以使用链接自动导航。 这就是REST的工作原理。 所以URI结构对客户来说并不重要。 (如果您希望使响应更紧凑,也可以使用紧凑的URI和URI模板。)


1
投票

URI是“可以赋予名称的任何信息”

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

在尝试猜测您的域名时想到的问题是“显示”真的取决于“网络”吗?

您域中的网络是什么? 节目与网络之间的关系是什么? 这只是播放节目的人吗? 或者更多的是与生产信息有关?

我相信你的例子2更合适。


0
投票

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

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

或换句话说,以下网址将是多余的:

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

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

0
投票

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

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

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

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

e.g. tag

<method>getEpisodes</method>

0
投票

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

PD:抱歉我的英文。

© www.soinside.com 2019 - 2024. All rights reserved.