Advertisement
Guest User

Untitled

a guest
Jun 19th, 2017
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.70 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "html"
  6. "html/template"
  7. "log"
  8. "math/rand"
  9. "time"
  10. "io/ioutil"
  11. "encoding/json"
  12. "strconv"
  13.  
  14. "github.com/buaazp/fasthttprouter"
  15. "github.com/jackc/pgx"
  16. "github.com/valyala/fasthttp"
  17. )
  18.  
  19. type Configuration struct {
  20. DBHost string `json:"db_host"`
  21. DBUser string `json:"db_user"`
  22. DBPass string `json:"db_pass"`
  23. DBName string `json:"db_name"`
  24. DBPort string `json:"db_port"`
  25. Port string `json:"port"`
  26. MaxPasteSizeMB float32 `json:"max_paste_size_megabytes"`
  27. }
  28.  
  29. var (
  30. grabPasteById *pgx.PreparedStatement
  31. insertPaste *pgx.PreparedStatement
  32. tmpl = template.Must(template.ParseFiles("templates/index.html"))
  33. config = grabConfig("config.json")
  34. db *pgx.ConnPool
  35. idAlphabet = []rune("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
  36. idNumChars = 8
  37. )
  38.  
  39. func main() {
  40. rand.Seed(time.Now().UnixNano())
  41.  
  42. port, err := strconv.ParseUint(config.DBPort, 10, 16)
  43. if db, err = initDatabase(config.DBHost, config.DBUser, config.DBPass, config.DBName, uint16(port), 256); err != nil {
  44. log.Fatalf("Error opening database: %s", err)
  45. }
  46.  
  47. router := fasthttprouter.New()
  48. router.GET("/", Index)
  49. router.GET("/:paste_id", GrabPaste)
  50. router.POST("/save", Save)
  51.  
  52. log.Fatal(fasthttp.ListenAndServe(":" + config.Port, router.Handler))
  53. }
  54.  
  55. func grabConfig(filename string) *Configuration {
  56. c := Configuration{}
  57.  
  58. b, err := ioutil.ReadFile(filename)
  59. if err != nil {
  60. log.Fatalf("Error reading in config file: %s", err)
  61. }
  62.  
  63. if err := json.Unmarshal(b, &c); err != nil {
  64. log.Fatalf("Error decoding config file: %s", err)
  65. }
  66.  
  67. return &c
  68. }
  69.  
  70. func Index(ctx *fasthttp.RequestCtx, _ fasthttprouter.Params) {
  71. ctx.SetContentType("text/html;charset:UTF-8")
  72. data := make([]string, 0, 10)
  73. tmpl.Execute(ctx, data)
  74. }
  75.  
  76. func Save(ctx *fasthttp.RequestCtx, ps fasthttprouter.Params) {
  77. randId := generateRandomId(idNumChars, idAlphabet)
  78. paste := string(ctx.FormValue("pastearea"))
  79. pasteSize := len(paste);
  80. pasteSizeMB := float32(pasteSize) / 1000000
  81.  
  82. if pasteSizeMB > config.MaxPasteSizeMB {
  83. ctx.SetStatusCode(fasthttp.StatusRequestEntityTooLarge)
  84. fmt.Fprintf(ctx, "You tried to paste %.2f MB of text, which exceeds our limit of %.2f MB per paste.", pasteSizeMB, config.MaxPasteSizeMB)
  85. } else {
  86. txn, err := db.Begin()
  87. if err != nil {
  88. log.Fatalf("Error starting db: %s", err)
  89. }
  90.  
  91. if _, err := txn.Exec("insertPaste", randId, paste); err != nil {
  92. log.Fatalf("Error inserting new paste: %s", err)
  93. }
  94.  
  95. if err = txn.Commit(); err != nil {
  96. log.Fatalf("Error when committing new paste: %s", err)
  97. }
  98.  
  99. ctx.Redirect("/" + randId, 302)
  100. }
  101. }
  102.  
  103. func GrabPaste(ctx *fasthttp.RequestCtx, ps fasthttprouter.Params) {
  104. var pasteText string
  105. pasteId := ps.ByName("paste_id")
  106.  
  107. if err := db.QueryRow("grabPasteById", pasteId).Scan(&pasteText); err != nil {
  108. if err.Error() == "no rows in result set" {
  109. ctx.SetStatusCode(fasthttp.StatusNotFound)
  110. fmt.Fprintf(ctx, "Can't find that paste!")
  111. } else {
  112. log.Fatalf("Error grabbing paste: %s", err)
  113. }
  114. }
  115.  
  116. unescapedPaste := html.UnescapeString(pasteText)
  117. fmt.Fprint(ctx, unescapedPaste)
  118. }
  119.  
  120. /* generateRandomId
  121. * ------------
  122. * Returns an random alphanumeric string of length numChars, like xJ2h9a0 */
  123. func generateRandomId(numChars int, alphabet []rune) string {
  124. randStr := make([]rune, numChars)
  125. for i := range randStr {
  126. randStr[i] = alphabet[rand.Intn(len(alphabet))]
  127. }
  128.  
  129. return string(randStr)
  130. }
  131.  
  132. /* initDatabase
  133. * ------------
  134. * Initializes database connection.
  135. * Taken from https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/frameworks/Go/fasthttp-postgresql/src/hello/hello.go */
  136. func initDatabase(dbHost string, dbUser string, dbPass string, dbName string, dbPort uint16, maxConnectionsInPool int) (*pgx.ConnPool, error) {
  137. var successOrFailure string = "OK"
  138.  
  139. var config pgx.ConnPoolConfig
  140.  
  141. config.Host = dbHost
  142. config.User = dbUser
  143. config.Password = dbPass
  144. config.Database = dbName
  145. config.Port = dbPort
  146.  
  147. config.MaxConnections = maxConnectionsInPool
  148.  
  149. config.AfterConnect = func(conn *pgx.Conn) error {
  150. var err error
  151.  
  152. grabPasteById, err = conn.Prepare("grabPasteById", "SELECT paste FROM pastes WHERE id = $1")
  153. if err != nil {
  154. log.Fatalf("Error when preparing statement grabPaste: %s", err)
  155. }
  156.  
  157. insertPaste, err = conn.Prepare("insertPaste", "INSERT INTO pastes(id, paste) VALUES($1, $2)")
  158. if err != nil {
  159. log.Fatalf("Error when preparing statement grabPasteById: %s", err)
  160. }
  161.  
  162. // Disable synchronous commit for the current db connection
  163. // as a performance optimization.
  164. // See http://www.postgresql.org/docs/current/static/runtime-config-wal.html
  165. // for details.
  166. if _, err := conn.Exec("SET synchronous_commit TO OFF"); err != nil {
  167. log.Fatalf("Error when disabling synchronous commit")
  168. }
  169.  
  170. return nil
  171. }
  172.  
  173. connPool, err := pgx.NewConnPool(config)
  174. if err != nil {
  175. successOrFailure = "FAILED"
  176. fmt.Println("Connecting to database", dbName, "as user", dbUser, ":", successOrFailure, err)
  177. } else {
  178. fmt.Println("Connecting to database", dbName, "as user", dbUser, ":", successOrFailure)
  179. }
  180.  
  181. return connPool, err
  182. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement