Skip to content
Snippets Groups Projects
Commit 3d53bc53 authored by Dean's avatar Dean
Browse files

Merge branch 'feat/discord-video-embed' into 'master'

Add HTML response for Discord video embeds

See merge request whats-this/cdn-origin!11
parents dd504b14 6cc18575
Branches master
No related tags found
No related merge requests found
......@@ -60,8 +60,9 @@ var redirectHTMLTemplate *template.Template
// redirectPreviewHTML is the html/template template for generating redirect preview HTML.
const redirectPreviewHTML = `<html><head><meta charset="UTF-8" /><title>Redirect Preview</title></head><body><p>This link goes to <code>{{.}}</code>. If you would like to visit this link, click <a href="{{.}}">here</a> to go to the destination.</p></body></html>`
// discordHTML is the html/template template for generating Discord-fixing HTML.
const discordHTML = `<html>
// discordImageHTML is the html/template template for generating Discord-fixing
// HTML for images.
const discordImageHTML = `<html>
<head>
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:image" content="{{.}}" />
......@@ -71,10 +72,22 @@ const discordHTML = `<html>
</head>
</html>`
var discordHTMLTemplate *template.Template
// discordVideoHTML is the html/template template for generating Discord-fixing
// HTML for videos.
const discordVideoHTML = `<html>
<head>
<meta property="og:type" content="video.other" />
<meta property="og:video:url" content="{{.}}" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
</head>
</html>`
var redirectPreviewHTMLTemplate *template.Template
var discordMediaTypeToTemplate map[string]*template.Template
// printConfiguration iterates through a configuration map[string]interface{}
// and prints out all of the values in alphabetical order. Configuration keys
// are printed with dot notation.
......@@ -182,9 +195,30 @@ func init() {
if err != nil {
log.Fatal().Err(err).Msg("failed to parse redirectPreviewHTML template")
}
discordHTMLTemplate, err = template.New("discordHTML").Parse(discordHTML)
// Parse Discord-fixing templates
discordImageHTMLTemplate, err := template.New("discordImageHTML").Parse(discordImageHTML)
if err != nil {
log.Fatal().Err(err).Msg("failed to parse discordHTML template")
log.Fatal().Err(err).Msg("failed to parse discordImageHTML template")
}
discordVideoHTMLTemplate, err := template.New("discordVideoHTML").Parse(discordVideoHTML)
if err != nil {
log.Fatal().Err(err).Msg("failed to parse discordVideoHTML template")
}
discordMediaTypeToTemplate = map[string]*template.Template{
"image/jpeg": discordImageHTMLTemplate,
"image/png": discordImageHTMLTemplate,
"image/gif": discordImageHTMLTemplate,
"image/webp": discordImageHTMLTemplate,
// Official media type, registered in 2022
"image/apng": discordImageHTMLTemplate,
// Official-unofficial media type, still in use, registered in 2015
"image/vnd.mozilla.apng": discordImageHTMLTemplate,
// Currently unsupported by Discord, but no harm keeping it here
"image/avif": discordImageHTMLTemplate,
"video/mp4": discordVideoHTMLTemplate,
"video/webm": discordVideoHTMLTemplate,
"video/ogg": discordVideoHTMLTemplate,
}
}
......@@ -434,8 +468,10 @@ func requestHandler(ctx *fasthttp.RequestCtx) {
return
}
// Discord workaround. They're hiding direct image embeds, so we
// serve HTML pages with metadata showing the image.
// Discord workaround. Directly returning images results in the
// URL being hidden, while directly returning multimedia
// containers reduces the chances of the media embedding at all
// (lower size constraints, fewer whitelisted codecs).
if object.ContentType != nil && discordBotRegex.Match(ctx.Request.Header.UserAgent()) && !ctx.QueryArgs().Has(rawParam) {
typ, _, err := mime.ParseMediaType(*object.ContentType)
if err != nil {
......@@ -444,7 +480,8 @@ func requestHandler(ctx *fasthttp.RequestCtx) {
return
}
if typ == "image/jpeg" || typ == "image/jpg" || typ == "image/png" || typ == "image/gif" {
discordTemplate := discordMediaTypeToTemplate[typ]
if discordTemplate != nil {
var (
host = string(ctx.Request.Header.Peek("Host"))
// Assume anything Discord hits is HTTPS
......@@ -463,7 +500,7 @@ func requestHandler(ctx *fasthttp.RequestCtx) {
ctx.Response.Header.Add("Cache-Control", "no-cache, no-store, must-revalidate")
ctx.Response.Header.Add("Pragma", "no-cache")
ctx.Response.Header.Add("Expires", "0")
err = discordHTMLTemplate.Execute(ctx, url)
err = discordTemplate.Execute(ctx, url)
if err != nil {
log.Warn().Err(err).Msg("failed to execute discord html template on discordbot connection")
internalServerError(ctx)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment