【问题标题】:REST API - string or numerical identifier in URLREST API - URL 中的字符串或数字标识符
【发布时间】:2017-05-31 14:08:23
【问题描述】:

我们正在为我们的平台开发一个 REST API。假设我们有organisationsprojects,而projects 属于organisations

读完this answer后,我会倾向于在URL中使用数字ID,这样一些URL就会变成(比如前缀/api/v1):

/organisations/1234
/organisations/1234/projects/5678

但是,我们希望为前端 UI 使用相同的 URL 结构,这样如果您在浏览器中键入这些 URL,您将在响应中获得相关网页,而不是 JSON 文件。就像您在 Facebook 或 Github 等网站上看到个人和组织的相关名称一样。

使用这个,我们可以得到类似的东西:

/organisations/dutchpainters
/organisations/dutchpainters/projects/nightwatch

看起来 Github 实际上以同样的方式公开了their API

使用名称而不是 ID 来定义 URL 的优点和缺点如下:

优点:

  • 为最终用户提供更直观的 URL
  • 前端 UI 和 JSON API 的一对一映射

缺点:

  • 必须使用唯一的名称
  • 必须处理与保留名称的冲突,例如count,所以稍后,您仍然可以开发类似/organisations/count 的API 端点,并实际获取组织的数量而不是名为count 的组织。

尤其是后者,似乎成为了潜在的后背痛。不过,在阅读 this answer 之后,我几乎确信要使用字符串标识符,因为从约定的角度来看,它似乎没有什么不同。

我的问题是:

  • 我是否错过了使用字符串而不是数字 ID 的重要优点/缺点?
  • Github 是在他们的平台成熟后开发了他们的基于字符串的方法,还是他们从一开始就知道这意味着一些限制(就像我之前提到的那样,他们似乎没有实现这样的功能)?李>

【问题讨论】:

    标签: rest url-routing github-api identifier api-design


    【解决方案1】:

    两者结合使用是很常见的:

    /organisations/1234/projects/5678/nightwatch
    

    最后一部分被简单地忽略,但用于使 url 更具可读性。

    在您的情况下,您可以尝试使用这种格式的多个级别的集合:

    /organisations/1234/dutchpainters/projects/5678/nightwatch
    

    如果有人写

    /organisations/1234/germanpainters/projects/5678/wanderer
    

    它仍然会映射到伦勃朗,但这应该没问题。这将为编辑名称留下空间,而不会弄乱 url:s allready。此外,如果您真的不需要,名称也不必是唯一的。

    【讨论】:

    • 我倾向于接受您的回答,只是想确保我没有错过使用字符串而不是数字 ID 的任何其他重要优点/缺点...您知道吗?
    • 嗯不,我不这么认为。
    【解决方案2】:

    Reserved HTTP characters: such as “:”, “/”, “?”, “#”, “[“, “]” and “@”——这些字符和其他字符在 HTTP 协议中是“保留的”,在实现语法中具有“特殊”含义,以便与 URL 中的其他数据区分开来。如果路径中的变量值包含一个或多个这些保留字符,那么它将破坏路径并生成格式错误的请求。您可以通过 URL 编码或有时通过双重转义来解决查询字符串参数中的保留字符,但您不能在路径参数中。

    https://www.serviceobjects.com/blog/path-and-query-string-parameter-calls-to-a-restful-web-service

    【讨论】:

    • 谢谢,我知道(非常常用的)查询参数和类似的,我们肯定会在某个时候使用它们,但现在我真的只是在寻找如何设置我的基本路径参数。
    • 是的,在查询字符串中您可以解决此问题,但使用路径参数您无法转义它们。对于您的示例,组织名称不能包含这些字符,否则 url 将中断。如果您控制数据库中的数据,这可能不会是一个主要问题。但是,如果数据对公共创建或编辑开放,则需要专门阻止这些字符进入该字段。
    【解决方案3】:

    不再推荐使用数字连续 ID,因为它很容易猜测数据库中的记录,有些人可能会使用它来获取他们无权访问的信息。

    使用数字 ID 是因为在数据库中它是一个固定长度的存储,这使得数据库的索引变得容易。例如 INT 在 MySQL 中有 4 个字节,而 BIGINT 是 8 个字节,所以数字在内存中的长度相同(INT 中的 100 与 200 的长度相同),因此很容易索引和搜索记录。

    如果数据库中有很多条目,那么使用 VARCHAR 字段来索引是个坏主意。您应该使用 CHAR(32) 等固定宽度字段并用空格填充差异,但您必须在程序中添加逻辑以在搜索数据库时处理差异。

    另一个想法是使用 slug,但在这里您应该考虑到一些记录可能具有相同的 slug,这取决于您使用什么来形成该 slug。 https://en.wikipedia.org/wiki/Semantic_URL#Slug

    我建议使用 UUID,因为它们具有相同的长度并且可以轻松解决此问题。

    【讨论】:

    • 嗯,我想这取决于您的安全实施对吧?我认为您的 SO ID 是 6676502...
    • 是的,这取决于,但我在许多应用程序中也遇到了它的问题,通过增加 ID,它会返回有关未链接到我的帐户的其他记录的信息。
    • 您可以使用 Slug 来识别记录,同样具有严格的长度,但在这里您应该处理冲突(对于同一记录具有相同的 slug)
    猜你喜欢
    • 2012-06-09
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多