2

所以我正在尝试向我们的 CMS 添加一个新的、闪亮的 REST Web 服务。它应该非常接近 REST“规则”,因此它应该使用 GET/POST/PUT/DELETE 和正确的逻辑 URL。我的设计深受Apigee Best Practices的启发。

CMS 管理一个类别树,其中每个类别可以包含许多文章。对于多语言项目,每种语言的类别都是重复的(因此任何文章都由其 ID 和语言 ID 唯一标识)。所有语言的结构都是相同的,只是位置可以不同(因此类别 X 包含每种语言中的类别 Y 和 Z,但在语言 1 中 Y 可以在 Z 之前,而在语言 2 中则相反)。创建新文章或类别总是会创建所有语言的副本。删除的工作方式相同,因此始终删除所有语言的文章。

仅供参考:语言由其数字 ID 或语言环境(如en_US)标识。

(请/v1在所有 URI 前面画一个前导;我跳过了它,因为它对这个问题没有任何帮助。)`

我目前的方法是使用这样的 URL 方案:

GET    /articles               :(  returns all articles in all languages
GET    /articles/:id-:langid   :)  returns a single article in a given language
POST   /articles               :)  creates a new article
PUT    /articles/:id-:langid   :)  update a single article in a given language
DELETE /articles/:id           :)  delete an article in all languages

但...

如何识别语言?

目前,每种语言分配的区域设置不需要是唯一的,因此在极少数情况下两种语言可以具有相同的区域设置。使用 ID 保证是唯一的。

使用区域设置(很可能强制小写)会很好,因为 URL 更具可读性。但这会

  • 可能会导致项目具有重叠的语言环境。
  • 要求客户端首先获取语言环境(但我猜客户端无论如何都必须获取语言 ID,所以这没关系)。

我想最终得到一个解决方案,并倾向于使用语言环境。但是,是否值得冒重叠地区的风险?

(您可以在下面的图像langid=X中互换locale=xx_xx。)

语言应该是层次结构元素吗?

在大多数情况下,API 的客户端将希望获取给定语言的文章,而不是全部。我可以通过允许 GET 参数和 offer 来解决这个问题GET /articles?langid=42。但由于这是一个常见的用例,我想避免使用可选参数并使其明确。

这将导致GET /articles/:langid,但这引入了语言是 API 内部层次结构级别的概念。如果我要这样做,我想让其他动词保持一致。新的 URL 布局如下所示:

GET    /articles/:langid       :)  returns all articles in a given language
GET    /articles/:langid/:id   :)  returns a single article in a given language
POST   /articles               :(  creates a new article in all languages
PUT    /articles/:langid/:id   :)  update a single article in a given language
DELETE /articles/:langid/:id   :(  delete an article in all languages

或者

GET    /:langid/articles       :)  returns all articles in a given language
GET    /:langid/articles/:id   :)  returns a single article in a given language
POST   /articles               :(  creates a new article in all languages
PUT    /:langid/articles/:id   :)  update a single article in a given language
DELETE /:langid/articles/:id   :(  delete an article in all languages

这将导致...

如何处理全球行动?

上述布局存在适用于所有语言的问题POSTDELETE但 URL 表明它们仅适用于一种语言。所以我可以修改布局:

GET    /articles/:langid       :)  returns all articles in a given language
GET    /articles/:langid/:id   :)  returns a single article in a given language
POST   /articles               :)  creates a new article in all languages
PUT    /articles/:langid/:id   :)  update a single article in a given language
DELETE /articles/:id           :)  delete an article in all languages

这使得布局有些混乱,因为语言级别只是有时存在,并且需要对系统的内部有很多了解。从好的方面来说,这与系统非常匹配,并且与内部工作非常相似。

牺牲?

那么我在哪里做牺牲呢?我是否应该引入别名 URL 以获得良好的 URL 布局,但可能会在背景中做一些意想不到的事情?

4

2 回答 2

1

前段时间我遇到了完全相同的问题,我决定把本地放在一切前面。在消费内容时,阅读以下 URL 更有意义:

/en/articles/1/

/en/authors/2/

/gr/articles/1/

/gr/authors/2/

/articles/en/1/

/authors/en/2/

/articles/gr/1/

/authors/gr/2/

为了解决“没有特定语言环境”的问题,我会使用一个关键字来引用所有可用的语言环境或默认语言环境。所以:

/global/articles/

或者

/all-locales/articles/

或者

/all/articles/

老实说,我喜欢 global ,因为它们读起来很有意义。

DELETE /global/articles/:id :) delete an article in all languages

希望我有所帮助

于 2013-07-08T09:16:01.397 回答
0

我最初的方法是将语言作为 URL 中的可选前缀,例如/en_us/articles, /en_us/articles/:id,但是如果您不想使用语言标识符“污染”您的 URL,您可以使用Accept-language标头代替,就像内容协商一样在RFC 2616中定义。Microsoft 的 WebAPI 正在使用这种方法进行格式协商。

于 2012-11-02T21:45:57.477 回答