/* * mime-db: Mime Database, (C) 2015 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // Package contentdb is a database of file extension to mime content-type. // Definitions are imported from NodeJS mime-db project under MIT license. package contentdb import ( "errors" "fmt" "strings" "sync" "encoding/json" ) var ( // Internal lock. mutex = &sync.Mutex{} // Make note of initialization. isInitialized = false // Database of extension:content-type. extDB map[string]string ) // Load JSON data from gobindata and parse them into extDB. func loadDB() error { // Structure of JSON data from mime-db project. type dbEntry struct { Source string `json:"source"` Compressible bool `json:"compresible"` Extensions []string `json:"extensions"` } // Access embedded "db.json" inside go-bindata. jsonDB, e := Asset("db/db.json") if e != nil { return e } // Convert db.json into go's typed structure. db := make(map[string]dbEntry) if e := json.Unmarshal(jsonDB, &db); e != nil { return e } // Generate a new database from mime-db. for key, val := range db { if len(val.Extensions) > 0 { /* Denormalize - each extension has its own unique content-type now. Looks will be fast. */ for _, ext := range val.Extensions { /* Single extension type may map to multiple content-types. In that case, simply prefer the longest content-type to maintain some level of consistency. Only guarantee is, whatever content type is assigned, it is appropriate and valid type. */ if strings.Compare(extDB[ext], key) < 0 { extDB[ext] = key } } } } return nil } // Init initializes contentdb for lookups. JSON structure is parsed into a simple map of extension and content-type. func Init() error { mutex.Lock() defer mutex.Unlock() if !isInitialized { var e error extDB = make(map[string]string) if !isInitialized { e = loadDB() } isInitialized = true return e } return nil } // Lookup returns matching content-type for known types of file extensions. func Lookup(extension string) (contentType string, e error) { if !isInitialized { return "", errors.New("contentdb is not initialized") } return extDB[extension], e } // MustLookup returns matching content-type for known types of file extensions. In case of error, it panics. func MustLookup(extension string) (contentType string) { var e error if contentType, e = Lookup(extension); e != nil { panic(fmt.Sprintf("Lookup failed: %s\n", e)) } return contentType }