mime.go 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package mime
  2. import (
  3. "errors"
  4. "regexp"
  5. )
  6. type MediaType struct {
  7. Essence string
  8. Supertype string
  9. Subtype string
  10. }
  11. /*
  12. See: https://httpwg.org/specs/rfc9110.html#media.type
  13. */
  14. var re = regexp.MustCompile(`(?s)^(([!#$%&'*+\-.^_\x60|~a-zA-Z0-9]+)/([!#$%&'*+\-.^_\x60|~a-zA-Z0-9]+)).*$`)
  15. func Default() *MediaType {
  16. return &MediaType{
  17. Essence: "text/html",
  18. Supertype: "text",
  19. Subtype: "html",
  20. }
  21. }
  22. func Unknown() *MediaType {
  23. return &MediaType{
  24. Essence: "*/*",
  25. Supertype: "*",
  26. Subtype: "*",
  27. }
  28. }
  29. func UnknownSubtype(supertype string) *MediaType {
  30. return &MediaType{
  31. Essence: supertype + "/*",
  32. Supertype: supertype,
  33. Subtype: "*",
  34. }
  35. }
  36. func Parse(input string) (*MediaType, error) {
  37. matches := re.FindStringSubmatch(input)
  38. if len(matches) != 4 {
  39. return nil, errors.New(`"` + input + `" is not a valid media type`)
  40. }
  41. return &MediaType{
  42. Essence: matches[1],
  43. Supertype: matches[2],
  44. Subtype: matches[3],
  45. }, nil
  46. }
  47. func (m *MediaType) Update(input string) error {
  48. parsed, err := Parse(input)
  49. if err != nil {
  50. return err
  51. }
  52. *m = *parsed
  53. return nil
  54. }
  55. func (m *MediaType) Matches(mediaTypes []string) bool {
  56. for _, mediaType := range mediaTypes {
  57. if m.Essence == mediaType {
  58. return true
  59. }
  60. }
  61. return false
  62. }