Publish HTML quickly. https://html.house
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

128 行
3.3 KiB

  1. package htmlhouse
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "io/ioutil"
  6. "net/http"
  7. "regexp"
  8. "strings"
  9. "github.com/gorilla/mux"
  10. "github.com/writeas/impart"
  11. "github.com/writeas/nerds/store"
  12. )
  13. func createHouse(app *app, w http.ResponseWriter, r *http.Request) error {
  14. html := r.FormValue("html")
  15. if strings.TrimSpace(html) == "" {
  16. return impart.HTTPError{http.StatusBadRequest, "Supply something to publish."}
  17. }
  18. houseID := store.GenerateFriendlyRandomString(8)
  19. _, err := app.db.Exec("INSERT INTO houses (id, html) VALUES (?, ?)", houseID, html)
  20. if err != nil {
  21. return err
  22. }
  23. if err = app.session.writeToken(w, houseID); err != nil {
  24. return err
  25. }
  26. resUser := newSessionInfo(houseID)
  27. return impart.WriteSuccess(w, resUser, http.StatusCreated)
  28. }
  29. func renovateHouse(app *app, w http.ResponseWriter, r *http.Request) error {
  30. vars := mux.Vars(r)
  31. houseID := vars["house"]
  32. html := r.FormValue("html")
  33. if strings.TrimSpace(html) == "" {
  34. return impart.HTTPError{http.StatusBadRequest, "Supply something to publish."}
  35. }
  36. authHouseID, err := app.session.readToken(r)
  37. if err != nil {
  38. return err
  39. }
  40. if authHouseID != houseID {
  41. return impart.HTTPError{http.StatusUnauthorized, "Bad token for this ⌂ house ⌂."}
  42. }
  43. _, err = app.db.Exec("UPDATE houses SET html = ? WHERE id = ?", html, houseID)
  44. if err != nil {
  45. return err
  46. }
  47. if err = app.session.writeToken(w, houseID); err != nil {
  48. return err
  49. }
  50. resUser := newSessionInfo(houseID)
  51. return impart.WriteSuccess(w, resUser, http.StatusOK)
  52. }
  53. func getHouseHTML(app *app, houseID string) (string, error) {
  54. var html string
  55. err := app.db.QueryRow("SELECT html FROM houses WHERE id = ?", houseID).Scan(&html)
  56. switch {
  57. case err == sql.ErrNoRows:
  58. return "", impart.HTTPError{http.StatusNotFound, "Return to sender. Address unknown."}
  59. case err != nil:
  60. fmt.Printf("Couldn't fetch: %v\n", err)
  61. return "", err
  62. }
  63. return html, nil
  64. }
  65. var (
  66. htmlReg = regexp.MustCompile("<html( ?.*)>")
  67. )
  68. func getHouse(app *app, w http.ResponseWriter, r *http.Request) error {
  69. vars := mux.Vars(r)
  70. houseID := vars["house"]
  71. // Fetch HTML
  72. html, err := getHouseHTML(app, houseID)
  73. if err != nil {
  74. if err, ok := err.(impart.HTTPError); ok {
  75. if err.Status == http.StatusNotFound {
  76. page, err := ioutil.ReadFile(app.cfg.StaticDir + "/404.html")
  77. if err != nil {
  78. page = []byte("<!DOCTYPE html><html><body>HTMLlot.</body></html>")
  79. }
  80. fmt.Fprintf(w, "%s", page)
  81. return nil
  82. }
  83. }
  84. return err
  85. }
  86. // Add nofollow meta tag
  87. if strings.Index(html, "<head>") == -1 {
  88. html = htmlReg.ReplaceAllString(html, "<html$1><head></head>")
  89. }
  90. html = strings.Replace(html, "<head>", "<head><meta name=\"robots\" content=\"nofollow\" />", 1)
  91. // Add links back to HTMLhouse
  92. watermark := "<div style='position: absolute;top:16px;right:16px;'><a href='/'>&lt;&#8962;/&gt;</a> &middot; <a href='/edit/" + houseID + ".html'>edit</a></div>"
  93. if strings.Index(html, "</body>") == -1 {
  94. html = strings.Replace(html, "</html>", "</body></html>", 1)
  95. }
  96. html = strings.Replace(html, "</body>", fmt.Sprintf("%s</body>", watermark), 1)
  97. // Print HTML, with sanity check in case someone did something crazy
  98. if strings.Index(html, "<a href='/'>&lt;&#8962;/&gt;</a>") == -1 {
  99. fmt.Fprintf(w, "%s%s", html, watermark)
  100. } else {
  101. fmt.Fprintf(w, "%s", html)
  102. }
  103. return nil
  104. }