Build oEmbed API for Gatsby blog
2020-05-22
GatsbyGoPreviously, I wrote a post about that this blog has a capability to expand oEmbed articles using raae/gatsby-remark-oembed.
As it is embed here, this blog is also able to expand self posts as well based on oEmbed specification.
Though the style is not sophisticated for the time being.
This post describes how to build an API to embed blog posts in oEmbed format that is powered by Gatsby.
Also see: https://oembed.com/
tl;dr
Source code is here: https://gist.github.com/petitviolet/a2a601f06ae20f98d1306e8690d358bd
How it works
To offer an API to return response following the oEmbed specification, at first, it needs to collect metadata of requested page.
Which page is requested is given by the url
URL parameter such as /oembed?url=
.
And metadata of each post is available at ./public/page-data/path/to/post/page-data.json
that Gatsby generates in its build process.
Go code to retrieve the page-data.json
for the specified blog post is below.
var urlPattern = regexp.MustCompile(`^https://blog.petitviolet.net/post/(\d{4}-\d{2}-\d{2})/(.+)$`)
func findPost(url string) (*Post, error) {
res := urlPattern.FindStringSubmatch(url)
if len(res) != 3 {
return nil, fmt.Errorf("Invalid url. url: %s", url)
}
pageDataPath := fmt.Sprintf("public/page-data/post/%s/%s/page-data.json", res[1], res[2])
raw, err := ioutil.ReadFile(pageDataPath)
if err != nil {
err = fmt.Errorf("Failed to read file. file = %s, err = %s", pageDataPath, err.Error())
return nil, err
}
// ...
}
Next, build a Post
struct as a source of HTTP response from found page-data.json.
It uses mattn/go-jsonpointer to get data from json object.
func buildPost(raw []byte) *Post {
var pageData map[string]interface{}
json.Unmarshal(raw, &pageData)
title, _ := jsonpointer.Get(pageData, "/result/data/post/frontmatter/title")
description, _ := jsonpointer.Get(pageData, "/result/data/post/frontmatter/description")
excerpt, _ := jsonpointer.Get(pageData, "/result/data/post/excerpt")
date, _ := jsonpointer.Get(pageData, "/result/data/post/frontmatter/date")
_tags, _ := jsonpointer.Get(pageData, "/result/data/post/frontmatter/tags")
tagIs := _tags.([]interface{})
tagStrs := make([]string, len(tagIs))
for i, v := range tagIs {
tagStrs[i] = v.(string)
}
post := Post{
Title: title.(string),
Description: description.(string),
Excerpt: excerpt.(string),
Date: date.(string),
Tags: tagStrs,
}
return &post
}
The last step is building a HTML. If you're interested in, please refer the source code at gist.