mirror of
https://github.com/h2non/filetype.git
synced 2025-12-24 11:52:08 +08:00
feat: release
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
language: go
|
||||
script: go test ./...
|
||||
go:
|
||||
- 1.5
|
||||
- 1.4
|
||||
- 1.3
|
||||
- release
|
||||
- tip
|
||||
|
||||
185
README.md
185
README.md
@@ -1,8 +1,16 @@
|
||||
# filetype [](https://travis-ci.org/h2non/filetype) [](https://godoc.org/github.com/h2non/filetype)
|
||||
|
||||
Small [Go](https://golang.org) package to infer the file type checking the [magic number](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) of a given binary buffer.
|
||||
Small [Go](https://golang.org) package to infer the file and MIME type checking the [magic numbers](https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_numbers_in_files) signature.
|
||||
|
||||
Supports a wide range of file types, including images formats, fonts, videos, audio and other common application files, and provides the proper file extension and convenient MIME code.
|
||||
## Features
|
||||
|
||||
- Supports a [wide range](#supported-types) of file types
|
||||
- Provides file extension and proper MIME type
|
||||
- File discovery by extension or MIME type
|
||||
- File discovery by class (image, video, audio...)
|
||||
- Bunch of helpers and shortcuts for easy file checking
|
||||
- Pluggable by default: plug in new types and file matchers
|
||||
- Simple and semantic API
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -10,31 +18,192 @@ Supports a wide range of file types, including images formats, fonts, videos, au
|
||||
go get gopkg.in/h2non/filetype.v0
|
||||
```
|
||||
|
||||
## Usage
|
||||
## Usage
|
||||
|
||||
```go
|
||||
import "gopkg.in/h2non/filetype.v0"
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
See [Godoc](https://godoc.org/github.com/h2non/filetype) reference.
|
||||
|
||||
## Examples
|
||||
|
||||
#### Simple file type checking
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"gopkg.in/h2non/filetype.v0"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
buf, _ := ioutil.ReadFile("sample.jpg")
|
||||
|
||||
kind, unkwown := filetype.Type(buf)
|
||||
kind, unkwown := filetype.Match(buf)
|
||||
if unkwown != nil {
|
||||
fmt.Printf("Unkwown file type")
|
||||
fmt.Printf("Unkwown: %s", unkwown)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("File type found: %s. MIME: %s", kind.Extension, kind.MIME.Value)
|
||||
fmt.Printf("File type: %s. MIME: %s\n", kind.Extension, kind.MIME.Value)
|
||||
}
|
||||
```
|
||||
|
||||
## API
|
||||
#### Check type class
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/h2non/filetype.v0"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
buf, _ := ioutil.ReadFile("sample.jpg")
|
||||
|
||||
if filetype.IsImage(buf) {
|
||||
fmt.Println("Image file")
|
||||
} else {
|
||||
fmt.Println("Not an image")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Supported type
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/h2non/filetype.v0"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Check if file is supported by extension
|
||||
if filetype.IsSupported("jpg") {
|
||||
fmt.Println("Extension supported")
|
||||
} else {
|
||||
fmt.Println("Extension not supported")
|
||||
}
|
||||
|
||||
// Check if file is supported by extension
|
||||
if filetype.IsMIMESupported("image/jpeg") {
|
||||
fmt.Println("MIME type supported")
|
||||
} else {
|
||||
fmt.Println("MIME type not supported")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Add additional file type matchers
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gopkg.in/h2non/filetype.v0"
|
||||
)
|
||||
|
||||
var fooType = filetype.NewType("foo", "foo/foo")
|
||||
|
||||
func fooMatcher(buf []byte, length int) bool {
|
||||
return length > 1 && buf[0] == 0x01 && buf[1] == 0x02
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Register the new matcher and its type
|
||||
filetype.AddMatcher(fooType, fooMatcher)
|
||||
|
||||
// Check if the new type is supported by extension
|
||||
if filetype.IsSupported("foo") {
|
||||
fmt.Println("Suppored type: foo")
|
||||
}
|
||||
|
||||
// Check if the new type is supported by MIME
|
||||
if filetype.IsMIMESupported("foo/foo") {
|
||||
fmt.Println("Suppored type: foo/foo")
|
||||
}
|
||||
|
||||
// Try to match the file
|
||||
fooFile := []byte{0x01, 0x02}
|
||||
kind, _ := filetype.Match(fooFile)
|
||||
if kind == filetype.Unknown {
|
||||
fmt.Println("Unknown file type")
|
||||
} else {
|
||||
fmt.Printf("File type matched: %s\n", kind.Extension)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Supported types
|
||||
|
||||
#### Image
|
||||
|
||||
- **jpg** - `image/jpeg`
|
||||
- **png** - `image/png`
|
||||
- **gif** - `image/gif`
|
||||
- **webp** - `image/webp`
|
||||
- **cr2** - `image/x-canon-cr2`
|
||||
- **tif** - `image/tiff`
|
||||
- **bmp** - `image/bmp`
|
||||
- **jxr** - `image/vnd.ms-photo`
|
||||
- **psd** - `image/vnd.adobe.photoshop`
|
||||
- **ico** - `image/x-icon`
|
||||
|
||||
#### Video
|
||||
|
||||
- **mp4** - `video/mp4`
|
||||
- **m4v** - `video/x-m4v`
|
||||
- **mkv** - `video/x-matroska`
|
||||
- **webm** - `video/webm`
|
||||
- **mov** - `video/quicktime`
|
||||
- **avi** - `video/x-msvideo`
|
||||
- **wmv** - `video/x-ms-wmv`
|
||||
- **mpg** - `video/mpeg`
|
||||
- **flv** - `video/x-flv`
|
||||
|
||||
#### Audio
|
||||
|
||||
- **mid** - `audio/midi`
|
||||
- **mp3** - `audio/mpeg`
|
||||
- **m4a** - `audio/m4a`
|
||||
- **ogg** - `audio/ogg`
|
||||
- **flac** - `audio/x-flac`
|
||||
- **wav** - `audio/x-wav`
|
||||
|
||||
#### Archive
|
||||
|
||||
- **epub** - `application/epub+zip`
|
||||
- **zip** - `application/zip`
|
||||
- **tar** - `application/x-tar`
|
||||
- **rar** - `application/x-rar-compressed`
|
||||
- **gz** - `application/gzip`
|
||||
- **bz2** - `application/x-bzip2`
|
||||
- **7z** - `application/x-7z-compressed`
|
||||
- **xz** - `application/x-xz`
|
||||
- **pdf** - `application/pdf`
|
||||
- **exe** - `application/x-msdownload`
|
||||
- **swf** - `application/x-shockwave-flash`
|
||||
- **rtf** - `application/rtf`
|
||||
- **eot** - `application/octet-stream`
|
||||
- **ps** - `application/postscript`
|
||||
- **sqlite** - `application/x-sqlite3`
|
||||
|
||||
#### Font
|
||||
|
||||
- **woff** - `application/font-woff`
|
||||
- **woff2** - `application/font-woff`
|
||||
- **ttf** - `application/font-sfnt`
|
||||
- **otf** - `application/font-sfnt`
|
||||
|
||||
## License
|
||||
|
||||
|
||||
43
filetype.go
43
filetype.go
@@ -12,14 +12,19 @@ var Types = types.Types
|
||||
// Create and register a new type
|
||||
var NewType = types.NewType
|
||||
|
||||
// Default types
|
||||
var Empty = types.Empty
|
||||
// Default unknown file type
|
||||
var Unknown = types.Unknown
|
||||
|
||||
// Predefined errors
|
||||
var EmptyBufferErr = errors.New("Empty buffer")
|
||||
var UnknownBufferErr = errors.New("Unknown buffer type")
|
||||
|
||||
// Register a new file type
|
||||
func AddType(ext, mime string) types.Type {
|
||||
return types.NewType(ext, mime)
|
||||
}
|
||||
|
||||
// Checks if a given buffer matches with the given file type extension
|
||||
func Is(buf []byte, ext string) bool {
|
||||
kind, ok := types.Types[ext]
|
||||
if ok {
|
||||
@@ -28,24 +33,29 @@ func Is(buf []byte, ext string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Semantic alias to Is()
|
||||
func IsExtension(buf []byte, ext string) bool {
|
||||
return Is(buf, ext)
|
||||
}
|
||||
|
||||
// Checks if a given buffer matches with the given file type
|
||||
func IsType(buf []byte, kind types.Type) bool {
|
||||
matcher := matchers.Matchers[kind]
|
||||
if matcher == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
length := len(buf)
|
||||
return matcher(buf, length) != types.Unknown
|
||||
return matcher(buf, len(buf)) != types.Unknown
|
||||
}
|
||||
|
||||
// Register a new matcher type
|
||||
func AddMatcher(fileType types.Type, matcher matchers.Matcher) matchers.TypeMatcher {
|
||||
return matchers.NewMatcher(fileType, matcher)
|
||||
}
|
||||
|
||||
// Register a new file type
|
||||
func AddType(ext, mime string) types.Type {
|
||||
return types.NewType(ext, mime)
|
||||
// Checks if a given buffer matches with the given MIME type
|
||||
func IsMIME(buf []byte, mime string) bool {
|
||||
for _, kind := range types.Types {
|
||||
if kind.MIME.Value == mime {
|
||||
matcher := matchers.Matchers[kind]
|
||||
return matcher(buf, len(buf)) != types.Unknown
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if a given file extension is supported
|
||||
@@ -58,7 +68,7 @@ func IsSupported(ext string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if a given MIME expression is supported
|
||||
// Check if a given MIME type is supported
|
||||
func IsMIMESupported(mime string) bool {
|
||||
for _, m := range Types {
|
||||
if m.MIME.Value == mime {
|
||||
@@ -67,3 +77,8 @@ func IsMIMESupported(mime string) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Retrieve a Type by file extension
|
||||
func GetType(ext string) types.Type {
|
||||
return types.Get(ext)
|
||||
}
|
||||
|
||||
119
filetype_test.go
119
filetype_test.go
@@ -1,25 +1,122 @@
|
||||
package filetype
|
||||
|
||||
import (
|
||||
"gopkg.in/h2non/filetype.v0/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMatches(t *testing.T) {
|
||||
func TestIs(t *testing.T) {
|
||||
cases := []struct {
|
||||
buf []byte
|
||||
ext string
|
||||
buf []byte
|
||||
ext string
|
||||
match bool
|
||||
}{
|
||||
{[]byte{0xFF, 0xD8, 0xFF}, "jpg"},
|
||||
{[]byte{0xFF, 0xD8, 0xFF}, "jpg", true},
|
||||
{[]byte{0xFF, 0xD8, 0x00}, "jpg", false},
|
||||
{[]byte{0x89, 0x50, 0x4E, 0x47}, "png", true},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
match, err := Match(test.buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Error: %s", err)
|
||||
}
|
||||
|
||||
if match.Extension != test.ext {
|
||||
t.Fatalf("Invalid image type: %s", match.Extension)
|
||||
if Is(test.buf, test.ext) != test.match {
|
||||
t.Fatalf("Invalid match: %s", test.ext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsType(t *testing.T) {
|
||||
cases := []struct {
|
||||
buf []byte
|
||||
kind types.Type
|
||||
match bool
|
||||
}{
|
||||
{[]byte{0xFF, 0xD8, 0xFF}, types.Get("jpg"), true},
|
||||
{[]byte{0xFF, 0xD8, 0x00}, types.Get("jpg"), false},
|
||||
{[]byte{0x89, 0x50, 0x4E, 0x47}, types.Get("png"), true},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
if IsType(test.buf, test.kind) != test.match {
|
||||
t.Fatalf("Invalid match: %s", test.kind.Extension)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsMIME(t *testing.T) {
|
||||
cases := []struct {
|
||||
buf []byte
|
||||
mime string
|
||||
match bool
|
||||
}{
|
||||
{[]byte{0xFF, 0xD8, 0xFF}, "image/jpeg", true},
|
||||
{[]byte{0xFF, 0xD8, 0x00}, "image/jpeg", false},
|
||||
{[]byte{0x89, 0x50, 0x4E, 0x47}, "image/png", true},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
if IsMIME(test.buf, test.mime) != test.match {
|
||||
t.Fatalf("Invalid match: %s", test.mime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsSupported(t *testing.T) {
|
||||
cases := []struct {
|
||||
ext string
|
||||
match bool
|
||||
}{
|
||||
{"jpg", true},
|
||||
{"jpeg", false},
|
||||
{"abc", false},
|
||||
{"png", true},
|
||||
{"mp4", true},
|
||||
{"", false},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
if IsSupported(test.ext) != test.match {
|
||||
t.Fatalf("Invalid match: %s", test.ext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsMIMESupported(t *testing.T) {
|
||||
cases := []struct {
|
||||
mime string
|
||||
match bool
|
||||
}{
|
||||
{"image/jpeg", true},
|
||||
{"foo/bar", false},
|
||||
{"image/png", true},
|
||||
{"video/mpeg", true},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
if IsMIMESupported(test.mime) != test.match {
|
||||
t.Fatalf("Invalid match: %s", test.mime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddType(t *testing.T) {
|
||||
AddType("foo", "foo/foo")
|
||||
|
||||
if !IsSupported("foo") {
|
||||
t.Fatalf("Not supported extension")
|
||||
}
|
||||
|
||||
if !IsMIMESupported("foo/foo") {
|
||||
t.Fatalf("Not supported MIME type")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetType(t *testing.T) {
|
||||
jpg := GetType("jpg")
|
||||
if jpg == types.Unknown {
|
||||
t.Fatalf("Type should be supported")
|
||||
}
|
||||
|
||||
invalid := GetType("invalid")
|
||||
if invalid != Unknown {
|
||||
t.Fatalf("Type should not be supported")
|
||||
}
|
||||
}
|
||||
|
||||
10
kind.go
10
kind.go
@@ -5,7 +5,7 @@ import (
|
||||
"gopkg.in/h2non/filetype.v0/types"
|
||||
)
|
||||
|
||||
// Match file as image type
|
||||
// Try to match a file as image type
|
||||
func Image(buf []byte) (types.Type, error) {
|
||||
return doMatchMap(buf, matchers.Image)
|
||||
}
|
||||
@@ -16,7 +16,7 @@ func IsImage(buf []byte) bool {
|
||||
return kind != types.Unknown
|
||||
}
|
||||
|
||||
// Match file as audio type
|
||||
// Try to match a file as audio type
|
||||
func Audio(buf []byte) (types.Type, error) {
|
||||
return doMatchMap(buf, matchers.Audio)
|
||||
}
|
||||
@@ -27,7 +27,7 @@ func IsAudio(buf []byte) bool {
|
||||
return kind != types.Unknown
|
||||
}
|
||||
|
||||
// Match file as video type
|
||||
// Try to match a file as video type
|
||||
func Video(buf []byte) (types.Type, error) {
|
||||
return doMatchMap(buf, matchers.Video)
|
||||
}
|
||||
@@ -38,7 +38,7 @@ func IsVideo(buf []byte) bool {
|
||||
return kind != types.Unknown
|
||||
}
|
||||
|
||||
// Match file as text font type
|
||||
// Try to match a file as text font type
|
||||
func Font(buf []byte) (types.Type, error) {
|
||||
return doMatchMap(buf, matchers.Font)
|
||||
}
|
||||
@@ -49,7 +49,7 @@ func IsFont(buf []byte) bool {
|
||||
return kind != types.Unknown
|
||||
}
|
||||
|
||||
// Match file as generic archive type
|
||||
// Try to match a file as generic archive type
|
||||
func Archive(buf []byte) (types.Type, error) {
|
||||
return doMatchMap(buf, matchers.Archive)
|
||||
}
|
||||
|
||||
39
kind_test.go
39
kind_test.go
@@ -1 +1,40 @@
|
||||
package filetype
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestKind(t *testing.T) {
|
||||
var cases = []struct {
|
||||
buf []byte
|
||||
ext string
|
||||
}{
|
||||
{[]byte{0xFF, 0xD8, 0xFF}, "jpg"},
|
||||
{[]byte{0x89, 0x50, 0x4E, 0x47}, "png"},
|
||||
{[]byte{0x89, 0x0, 0x0}, "unknown"},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
kind, _ := Image(test.buf)
|
||||
if kind.Extension != test.ext {
|
||||
t.Fatalf("Invalid match: %s != %s", kind.Extension, test.ext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsKind(t *testing.T) {
|
||||
var cases = []struct {
|
||||
buf []byte
|
||||
match bool
|
||||
}{
|
||||
{[]byte{0xFF, 0xD8, 0xFF}, true},
|
||||
{[]byte{0x89, 0x50, 0x4E, 0x47}, true},
|
||||
{[]byte{0x89, 0x0, 0x0}, false},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
if IsImage(test.buf) != test.match {
|
||||
t.Fatalf("Invalid match: %s", test.match)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
7
match.go
7
match.go
@@ -15,7 +15,7 @@ var NewMatcher = matchers.NewMatcher
|
||||
func Match(buf []byte) (types.Type, error) {
|
||||
length := len(buf)
|
||||
if length == 0 {
|
||||
return types.Empty, nil
|
||||
return types.Unknown, EmptyBufferErr
|
||||
}
|
||||
|
||||
for _, checker := range Matchers {
|
||||
@@ -33,6 +33,11 @@ func Get(buf []byte) (types.Type, error) {
|
||||
return Match(buf)
|
||||
}
|
||||
|
||||
// Register a new matcher type
|
||||
func AddMatcher(fileType types.Type, matcher matchers.Matcher) matchers.TypeMatcher {
|
||||
return matchers.NewMatcher(fileType, matcher)
|
||||
}
|
||||
|
||||
// Checks if the given buffer matches with some supported file type
|
||||
func Matches(buf []byte) bool {
|
||||
kind, _ := Match(buf)
|
||||
|
||||
@@ -1 +1,100 @@
|
||||
package filetype
|
||||
|
||||
import (
|
||||
"gopkg.in/h2non/filetype.v0/matchers"
|
||||
"gopkg.in/h2non/filetype.v0/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMatch(t *testing.T) {
|
||||
cases := []struct {
|
||||
buf []byte
|
||||
ext string
|
||||
}{
|
||||
{[]byte{0xFF, 0xD8, 0xFF}, "jpg"},
|
||||
{[]byte{0xFF, 0xD8, 0x00}, "unknown"},
|
||||
{[]byte{0x89, 0x50, 0x4E, 0x47}, "png"},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
match, err := Match(test.buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Error: %s", err)
|
||||
}
|
||||
|
||||
if match.Extension != test.ext {
|
||||
t.Fatalf("Invalid image type: %s", match.Extension)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatches(t *testing.T) {
|
||||
cases := []struct {
|
||||
buf []byte
|
||||
match bool
|
||||
}{
|
||||
{[]byte{0xFF, 0xD8, 0xFF}, true},
|
||||
{[]byte{0xFF, 0x0, 0x0}, false},
|
||||
{[]byte{0x89, 0x50, 0x4E, 0x47}, true},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
if Matches(test.buf) != test.match {
|
||||
t.Fatalf("Do not matches: %#v", test.buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddMatcher(t *testing.T) {
|
||||
fileType := AddType("foo", "foo/foo")
|
||||
|
||||
AddMatcher(fileType, func(buf []byte, l int) bool {
|
||||
return l == 2 && buf[0] == 0x00 && buf[1] == 0x00
|
||||
})
|
||||
|
||||
if !Is([]byte{0x00, 0x00}, "foo") {
|
||||
t.Fatalf("Type cannot match")
|
||||
}
|
||||
|
||||
if !IsSupported("foo") {
|
||||
t.Fatalf("Not supported extension")
|
||||
}
|
||||
|
||||
if !IsMIMESupported("foo/foo") {
|
||||
t.Fatalf("Not supported MIME type")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchMap(t *testing.T) {
|
||||
cases := []struct {
|
||||
buf []byte
|
||||
kind types.Type
|
||||
}{
|
||||
{[]byte{0xFF, 0xD8, 0xFF}, types.Get("jpg")},
|
||||
{[]byte{0x89, 0x50, 0x4E, 0x47}, types.Get("png")},
|
||||
{[]byte{0xFF, 0x0, 0x0}, Unknown},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
if kind := MatchMap(test.buf, matchers.Image); kind != test.kind {
|
||||
t.Fatalf("Do not matches: %#v", test.buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchesMap(t *testing.T) {
|
||||
cases := []struct {
|
||||
buf []byte
|
||||
match bool
|
||||
}{
|
||||
{[]byte{0xFF, 0xD8, 0xFF}, true},
|
||||
{[]byte{0x89, 0x50, 0x4E, 0x47}, true},
|
||||
{[]byte{0xFF, 0x0, 0x0}, false},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
if match := MatchesMap(test.buf, matchers.Image); match != test.match {
|
||||
t.Fatalf("Do not matches: %#v", test.buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,5 +39,6 @@ func register(matchers ...Map) {
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Arguments order is intentional
|
||||
register(Image, Video, Audio, Font, Archive)
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package matchers
|
||||
@@ -1,4 +1,3 @@
|
||||
package types
|
||||
|
||||
var Empty = NewType("", "")
|
||||
var Unknown = NewType("unknown", "")
|
||||
|
||||
@@ -6,6 +6,7 @@ type MIME struct {
|
||||
Value string
|
||||
}
|
||||
|
||||
// Creates a new MIME type
|
||||
func NewMIME(mime string) MIME {
|
||||
kind, subtype := splitMime(mime)
|
||||
return MIME{Type: kind, Subtype: subtype, Value: mime}
|
||||
|
||||
@@ -1 +1,27 @@
|
||||
package types
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSplit(t *testing.T) {
|
||||
cases := []struct {
|
||||
mime string
|
||||
kind string
|
||||
subtype string
|
||||
}{
|
||||
{"image/jpeg", "image", "jpeg"},
|
||||
{"/jpeg", "", "jpeg"},
|
||||
{"image/", "image", ""},
|
||||
{"/", "", ""},
|
||||
{"image", "image", ""},
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
kind, subtype := splitMime(test.mime)
|
||||
if test.kind != kind {
|
||||
t.Fatalf("Invalid kind: %s", test.kind)
|
||||
}
|
||||
if test.subtype != subtype {
|
||||
t.Fatalf("Invalid subtype: %s", test.subtype)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,17 @@ package types
|
||||
|
||||
var Types = make(map[string]Type)
|
||||
|
||||
// Register a new type
|
||||
func Add(t Type) Type {
|
||||
Types[t.Extension] = t
|
||||
return t
|
||||
}
|
||||
|
||||
// Retrieve a Type by extension
|
||||
func Get(ext string) Type {
|
||||
kind := Types[ext]
|
||||
if kind.Extension != "" {
|
||||
return kind
|
||||
}
|
||||
return Unknown
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user