Skip to content

Instantly share code, notes, and snippets.

@peeyushsrj
Last active February 22, 2016 16:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peeyushsrj/2eb4a2783dad679fc57b to your computer and use it in GitHub Desktop.
Save peeyushsrj/2eb4a2783dad679fc57b to your computer and use it in GitHub Desktop.
Implementation of prerender.io service in golang
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"time"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"github.com/gorilla/mux"
)
//Set host in putintoCache
type cachePage struct {
Url string
Content string
LastModified time.Time
}
var cachePages *mgo.Collection
func prerenderHandler(w http.ResponseWriter, r *http.Request) {
requestPath := strings.TrimSuffix(r.URL.String(), "?escaped_fragment_=")
content := serveCache(requestPath)
fmt.Fprint(w, content)
}
func putintoCache(url string) string {
//Request to prerender server
host := "localhost"
requestUrl := "http://" + host + ":3000/http://" + host + url
//Inserting in db
cpage := cachePage{}
cpage.Url = url
cpage.Content, cpage.LastModified = downloadPage(requestUrl)
err := cachePages.Insert(&cpage)
if err != nil {
log.Fatal(err)
}
return cpage.Content
}
func downloadPage(requestUrl string) (string, time.Time) {
resp, err := http.Get(requestUrl)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
//lastmodDate := resp.Header.Get("Last-Modified")
lastModDate := time.Now()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
return string(b), lastModDate
}
func serveCache(url string) string {
page := cachePage{}
err := cachePages.Find(bson.M{"url": url}).One(&page)
cacheDurationSeconds := time.Now().Unix() - page.LastModified.Unix()
cacheDurationDays := cacheDurationSeconds / 60 * 60 * 24
if err != nil {
return putintoCache(url) //if not found in db
} else if cacheDurationDays > 1 {
return putintoCache(url)
} else {
return page.Content
}
}
func routePathHandler(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "public/index.html")
}
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "hello")
}
func main() {
session, err := mgo.Dial("localhost")
if err != nil {
log.Fatal(err)
}
cachePages = session.DB("cache").C("pages")
r := mux.NewRouter()
r.Queries("escaped_fragment_", "").HandlerFunc(prerenderHandler)
//r.PathPrefix("/public").Handler(http.StripPrefix("/public", http.FileServer(http.Dir("public/"))))
r.Path("/hello").HandlerFunc(hello)
r.Path("/index").HandlerFunc(routePathHandler)
r.Path("/new").HandlerFunc(routePathHandler)
r.Path("/index/new").HandlerFunc(routePathHandler)
r.PathPrefix("/").Handler(http.FileServer(http.Dir("public/")))
err = http.ListenAndServe(":80", r)
if err != nil {
log.Fatal(err)
}
//When not using cache we can just redirect crawler
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment