path.go 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. package amp
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "fmt"
  6. "strings"
  7. )
  8. // EncodePath encodes data in a way that is suitable for the suffix of an AMP
  9. // cache URL.
  10. func EncodePath(data []byte) string {
  11. var cacheBreaker [9]byte
  12. _, err := rand.Read(cacheBreaker[:])
  13. if err != nil {
  14. panic(err)
  15. }
  16. b64 := base64.RawURLEncoding.EncodeToString
  17. return "0" + b64(cacheBreaker[:]) + "/" + b64(data)
  18. }
  19. // DecodePath decodes data from a path suffix as encoded by EncodePath. The path
  20. // must have already been trimmed of any directory prefix (as might be present
  21. // in, e.g., an HTTP request). That is, the first character of path should be
  22. // the "0" message format indicator.
  23. func DecodePath(path string) ([]byte, error) {
  24. if len(path) < 1 {
  25. return nil, fmt.Errorf("missing format indicator")
  26. }
  27. version := path[0]
  28. rest := path[1:]
  29. switch version {
  30. case '0':
  31. // Ignore everything else up to and including the final slash
  32. // (there must be at least one slash).
  33. i := strings.LastIndexByte(rest, '/')
  34. if i == -1 {
  35. return nil, fmt.Errorf("missing data")
  36. }
  37. return base64.RawURLEncoding.DecodeString(rest[i+1:])
  38. default:
  39. return nil, fmt.Errorf("unknown format indicator %q", version)
  40. }
  41. }