REST API - URL 中的字符串或数字标识符
REST API - string or numerical identifier in URL
我们正在为我们的平台开发 REST API。假设我们有 organisations
和 projects
,并且 projects
属于 organisations
。
阅读后,我倾向于在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。
对于 URL 定义使用名称而不是 ID,我能想到的优点和缺点如下:
优点:
- 对于最终用户来说更直观 URL
- 前端UI和JSON的1对1映射API
缺点:
- 必须使用唯一的名称
- 必须处理与保留名称的冲突,例如
count
,因此稍后,您仍然可以开发一个 API 端点,例如 /organisations/count
并实际获取组织而不是名为 count
. 的组织
尤其是后者,似乎成了后方的潜在隐痛。尽管如此,在阅读 this answer 之后,我几乎确信使用字符串标识符,因为从约定的角度来看它似乎没有什么不同。
我的问题是:
- 我是否错过了使用字符串而不是数字 ID 的重要优点/缺点?
- Github 是在他们的平台成熟后开发了他们基于字符串的方法,还是他们从一开始就知道这意味着一些限制(就像我之前提到的那样,他们似乎没有实现这样的功能)?
两者结合使用很常见:
/organisations/1234/projects/5678/nightwatch
最后一部分被忽略但用于使 url 更具可读性。
在您的情况下,对于多级集合,您可以尝试使用这种格式:
/organisations/1234/dutchpainters/projects/5678/nightwatch
如果有人写
/organisations/1234/germanpainters/projects/5678/wanderer
它仍然会映射到伦勃朗,但应该没问题。这将为编辑名称留出空间,而不会弄乱 url:s 已经准备就绪。此外,如果您真的不需要名称,则名称不必是唯一的。
Reserved HTTP characters: such as “:”, “/”, “?”, “#”, “[“, “]” and “@” – These characters and others are “reserved” in the HTTP protocol to have “special” meaning in the implementation syntax so that they are distinguishable to other data in the URL. If a variable value within the path contains one or more of these reserved characters then it will break the path and generate a malformed request. You can workaround reserved characters in query string parameters by URL encoding them or sometimes by double escaping them, but you cannot in path parameters.
https://www.serviceobjects.com/blog/path-and-query-string-parameter-calls-to-a-restful-web-service
不再推荐数字连续 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,因为它们具有相同的长度并且可以轻松解决此问题。
我们正在为我们的平台开发 REST API。假设我们有 organisations
和 projects
,并且 projects
属于 organisations
。
阅读/api/v1
):
/organisations/1234
/organisations/1234/projects/5678
但是,我们想为我们的前端UI使用相同的URL结构,这样如果你在浏览器中输入这些URL,你会得到相关的响应中的网页而不是 JSON
文件。与您在 Facebook 或 Github.
使用这个,我们可以得到类似的东西:
/organisations/dutchpainters
/organisations/dutchpainters/projects/nightwatch
看起来 Github 实际上以同样的方式暴露了 their API。
对于 URL 定义使用名称而不是 ID,我能想到的优点和缺点如下:
优点:
- 对于最终用户来说更直观 URL
- 前端UI和JSON的1对1映射API
缺点:
- 必须使用唯一的名称
- 必须处理与保留名称的冲突,例如
count
,因此稍后,您仍然可以开发一个 API 端点,例如/organisations/count
并实际获取组织而不是名为count
. 的组织
尤其是后者,似乎成了后方的潜在隐痛。尽管如此,在阅读 this answer 之后,我几乎确信使用字符串标识符,因为从约定的角度来看它似乎没有什么不同。
我的问题是:
- 我是否错过了使用字符串而不是数字 ID 的重要优点/缺点?
- Github 是在他们的平台成熟后开发了他们基于字符串的方法,还是他们从一开始就知道这意味着一些限制(就像我之前提到的那样,他们似乎没有实现这样的功能)?
两者结合使用很常见:
/organisations/1234/projects/5678/nightwatch
最后一部分被忽略但用于使 url 更具可读性。
在您的情况下,对于多级集合,您可以尝试使用这种格式:
/organisations/1234/dutchpainters/projects/5678/nightwatch
如果有人写
/organisations/1234/germanpainters/projects/5678/wanderer
它仍然会映射到伦勃朗,但应该没问题。这将为编辑名称留出空间,而不会弄乱 url:s 已经准备就绪。此外,如果您真的不需要名称,则名称不必是唯一的。
Reserved HTTP characters: such as “:”, “/”, “?”, “#”, “[“, “]” and “@” – These characters and others are “reserved” in the HTTP protocol to have “special” meaning in the implementation syntax so that they are distinguishable to other data in the URL. If a variable value within the path contains one or more of these reserved characters then it will break the path and generate a malformed request. You can workaround reserved characters in query string parameters by URL encoding them or sometimes by double escaping them, but you cannot in path parameters.
https://www.serviceobjects.com/blog/path-and-query-string-parameter-calls-to-a-restful-web-service
不再推荐数字连续 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,因为它们具有相同的长度并且可以轻松解决此问题。