List objects in a bucket.

master
Frederick F. Kautz IV 10 years ago
parent d6fd1b0a38
commit cc4329fb12
  1. 42
      pkg/storage/storage.go
  2. 6
      pkg/webapi/minioapi/definitions.go
  3. 78
      pkg/webapi/minioapi/minioapi.go

@ -3,13 +3,25 @@ package storage
import ( import (
"bytes" "bytes"
"io" "io"
"log"
"strings"
"time"
) )
type Storage struct { type Storage struct {
data map[string][]byte data map[string]storedObject
} }
type ObjectMetadata struct{} type storedObject struct {
metadata ObjectMetadata
data []byte
}
type ObjectMetadata struct {
Key string
SecCreated int64
Size int
}
type GenericError struct { type GenericError struct {
bucket string bucket string
@ -27,7 +39,7 @@ func (storage *Storage) CopyObjectToWriter(w io.Writer, bucket string, object st
// get object // get object
key := bucket + ":" + object key := bucket + ":" + object
if val, ok := storage.data[key]; ok { if val, ok := storage.data[key]; ok {
objectBuffer := bytes.NewBuffer(val) objectBuffer := bytes.NewBuffer(val.data)
written, err := io.Copy(w, objectBuffer) written, err := io.Copy(w, objectBuffer)
return written, err return written, err
} else { } else {
@ -35,16 +47,30 @@ func (storage *Storage) CopyObjectToWriter(w io.Writer, bucket string, object st
} }
} }
func (storage *Storage) StoreObject(bucket string, object string, data io.Reader) { func (storage *Storage) StoreObject(bucket string, key string, data io.Reader) {
key := bucket + ":" + object objectKey := bucket + ":" + key
var bytesBuffer bytes.Buffer var bytesBuffer bytes.Buffer
newObject := storedObject{}
if _, ok := io.Copy(&bytesBuffer, data); ok == nil { if _, ok := io.Copy(&bytesBuffer, data); ok == nil {
storage.data[key] = bytesBuffer.Bytes() newObject.metadata = ObjectMetadata{
Key: key,
SecCreated: time.Now().Unix(),
Size: len(bytesBuffer.Bytes()),
} }
newObject.data = bytesBuffer.Bytes()
}
storage.data[objectKey] = newObject
} }
func (storage *Storage) ListObjects(bucket, prefix string, count int) []ObjectMetadata { func (storage *Storage) ListObjects(bucket, prefix string, count int) []ObjectMetadata {
return []ObjectMetadata{} var results []ObjectMetadata
for key, object := range storage.data {
log.Println(key)
if strings.HasPrefix(key, bucket+":") {
results = append(results, object.metadata)
}
}
return results
} }
func Start() (chan<- string, <-chan error, *Storage) { func Start() (chan<- string, <-chan error, *Storage) {
@ -52,7 +78,7 @@ func Start() (chan<- string, <-chan error, *Storage) {
errorChannel := make(chan error) errorChannel := make(chan error)
go start(ctrlChannel, errorChannel) go start(ctrlChannel, errorChannel)
return ctrlChannel, errorChannel, &Storage{ return ctrlChannel, errorChannel, &Storage{
data: make(map[string][]byte), data: make(map[string]storedObject),
} }
} }

@ -7,9 +7,9 @@ import (
type ListResponse struct { type ListResponse struct {
XMLName xml.Name `xml:"ListBucketResult"` XMLName xml.Name `xml:"ListBucketResult"`
Name string `xml:"Name"` Name string `xml:"Name"`
Prefix string toragerefix string
Marker string Marker string
MaxKeys int32 MaxKeys int
IsTruncated bool IsTruncated bool
Contents []Content `xml:"Contents",innerxml` Contents []Content `xml:"Contents",innerxml`
} }
@ -18,7 +18,7 @@ type Content struct {
Key string Key string
LastModified string LastModified string
ETag string ETag string
Size uint64 Size int
StorageClass string StorageClass string
Owner Owner Owner Owner
} }

@ -2,9 +2,11 @@ package minioapi
import ( import (
"bytes" "bytes"
"encoding/json"
"encoding/xml" "encoding/xml"
"log" "log"
"net/http" "net/http"
"time"
"github.com/gorilla/mux" "github.com/gorilla/mux"
mstorage "github.com/minio-io/minio/pkg/storage" mstorage "github.com/minio-io/minio/pkg/storage"
@ -14,12 +16,17 @@ type minioApi struct {
storage *mstorage.Storage storage *mstorage.Storage
} }
type encoder interface {
Encode(v interface{}) error
}
func HttpHandler(storage *mstorage.Storage) http.Handler { func HttpHandler(storage *mstorage.Storage) http.Handler {
mux := mux.NewRouter() mux := mux.NewRouter()
api := minioApi{ api := minioApi{
storage: storage, storage: storage,
} }
mux.HandleFunc("/", api.listHandler).Methods("GET") mux.HandleFunc("/", api.listBucketsHandler).Methods("GET")
mux.HandleFunc("/{bucket}/", api.listObjectsHandler).Methods("GET")
mux.HandleFunc("/{bucket}/{object:.*}", api.getObjectHandler).Methods("GET") mux.HandleFunc("/{bucket}/{object:.*}", api.getObjectHandler).Methods("GET")
mux.HandleFunc("/{bucket}/{object:.*}", api.putObjectHandler).Methods("PUT") mux.HandleFunc("/{bucket}/{object:.*}", api.putObjectHandler).Methods("PUT")
return mux return mux
@ -49,14 +56,18 @@ func (server *minioApi) getObjectHandler(w http.ResponseWriter, req *http.Reques
} }
} }
func (server *minioApi) listHandler(w http.ResponseWriter, req *http.Request) { func (server *minioApi) listBucketsHandler(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("/"))
}
func (server *minioApi) listObjectsHandler(w http.ResponseWriter, req *http.Request) {
vars := mux.Vars(req) vars := mux.Vars(req)
//delimiter, ok := vars["delimiter"] //delimiter, ok := vars["delimiter"]
//encodingType, ok := vars["encoding-type"] //encodingType, ok := vars["encoding-type"]
//marker, ok := vars["marker"] //marker, ok := vars["marker"]
//maxKeys, ok := vars["max-keys"] //maxKeys, ok := vars["max-keys"]
bucket := "bucket" bucket := vars["bucket"]
//bucket, ok := vars["bucket"] //bucket, ok := vars["bucket"]
//if ok == false { //if ok == false {
// w.WriteHeader(http.StatusBadRequest) // w.WriteHeader(http.StatusBadRequest)
@ -67,14 +78,26 @@ func (server *minioApi) listHandler(w http.ResponseWriter, req *http.Request) {
prefix = "" prefix = ""
} }
contentType := "xml"
if req.Header["Accept"][0] == "application/json" {
contentType = "json"
}
objects := server.storage.ListObjects(bucket, prefix, 1000) objects := server.storage.ListObjects(bucket, prefix, 1000)
response := generateListResult(objects) response := generateListResult(objects)
var bytesBuffer bytes.Buffer var bytesBuffer bytes.Buffer
xmlEncoder := xml.NewEncoder(&bytesBuffer) var encoder encoder
xmlEncoder.Encode(response) if contentType == "json" {
w.Header().Set("Content-Type", "application/json")
encoder = json.NewEncoder(&bytesBuffer)
} else {
w.Header().Set("Content-Type", "application/xml") w.Header().Set("Content-Type", "application/xml")
encoder = xml.NewEncoder(&bytesBuffer)
}
encoder.Encode(response)
w.Write(bytesBuffer.Bytes()) w.Write(bytesBuffer.Bytes())
} }
@ -86,31 +109,34 @@ func (server *minioApi) putObjectHandler(w http.ResponseWriter, req *http.Reques
} }
func generateListResult(objects []mstorage.ObjectMetadata) ListResponse { func generateListResult(objects []mstorage.ObjectMetadata) ListResponse {
contents := []Content{}
owner := Owner{ owner := Owner{
ID: "MyID", ID: "minio",
DisplayName: "MyDisplayName", DisplayName: "minio",
} }
contents := []Content{
Content{ for _, object := range objects {
Key: "one", content := Content{
LastModified: "two", Key: object.Key,
ETag: "\"ETag\"", LastModified: formatDate(object.SecCreated),
Size: 1, ETag: object.Key,
StorageClass: "three", Size: object.Size,
Owner: owner, StorageClass: "STANDARD",
},
Content{
Key: "four",
LastModified: "five",
ETag: "\"ETag\"",
Size: 1,
StorageClass: "six",
Owner: owner, Owner: owner,
},
} }
data := &ListResponse{ contents = append(contents, content)
}
data := ListResponse{
Name: "name", Name: "name",
Contents: contents, Contents: contents,
MaxKeys: len(objects),
IsTruncated: false,
} }
return *data return data
}
func formatDate(sec int64) string {
timeStamp := time.Unix(sec, 0)
return timeStamp.Format("2006-01-02T15:04:05.000Z")
} }

Loading…
Cancel
Save