RESTful API URI设计

RESTful API URI设计,rest,uri,restful-url,restful-architecture,Rest,Uri,Restful Url,Restful Architecture,我正在寻找有关RESTful API的URI设计的一些方向。我将有几个嵌套链接的资源,并且目前已经设计了与本文类似的URI: 下面的例子不是我正在构建的,但我认为它很好地说明了我的情况。(假设一个节目只能属于一个网络) 我的情况将与协会进一步发展两个层次,但所有协会都是一对多的。我正在考虑把它换成类似的东西: /networks [GET,POST] /networks/{network_id} [GET,PUT] /networks/{network_id}/shows [GET,POST]

我正在寻找有关RESTful API的URI设计的一些方向。我将有几个嵌套链接的资源,并且目前已经设计了与本文类似的URI:

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

我的情况将与协会进一步发展两个层次,但所有协会都是一对多的。我正在考虑把它换成类似的东西:

/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]
我的问题是:

  • 第二个示例是有效的REST设计吗
  • 是否应该考虑实现这两个路径?

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


    如果有意义的话,让多个URL指向同一个资源是非常好的。但更重要的是,确保资源中包含连接节目与网络、剧集与节目等的元素。

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

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

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

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

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

    回答你的问题:

  • 对于您的示例,IMHO第二个设计可能不是有效的REST设计。A. 解决方法可能是传递查询参数

  • 我认为设计1是自给自足的

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

  • 第二种设计对于您的示例来说是有效的REST设计
  • 只有设计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]
    
    URI是“可以指定名称的任何信息”

    您的问题是一个与域相关的问题,只有了解您使用URI命名的资源的人才能真正回答您的问题

    当你试图猜测你的域名时,我想到的问题是,“秀”真的依赖于“网络”吗

    您的域中的网络是什么?节目和网络之间的关系是什么?是不是仅仅是某个人在播放这个节目?还是更多地与生产信息有关


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

    我认为我们应该尽可能简单地保持RESTAPI URL

    e、 g

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

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

    e.g. tag
    
    <method>getEpisodes</method>
    
    例如标签
    获得剧集
    
    这里真正的问题是:您的第二个示例是否符合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的测试版,但您也可以将JSON-LD与RDF词汇表(例如schema.org+hydra)一起使用。本例仅涉及层次结构(上一个、第一个、下一个、上一个、最后一个、集合、项目等),但您应该添加更多元数据,例如哪些链接指向网络、哪些链接指向节目、哪些链接指向插曲等。。。因此,您的客户将从元数据中了解内容,例如,他们可以使用链接自动导航。这就是REST的工作原理。因此URI结构对客户端来说并不重要。(如果你想让你的响应更紧凑,你可以使用紧凑型URI和URI模板。)

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


    PD:对不起,我说的是英语。

    请记住,您最终决定了RESTful API的结构。是你的客户在使用它。我认为两者都是好的,尽管第一个显然更能说明网络、节目和剧集之间的层次关系。然而,如果URI变得异常长,那么分离出来让这些实体处于/之下也不是疯狂的。我会问你自己,什么样的资源实际上会被用得最多。如果是剧集和节目,那么将它们放在基础下就很有意义了。+1:我更喜欢
    xlink:href
    属性,但是
    元素不是个坏主意。属性在XML/XHTML中工作得很好,但JSON等表示法不支持它们。无论如何,重要的是利用超媒体使服务真正RESTful。这看起来不是特别RESTful,而是非常SOAPy(如果这是您正在做的,这是可以的,但是SOAP和REST是构建应用程序的非常不同的方法…)我主要关心的是API的版本。e、 我的稳定API发布版本是1.2,我的客户在他们的应用程序中使用相同的版本。现在我们增强了API(版本
    {
        "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"
            }
        }
    }