package main import ( "encoding/json" "fmt" "io/ioutil" "log" "net/http" "os" "regexp" "strings" "github.com/mattn/go-jsonpointer" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World") } func main() { host := "0.0.0.0" port := os.Getenv("PORT") if port == "" { // local port = "8080" host = "127.0.0.1" } http.HandleFunc("/oembed", oEmbedHandler) http.HandleFunc("/", handler) log.Printf("Listening on port %s:%s", host, port) log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%s", host, port), nil)) } func oEmbedHandler(w http.ResponseWriter, r *http.Request) { log.Printf("Handle HTTP request %s\n", r.URL) target := r.URL.Query()["url"][0] data, err := newOEmbedData(target) if err != nil { body, _ := json.Marshal(map[string]string{"error": err.Error()}) w.WriteHeader(http.StatusNotFound) w.Header().Set("Content-Type", "application/json") w.Write(body) } else { body, _ := json.Marshal(data) w.Header().Set("Content-Type", "application/json") w.Write(body) } } type oEmbedData struct { Url string `json:"url"` Title string `json:"title"` Tags []string `json:"tags"` Description string `json:"description"` Html string `json:"html"` Published string `json:"published"` BlogUrl string `json:"blog_url"` BlogTitle string `json:"blog_title"` AuthorUrl string `json:"author_url"` AuthorName string `json:"author_name"` ProviderName string `json:"provider_name"` ProviderUrl string `json:"provider_url"` ImageUrl string `json:"image_url"` Width string `json:"width"` Height string `json:"height"` Version string `json:"version"` Type string `json:"type"` } func newOEmbedData(url string) (*oEmbedData, error) { post, err := findPost(url) if err != nil { log.Println(err.Error()) return nil, err } oEmbedData := oEmbedData{ Url: url, Title: post.Title, Description: post.Description, Tags: post.Tags, Published: post.Date, Html: buildHtml(url, post), BlogUrl: "https://blog.petitviolet.net", BlogTitle: "blog.petitviolet.net", AuthorUrl: "https://petitviolet.net", AuthorName: "petitviolet", ProviderName: "blog.petitviolet.net", ProviderUrl: "https://blog.petitviolet.net", ImageUrl: "https://s.gravatar.com/avatar/93bc8fb48f57c11e417dad9d26a2fb8a?s=480", Width: "100%", Height: "200px", Version: "1.0", Type: "rich", } return &oEmbedData, nil } type Post struct { Title string Tags []string Description string Excerpt string Date string } 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 := buildPageDatePath(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 } return buildPost(raw), nil } func buildHtml(url string, post *Post) string { id := strings.Replace(post.Title, " ", "-", -1) return fmt.Sprintf(`
%s %s %s
`, id, id, id, id, id, id, // CSS id, id, id, id, id, id, id, // CSS url, post.Title, id, post.Description, id, post.Excerpt, id, id, id, id, id, // CSS post.Date, strings.Join(post.Tags, ", ")) } 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) } // fmt.Printf("pageDataPath: %s\n", pageDataPath) // fmt.Printf("raw: %s\n", raw) // fmt.Printf("title: %v\n", title) // fmt.Printf("description: %v\n", description) // fmt.Printf("date: %v\n", date) // fmt.Printf("tags: %v\n", tagStrs) post := Post{ Title: title.(string), Description: description.(string), Excerpt: excerpt.(string), Date: date.(string), Tags: tagStrs, } return &post } func buildPageDatePath(date string, name string) string { return fmt.Sprintf("public/page-data/post/%s/%s/page-data.json", date, name) }