Web services 社交网络的RESTful设计

Web services 社交网络的RESTful设计,web-services,api,rest,social-networking,Web Services,Api,Rest,Social Networking,我正试图用RESTful设计来表达我的想法,我想从社交网络的角度来理解它。我读过,看过其他一些书,读过很多在线资源。然而,当我将这些规则应用于现实世界的问题时,我意识到我并不是完全理解一切。我想通过具体说明一些问题来了解我是否正确理解REST: 层次与平面设计 让我们假设我使用 /users/42 现在,该用户上传的照片将以 /users/42/photos /users/42/photos/1337/tags 如果他/她在照片中给他/她的朋友贴上标签,那么这些标签最终会出现在照片中 /u

我正试图用RESTful设计来表达我的想法,我想从社交网络的角度来理解它。我读过,看过其他一些书,读过很多在线资源。然而,当我将这些规则应用于现实世界的问题时,我意识到我并不是完全理解一切。我想通过具体说明一些问题来了解我是否正确理解REST:

层次与平面设计 让我们假设我使用

/users/42
现在,该用户上传的照片将以

/users/42/photos
/users/42/photos/1337/tags
如果他/她在照片中给他/她的朋友贴上标签,那么这些标签最终会出现在照片中

/users/42/photos
/users/42/photos/1337/tags
但是,这并不能找到标记了特定用户的所有照片。我应该为这个问题提出不同的层次结构吗?看起来有点尴尬。我是否可以完全忽略层次结构,并结合这样的查询提供照片

/photos?owner=42
/photos?tagged=42
不同用户的内容不同时的缓存 Web服务应设计为提供可缓存的数据(以便客户端可以决定使用本地副本,如果它认为没有任何更改),但这如何影响不同用户的隐私设置?两个都已登录的用户可能有权查看有关用户42的不同信息。这是否意味着我需要为访问同一用户的配置文件信息的不同用户请求不同的URI,或者只要用户提供不同的凭据,缓存就不会成为问题

从同一资源提供HTML和JSON/XML 我提到的那本书在他们的示例中指定了一条规则,即在以
API
开头的子域中应该可以访问APIhttp://api.soccer.restapi.org。我计划使用相同的控制器进行用户访问和机器访问(例如移动应用程序)。控制器将通过HTTP请求头中的
Accept
字段决定提供哪个视图(
text/html
application/json
application/xml
)。出于某种原因,我认为这是个坏主意(因为用户希望看到子域
www
,而不是
api
),但我不明白为什么。
www
api
是否可以指向同一台服务器,或者我是否应该尝试将HTML视图移动到其他虚拟主机?为什么?

我相信RubyonRails将(约定重于配置)从同一个控制器提供HTML和JSON,从而分享我的想法,即HTML和JSON只是相同数据的不同表示

换句话说,我的书说某个资源应该只有一个URI,并且应该基于
Accept
字段提供不同的表示。在不同子域之间重定向用户将违反关于从同一资源提供任何表示的规则,而复制信息(即将两个子域指向同一虚拟主机)则违反关于不为同一资源提供多个URI的规则。不提供
api
子域违反了另一个设计规则。如何在不违反任何规则的情况下解决此问题

限制发送回的数据 查询组件应该用于分页,但我是否可以拒绝满足缺少搜索条件的列表请求并限制项目数量,而不违反REST?我希望既减少数据库负载,又避免有人映射整个用户目录。我想要

/users
是非法请求,而

/users?name=leet+hacker
有效,但仅返回100件物品

我还想知道,只有在使用查询专门请求数据库列时,才返回数据库列的子集和更多/所有列是否合法

提供冗余数据的控制器 我相信提供这样的控制器是合法的

/users/me
但是它应该提供与文档URI完全相同的信息吗

/users/42
还是应该重定向到它

某些用户的扩展权限 哪种RESTful方式可以提供附加功能,例如管理权限?我现在假设管理员(一张照片、一组用户或整个站点的管理员)能够比其他用户看到更多关于特定对象的信息。该信息是否应保存在完全相同的URI中,并自动发送给管理员而不是其他任何人,是否应存储在不同的位置,是否应使用特定的管理员查询请求或以其他方式提供

本地化和设置更新
虽然大多数用户可见的字符串都应该由视图提供,但是有些设计决策可能涉及API。最明显的是名字。社交网络有时允许用户输入在不同语言环境中显示的不同名称。一些语言的名字,如俄语和阿拉伯语,不容易自动转录。在其他语言中,如汉语,本地和国际名称可以完全不同,没有任何相似或联系。处理这件事的平静方式是什么?我有一种感觉,答案将是
接受语言
字段,但是有人认真考虑过在他们所属的社交网络上切换语言吗?是否每次都要将所有这些信息返回给呼叫者,或者我可以依赖这些设置?这是否适用于缓存?

如果您使用的是WCF Web Api(或者即使您不使用),那么在这里查看OData支持可能是值得的。它确实解决了一些使事情更具搜索性的问题。

正如@Mark Dickinson所提到的,这里有很多问题,它们确实应该分开,但我会尽我所能

层次结构与平面设计的对比

REST中并没有任何东西表明您不能拥有多个并行层次结构(尽管我知道这样做是基于
<users>
    <user id="69" href="/users/69" name="John Smo"/>
    <user id="84" href="/users/84" name="Jane Smo"/>
    ...
    <next href="/users?page=3"/>
    <prev href="/users"/>
</users>
<users>
    <user id="69" href="/users/69" name="John Smo"/>
    <user id="84" href="/users/84" name="Jane Smo"/>
    ...
    <next href="/users?page=2"/>
    <prev href="/users"/>
    <search href="/users" method="get">
        <name cardinality="required" type="regex"/>
    </search>
</users>
<users>
    <user id="234" href="/users/234" name="leet hacker"/>
    <user id="999" href="/users/999" name="leet hacker"/>
    ...
    <next href="/users?name=leet+hacker&page=2"/>
    <search href="/users" method="get">
        <name cardinality="required" type="regex"/>
    </search>
</users>
<image id="266" href="/photos/266" caption="leet hacker with computer"
       src="http://us.123rf.com/400wm/400/400/creatista/creatista0911/creatista091100003/5827629.jpg"/>
    <tagged-users>
        <user id="234" href="/users/234" name="leet hacker"/>
    </tagged-users>
    <owner id="234" href="/users/234" name="leet hacker"/>
</image>
<image id="266" href="/photos/266" caption="leet hacker with computer"
       src="http://us.123rf.com/400wm/400/400/creatista/creatista0911/creatista091100003/5827629.jpg"/>
    <tagged-users>
        <tagged-user id="234" href="/users/234" name="leet hacker">
            <delete href="/photos/266/tagged/234" method="delete"/> 
        </tagged-user>
        <add href="/photos/266" method="put">
            <user cardinality="required" type="user-id"/>
        </add>
    </tagged-users>
    <owner id="234" href="/users/234" name="leet hacker"/>
    <delete href="/photos/266" method="delete"/>
    <update href="/photos/266" method="put">
        <caption cardinality="optional" type="string"/>
    </update>
</image>