a simple url shortening service, in the same vein as bit.ly and tinyurl.com, written in Go and using BoltDB as a backend
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

80 行
1.7KB

  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. }