1
0

stem_ext.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // stemext package provides methods which help to generate correct
  2. // content-disposition header.
  3. package contentdisposition
  4. import (
  5. "mime"
  6. "net/url"
  7. "path/filepath"
  8. )
  9. const (
  10. // fallbackStem is used when the stem cannot be determined from the URL.
  11. fallbackStem = "image"
  12. )
  13. // StemExt helps to detect correct stem and ext for content-disposition header.
  14. type StemExt struct {
  15. stem string
  16. ext string
  17. }
  18. // FromURL creates a new StemExt instance from the provided URL.
  19. // Returns a value type to avoid heap allocation.
  20. func FromURL(url *url.URL) StemExt {
  21. _, filename := filepath.Split(url.Path)
  22. ext := filepath.Ext(filename)
  23. // Avoid strings.TrimSuffix allocation by using slice operation
  24. var stem string
  25. if ext != "" {
  26. stem = filename[:len(filename)-len(ext)]
  27. } else {
  28. stem = filename
  29. }
  30. return StemExt{
  31. stem: stem,
  32. ext: ext,
  33. }
  34. }
  35. // SetExtFromContentTypeIfEmpty sets the ext field based on the provided content type.
  36. // Uses pointer receiver for zero-copy method chaining.
  37. func (cd *StemExt) SetExtFromContentTypeIfEmpty(contentType string) *StemExt {
  38. if len(contentType) == 0 || len(cd.ext) > 0 {
  39. return cd
  40. }
  41. if exts, err := mime.ExtensionsByType(contentType); err == nil && len(exts) != 0 {
  42. cd.ext = exts[0]
  43. }
  44. return cd
  45. }
  46. // OverrideExt sets the ext field if the provided ext is not empty.
  47. // Uses pointer receiver for zero-copy method chaining.
  48. func (cd *StemExt) OverrideExt(ext string) *StemExt {
  49. if len(ext) > 0 {
  50. cd.ext = ext
  51. }
  52. return cd
  53. }
  54. // OverrideStem sets the stem field if the provided stem is not empty.
  55. // Uses pointer receiver for zero-copy method chaining.
  56. func (cd *StemExt) OverrideStem(stem string) *StemExt {
  57. if len(stem) > 0 {
  58. cd.stem = stem
  59. }
  60. return cd
  61. }
  62. // StemExtWithFallback returns stem and ext, but if stem is empty, it uses a fallback value.
  63. func (cd StemExt) StemExtWithFallback() (string, string) {
  64. stem := cd.stem
  65. if len(stem) == 0 {
  66. stem = fallbackStem
  67. }
  68. return stem, cd.ext
  69. }
  70. // StemExt returns the tuple of stem and ext.
  71. func (cd StemExt) StemExt() (string, string) {
  72. return cd.stem, cd.ext
  73. }