使用 oEmbed 以编程方式发现共享代码
已发表: 2022-03-10网络充满了承载丰富内容的服务,例如视频、图像、音乐和播客、地图和图表,以及各种不同的乐趣。 很有可能,当您将内容添加到站点时,它会为您提供一种将内容嵌入到其他网页中的方法。
像 YouTube 这样的网站有自己的嵌入式播放器,在博客文章甚至产品页面中很受欢迎。 Soundcloud 有将他们的音乐播放器嵌入你乐队网站的代码。 慈善筹款人可能会将他们的大型比赛路线上传到 Strava 等网站,并希望在他们的筹款网站上分享给他们的赞助商。
所有这一切都是通过在托管站点上找到共享选项并复制一些通常是 HTML 和 JavaScript 混合的代码来完成的。 然后通常可以将该代码粘贴到目标页面中,托管站点将为您的所有朋友、客户和联系人提供丰富的内容表示形式。
到目前为止,一切都很好,这很好地涵盖了手动嵌入内容的选项。 然而,还有一个明显的第二个用例,其结果是相同的,但通往它的途径却大不相同。
以编程方式共享
假设您正在构建一个接受用户内容的应用程序或网站。 这可能是简单的,比如员工与同事分享新闻的基本 Intranet 页面,也可能是大型社交网络,人们可以在其中注册并开始发帖。
在这两种情况下,如果用户添加 URL 作为内容的一部分,您需要弄清楚该怎么做。 你可以想象这样的场景:
Check out this video! https://youtu.be/jw7bRnFbwAI
此时,作为发布系统,您需要弄清楚该怎么做。 第一个选项是什么都不做,只是将 URL 保留为纯文本。 这不是一个好主意,因为用户通常希望单击 URL,而纯文本无法帮助他们到达另一端的页面。
第二种选择是把它变成一个链接。 这是一个很好的下一步,因为用户可以点击链接并获取内容。 但这样做时,他们会离开您的网站,并且可能不会很快回来。
最好的用户体验可能是能够获取该内容的播放器并将其嵌入其中,而不仅仅是 URL。 这将使用户能够直接在您的网站中体验内容,就像他们在 Facebook 上一样。
这就提出了问题。 给定一个 URL,我如何将其转换为在页面上显示富播放器所需的 HTML/JavaScript 嵌入代码?
如果它是 YouTube 之类的知名网站,我可以编写一些代码,使用 YouTube API 来获取视频信息并以这种方式获取或构建嵌入代码。 我可以对 Vimeo 和 VIVO 等其他视频服务做同样的事情。 我可以编写代码来识别 Flickr 和 Instagram 的 URL,并使用它们的 API 来获取漂亮的可嵌入版本的照片。 Twitter 和推文也是如此。 但这听起来像很多工作!
理想的情况是,如果有一种标准化的方法可以从一段内容的 URL 获取到嵌入代码块,以在页面上显示该内容。 如果您一直在关注,您会发现答案就是 oEmbed。
oEmbed 的由来
这正是 Leah Culver 在 Pownce(一个真正创新的社交网站,是 Twitter 的 VHS 的 Betamax)工作时遇到的问题。 Pownce 希望将丰富的内容表示嵌入到用户的更新流中,但不想将支持仅限于他们专门编写代码以与之集成的服务。 在与同事 Mike Malone 以及 Cal Henderson(他在 Flickr 领导工程——当时是此类内容的主要提供商之一)和 Richard Crowley 共进晚餐时,他们一起讨论了一个用于获取嵌入代码的开放标准的想法一个网址。 Henderson 离开并根据讨论起草了一些东西,oEmbed 诞生了。
使用 oEmbed
这是它的工作原理。
它以指向单个内容项的 URL 开头。 这可能是 YouTube 视频、图像或其他任何内容。 通常,这将由您的网站或应用程序的用户作为他们希望发布的某些内容的一部分提供。 第一步是获取该 URL 的页面内容,该 URL 应该是一个 HTML 页面。
如果托管内容的站点支持 oEmbed,则在该页面的<head>
部分中应该有一个带有oembed
内容类型的link
元素:
<link rel="alternate" type="application/json+oembed" href="https://youtube.com/oembed?url=https%3A%2F%2Fyoutu.be%2Fjw7bRnFbwAI&format=json" title="Inclusive Components with Heydon Pickering" />
关于 XML 的说明: oEmbed 支持 XML 和 JSON 格式的响应。 对于本文,我只考虑 JSON,因为我们不是野蛮人。 如果您不幸需要使用 XML,请注意它是 oEmbed 规范支持的格式,尽管您可能会发现某些提供程序仅提供 JSON 响应。
此链接标记作为rel
属性设置为alternate
, type
设置为application/json+oembed
或text/xml+oembed
。 正是这个属性让我们知道在href
中给出的 URL 实际上是一个 oEmbed API 端点,用于检索内容的详细信息。
该 URL 通常有两个参数: url
和format
。
范围 | 价值 |
---|---|
url (必填) | 内容项的 URL 编码网址 |
format | 您希望响应的格式json 或xml 之一 |
初始消费者请求的通用 URL 参数
完整的规范在此处进行了更详细的介绍(如果创建自己的实现,您应该参考它),但这是您可能会看到最多的两个参数。
因此,我们得到了一个 URL,获取了页面,找到了一个 oEmbed 链接标签,其中包含另一个用于 API 端点的 URL。 接下来,我们请求该新 URL,它会返回服务必须提供的有关该内容的所有信息。
{ "author_name": "Smashing Magazine", "width": 480, "title": "Smashing TV: Inclusive Components with Heydon Pickering (Nov 7th 2019)", "provider_name": "YouTube", "height": 270, "html": "<iframe width=\"480\" height=\"270\" src=\"https://www.youtube.com/embed/jw7bRnFbwAI?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>", "provider_url": "https://www.youtube.com/", "thumbnail_url": "https://i.ytimg.com/vi/jw7bRnFbwAI/hqdefault.jpg", "type": "video", "thumbnail_height": 360, "author_url": "https://www.youtube.com/channel/UCSDtqcJ8ZXviPrEcj1vuLiQ", "version": "1.0", "thumbnail_width": 480 }
现在我们在说话! 响应为我们提供了有关内容的大量信息。 在可预见的将来, version
应该是1.0
,这是 oEmbed 规范的当前版本。 返回的其他信息很大程度上取决于type
的值。
响应类型
响应中type
键的值告诉您要嵌入哪种媒体。
type 值 | 期待什么 |
---|---|
photo | 提供可用于基本img 标签的url 、 width 和height 的静态照片 |
video | 一个视频播放器,带有html 指定在页面上嵌入播放器所需的代码,尽管具有width 和height |
link | 毕竟,处理这些内容的最好方法就是提供一个链接。 响应可能有其他有用的信息,如标题,但它应该只是链接起来。 |
rich | 某种内容丰富的播放器,就像视频类型一样返回html 、 width 和height |
除了专用视频内容之外,您可能在野外看到的更常见的类型是rich
。 即使是 Flickr 本身,在仍然发送photo
响应的同时,也为图像的丰富可嵌入“播放器”提供html
。
大多数情况下,将内容嵌入您的网站只是使用提供的代码作为html
值的一种情况。
关于安全的说明
您可能正确谨慎的一件事是获取 HTML 响应并将其以编程方式嵌入到您托管的页面中。 如果没有人为的步骤来仔细检查您粘贴的代码,那么该代码总是有可能是恶意的。 因此,您应该采取适当的措施来降低风险。
这可能包括过滤 URL 以确保方案和域与预期匹配,以及将代码沙箱化到不同的无 cookie 域上的 iframe 中。 您应该了解您使用代码的情况,并确保您没有将自己暴露在不适当的风险中。
入门
尽管在使用 oEmbed 时理解流程很重要,但现实情况是,大多数常用语言都有可用的库来抽象流程并使其相对简单。
例如,npm 打包的 oembed 提供了一个非常简单的接口,用于根据内容 URL 发出请求并返回 oEmbed 响应。
首先将包安装到您的项目中:
npm i oembed
然后请求 URL。 在这里,我使用了关于 oEmbed 的 Notist 演示文稿的 URL。 多么元。
const oembed = require('oembed'); const url = 'https://noti.st/drewm/ZOFFfI'; oembed.fetch(url, { maxwidth: 1920 }, function(error, result) { if (error) console.error(error); else console.log("oEmbed result", result); });
和回应:
{ type: 'rich', version: '1.0', title: 'Understanding oEmbed', author_name: 'Drew McLellan', author_url: 'https://noti.st/drewm', provider_name: 'Notist', provider_url: 'https://noti.st', cache_age: 604800, thumbnail_url: 'https://on.notist.cloud/slides/deck4179/large-0.png', thumbnail_width: 1600, thumbnail_height: 900, html: '<p data-notist="drewm/ZOFFfI">View <a href="https://noti.st/drewm/ZOFFfI">Understanding oEmbed</a> on Notist.</p><script async src="https://on.notist.cloud/embed/002.js"></script>', width: 960, height: 540 }
如果你想在 PHP 中做同样的事情,可以通过 Composer 安装一个名为 embed/embed 的方便的包。
composer require embed/embed
然后在您的 PHP 项目中:
use Embed\Embed; $info = Embed::create('https://noti.st/drewm/ZOFFfI'); $info->title; // "Understanding oEmbed" $info->authorName; // "Drew McLellan $info->code; // "<p data-notist="drewm/ZOFFfI"> ... </script>"
如您所见,使用库,该过程变得非常简单,您可以快速从 URL 获取嵌入代码,准备显示用户内容的丰富表示。
结论
oEmbed 是一个非常优雅的解决方案,可以解决非常具体的问题。 您会认为只有少数在大型社交网络上工作的工程师会从中受益,这是可以原谅的,但实际上,用户可能输入 URL 的发布系统非常普遍。 给我找一位在某些时候不需要构建某种 CMS 的后端工程师。 我们可能不会以相同的方式考虑它,但如果您接受用户输入,您应该考虑如果该输入包含 URL 该怎么办。
既然您了解了 oEmbed(抱歉),您就没有理由不认真考虑在未来项目中如何处理 URL。
- o嵌入规范
- 用于 NodeJS 的 oembed
- 嵌入/嵌入 PHP
- “宣布 OEmbed:嵌入式内容的开放标准”,Leah Culver