minio/pkg/contentdb/contentdb.go
2015-12-07 12:34:09 -08:00

119 lines
3 KiB
Go

/*
* 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
}