RESTful API URI设计

时间:2012-10-23 20:45:04

标签: rest uri restful-url restful-architecture

我正在寻找关于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. 我应该考虑实施两条路径吗?

6 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:1)

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

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

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

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

我相信你的榜样2更合适。

答案 2 :(得分:1)

真正的问题是:你的第二个例子是否符合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模板。)

答案 3 :(得分: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. IMHO第二个设计可能不是您的示例的有效REST设计。一个 解决方法可能是传递查询参数

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

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

    1. 第二个设计是针对您的示例的有效REST设计
    2. 只有设计2也应该足够
    3. 此外:

      /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]
      

答案 4 :(得分:0)

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

e.g。 https://www.yoursite.com/api/xml/1.0/

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

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

e.g. tag

<method>getEpisodes</method>

答案 5 :(得分:0)

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

PD:抱歉我的英文。