diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-10-16 10:05:49 +0200 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-10-16 10:07:26 +0200 |
commit | d8755eed1e452d2efbfc983af0e9d228d152bf6b (patch) | |
tree | db94181e7c993f67919f4ea2bb12f08401c437c2 /server/controllers | |
parent | 334ddfa47120ae53bc2643792ec5e1065a4d1141 (diff) | |
download | PeerTube-d8755eed1e452d2efbfc983af0e9d228d152bf6b.tar.gz PeerTube-d8755eed1e452d2efbfc983af0e9d228d152bf6b.tar.zst PeerTube-d8755eed1e452d2efbfc983af0e9d228d152bf6b.zip |
Add oembed endpoint
Diffstat (limited to 'server/controllers')
-rw-r--r-- | server/controllers/client.ts | 32 | ||||
-rw-r--r-- | server/controllers/index.ts | 1 | ||||
-rw-r--r-- | server/controllers/services.ts | 62 |
3 files changed, 85 insertions, 10 deletions
diff --git a/server/controllers/client.ts b/server/controllers/client.ts index b23f7e1ae..e3c962058 100644 --- a/server/controllers/client.ts +++ b/server/controllers/client.ts | |||
@@ -8,7 +8,7 @@ import { | |||
8 | CONFIG, | 8 | CONFIG, |
9 | STATIC_PATHS, | 9 | STATIC_PATHS, |
10 | STATIC_MAX_AGE, | 10 | STATIC_MAX_AGE, |
11 | OPENGRAPH_COMMENT | 11 | OPENGRAPH_AND_OEMBED_COMMENT |
12 | } from '../initializers' | 12 | } from '../initializers' |
13 | import { root, readFileBufferPromise } from '../helpers' | 13 | import { root, readFileBufferPromise } from '../helpers' |
14 | import { VideoInstance } from '../models' | 14 | import { VideoInstance } from '../models' |
@@ -19,7 +19,7 @@ const distPath = join(root(), 'client', 'dist') | |||
19 | const embedPath = join(distPath, 'standalone', 'videos', 'embed.html') | 19 | const embedPath = join(distPath, 'standalone', 'videos', 'embed.html') |
20 | const indexPath = join(distPath, 'index.html') | 20 | const indexPath = join(distPath, 'index.html') |
21 | 21 | ||
22 | // Special route that add OpenGraph tags | 22 | // Special route that add OpenGraph and oEmbed tags |
23 | // Do not use a template engine for a so little thing | 23 | // Do not use a template engine for a so little thing |
24 | clientsRouter.use('/videos/watch/:id', generateWatchHtmlPage) | 24 | clientsRouter.use('/videos/watch/:id', generateWatchHtmlPage) |
25 | 25 | ||
@@ -43,11 +43,11 @@ export { | |||
43 | 43 | ||
44 | // --------------------------------------------------------------------------- | 44 | // --------------------------------------------------------------------------- |
45 | 45 | ||
46 | function addOpenGraphTags (htmlStringPage: string, video: VideoInstance) { | 46 | function addOpenGraphAndOEmbedTags (htmlStringPage: string, video: VideoInstance) { |
47 | const previewUrl = CONFIG.WEBSERVER.URL + STATIC_PATHS.PREVIEWS + video.getPreviewName() | 47 | const previewUrl = CONFIG.WEBSERVER.URL + STATIC_PATHS.PREVIEWS + video.getPreviewName() |
48 | const videoUrl = CONFIG.WEBSERVER.URL + '/videos/watch/' + video.id | 48 | const videoUrl = CONFIG.WEBSERVER.URL + '/videos/watch/' + video.uuid |
49 | 49 | ||
50 | const metaTags = { | 50 | const openGraphMetaTags = { |
51 | 'og:type': 'video', | 51 | 'og:type': 'video', |
52 | 'og:title': video.name, | 52 | 'og:title': video.name, |
53 | 'og:image': previewUrl, | 53 | 'og:image': previewUrl, |
@@ -65,14 +65,26 @@ function addOpenGraphTags (htmlStringPage: string, video: VideoInstance) { | |||
65 | 'twitter:image': previewUrl | 65 | 'twitter:image': previewUrl |
66 | } | 66 | } |
67 | 67 | ||
68 | const oembedLinkTags = [ | ||
69 | { | ||
70 | type: 'application/json+oembed', | ||
71 | href: CONFIG.WEBSERVER.URL + '/services/oembed?url=' + encodeURIComponent(videoUrl), | ||
72 | title: video.name | ||
73 | } | ||
74 | ] | ||
75 | |||
68 | let tagsString = '' | 76 | let tagsString = '' |
69 | Object.keys(metaTags).forEach(tagName => { | 77 | Object.keys(openGraphMetaTags).forEach(tagName => { |
70 | const tagValue = metaTags[tagName] | 78 | const tagValue = openGraphMetaTags[tagName] |
71 | 79 | ||
72 | tagsString += '<meta property="' + tagName + '" content="' + tagValue + '" />' | 80 | tagsString += `<meta property="${tagName}" content="${tagValue}" />` |
73 | }) | 81 | }) |
74 | 82 | ||
75 | return htmlStringPage.replace(OPENGRAPH_COMMENT, tagsString) | 83 | for (const oembedLinkTag of oembedLinkTags) { |
84 | tagsString += `<link rel="alternate" type="${oembedLinkTag.type}" href="${oembedLinkTag.href}" title="${oembedLinkTag.title}" />` | ||
85 | } | ||
86 | |||
87 | return htmlStringPage.replace(OPENGRAPH_AND_OEMBED_COMMENT, tagsString) | ||
76 | } | 88 | } |
77 | 89 | ||
78 | function generateWatchHtmlPage (req: express.Request, res: express.Response, next: express.NextFunction) { | 90 | function generateWatchHtmlPage (req: express.Request, res: express.Response, next: express.NextFunction) { |
@@ -101,7 +113,7 @@ function generateWatchHtmlPage (req: express.Request, res: express.Response, nex | |||
101 | // Let Angular application handle errors | 113 | // Let Angular application handle errors |
102 | if (!video) return res.sendFile(indexPath) | 114 | if (!video) return res.sendFile(indexPath) |
103 | 115 | ||
104 | const htmlStringPageWithTags = addOpenGraphTags(html, video) | 116 | const htmlStringPageWithTags = addOpenGraphAndOEmbedTags(html, video) |
105 | res.set('Content-Type', 'text/html; charset=UTF-8').send(htmlStringPageWithTags) | 117 | res.set('Content-Type', 'text/html; charset=UTF-8').send(htmlStringPageWithTags) |
106 | }) | 118 | }) |
107 | .catch(err => next(err)) | 119 | .catch(err => next(err)) |
diff --git a/server/controllers/index.ts b/server/controllers/index.ts index 0223a98f1..51cb480a3 100644 --- a/server/controllers/index.ts +++ b/server/controllers/index.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | export * from './static' | 1 | export * from './static' |
2 | export * from './client' | 2 | export * from './client' |
3 | export * from './services' | ||
3 | export * from './api' | 4 | export * from './api' |
diff --git a/server/controllers/services.ts b/server/controllers/services.ts new file mode 100644 index 000000000..3ce6bd526 --- /dev/null +++ b/server/controllers/services.ts | |||
@@ -0,0 +1,62 @@ | |||
1 | import * as express from 'express' | ||
2 | |||
3 | import { CONFIG, THUMBNAILS_SIZE } from '../initializers' | ||
4 | import { oembedValidator } from '../middlewares' | ||
5 | import { VideoInstance } from '../models' | ||
6 | |||
7 | const servicesRouter = express.Router() | ||
8 | |||
9 | servicesRouter.use('/oembed', oembedValidator, generateOEmbed) | ||
10 | |||
11 | // --------------------------------------------------------------------------- | ||
12 | |||
13 | export { | ||
14 | servicesRouter | ||
15 | } | ||
16 | |||
17 | // --------------------------------------------------------------------------- | ||
18 | |||
19 | function generateOEmbed (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
20 | const video = res.locals.video as VideoInstance | ||
21 | const webserverUrl = CONFIG.WEBSERVER.URL | ||
22 | const maxHeight = parseInt(req.query.maxheight, 10) | ||
23 | const maxWidth = parseInt(req.query.maxwidth, 10) | ||
24 | |||
25 | const embedUrl = webserverUrl + video.getEmbedPath() | ||
26 | let thumbnailUrl = webserverUrl + video.getThumbnailPath() | ||
27 | let embedWidth = 560 | ||
28 | let embedHeight = 315 | ||
29 | |||
30 | if (maxHeight < embedHeight) embedHeight = maxHeight | ||
31 | if (maxWidth < embedWidth) embedWidth = maxWidth | ||
32 | |||
33 | // Our thumbnail is too big for the consumer | ||
34 | if ( | ||
35 | (maxHeight !== undefined && maxHeight < THUMBNAILS_SIZE.height) || | ||
36 | (maxWidth !== undefined && maxWidth < THUMBNAILS_SIZE.width) | ||
37 | ) { | ||
38 | thumbnailUrl = undefined | ||
39 | } | ||
40 | |||
41 | const html = `<iframe width="${embedWidth}" height="${embedHeight}" src="${embedUrl}" frameborder="0" allowfullscreen></iframe>` | ||
42 | |||
43 | const json: any = { | ||
44 | type: 'video', | ||
45 | version: '1.0', | ||
46 | html, | ||
47 | width: embedWidth, | ||
48 | height: embedHeight, | ||
49 | title: video.name, | ||
50 | author_name: video.Author.name, | ||
51 | provider_name: 'PeerTube', | ||
52 | provider_url: webserverUrl | ||
53 | } | ||
54 | |||
55 | if (thumbnailUrl !== undefined) { | ||
56 | json.thumbnail_url = thumbnailUrl | ||
57 | json.thumbnail_width = THUMBNAILS_SIZE.width | ||
58 | json.thumbnail_height = THUMBNAILS_SIZE.height | ||
59 | } | ||
60 | |||
61 | return res.json(json) | ||
62 | } | ||