a simple url shortener in Go (check it out at qurl.org)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

79 lines
1.7 KiB

4 years ago
4 years ago
4 years ago
  1. package pages
  2. import (
  3. "bytes"
  4. "compress/gzip"
  5. "crypto/md5"
  6. "fmt"
  7. "net/http"
  8. "strings"
  9. )
  10. type StaticContent struct {
  11. Type string
  12. Content []byte
  13. ETag string
  14. GZIPContent []byte
  15. GZIPETag string
  16. }
  17. func (sc *StaticContent) Init() {
  18. // Populate ETag
  19. sc.ETag = fmt.Sprintf("%x", md5.Sum(sc.Content))
  20. // Set a default Content-Type, if needed
  21. if sc.Type == "" {
  22. sc.Type = "application/octet-stream"
  23. }
  24. var buf bytes.Buffer
  25. gz, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
  26. defer gz.Close()
  27. if _, err := gz.Write(sc.Content); err != nil {
  28. return
  29. }
  30. if err := gz.Flush(); err != nil {
  31. return
  32. }
  33. // Using gzip encoding adds a minimum of 24 characters to the HTTP
  34. // header, so only accept gzip encoding if we save that much or more
  35. if (buf.Len() + 24) < len(sc.Content) {
  36. sc.GZIPContent = buf.Bytes()
  37. sc.GZIPETag = fmt.Sprintf("%x", md5.Sum(sc.GZIPContent))
  38. }
  39. }
  40. func (sc *StaticContent) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  41. gzok := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip")
  42. gzlen := len(sc.GZIPContent)
  43. // Use the correct etag
  44. var localETag string
  45. if gzok && gzlen > 0 {
  46. localETag = sc.GZIPETag
  47. } else {
  48. localETag = sc.ETag
  49. }
  50. // Check the etag, maybe we don't need to send content
  51. remoteETag := r.Header.Get("If-None-Match")
  52. if localETag == remoteETag {
  53. w.WriteHeader(http.StatusNotModified)
  54. return
  55. }
  56. w.Header().Set("ETag", localETag)
  57. w.Header().Set("Content-Type", sc.Type)
  58. // Finally, write our content
  59. if gzok && gzlen > 0 {
  60. w.Header().Set("Content-Encoding", "gzip")
  61. w.Header().Set("Content-Length", fmt.Sprintf("%d", gzlen))
  62. w.Write(sc.GZIPContent)
  63. } else {
  64. w.Header().Set("Content-Length", fmt.Sprintf("%d", len(sc.Content)))
  65. w.Write(sc.Content)
  66. }
  67. }