mirror of https://github.com/minio/minio.git
Restructure API handlers, add JSON RPC simple HelloService right now.
This commit is contained in:
parent
335c7827eb
commit
4addf7a996
24
commands.go
24
commands.go
|
@ -4,7 +4,8 @@ import (
|
|||
"os/user"
|
||||
|
||||
"github.com/minio/cli"
|
||||
"github.com/minio/minio/pkg/api"
|
||||
"github.com/minio/minio/pkg/server"
|
||||
"github.com/minio/minio/pkg/server/api"
|
||||
)
|
||||
|
||||
func removeDuplicates(slice []string) []string {
|
||||
|
@ -58,16 +59,29 @@ EXAMPLES:
|
|||
`,
|
||||
}
|
||||
|
||||
func getAPIServerConfig(c *cli.Context) api.Config {
|
||||
certFile := c.GlobalString("cert")
|
||||
keyFile := c.GlobalString("key")
|
||||
if (certFile != "" && keyFile == "") || (certFile == "" && keyFile != "") {
|
||||
Fatalln("Both certificate and key are required to enable https.")
|
||||
}
|
||||
tls := (certFile != "" && keyFile != "")
|
||||
return api.Config{
|
||||
Address: c.GlobalString("address"),
|
||||
TLS: tls,
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
RateLimit: c.GlobalInt("ratelimit"),
|
||||
}
|
||||
}
|
||||
|
||||
func runServer(c *cli.Context) {
|
||||
_, err := user.Current()
|
||||
if err != nil {
|
||||
Fatalf("Unable to determine current user. Reason: %s\n", err)
|
||||
}
|
||||
if len(c.Args()) < 1 {
|
||||
cli.ShowCommandHelpAndExit(c, "server", 1) // last argument is exit code
|
||||
}
|
||||
apiServerConfig := getAPIServerConfig(c)
|
||||
if err := api.StartServer(apiServerConfig); err != nil {
|
||||
if err := server.StartServices(apiServerConfig); err != nil {
|
||||
Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
|
17
main.go
17
main.go
|
@ -26,7 +26,6 @@ import (
|
|||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/minio/cli"
|
||||
"github.com/minio/minio/pkg/api"
|
||||
"github.com/minio/minio/pkg/iodine"
|
||||
)
|
||||
|
||||
|
@ -71,22 +70,6 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
func getAPIServerConfig(c *cli.Context) api.Config {
|
||||
certFile := c.GlobalString("cert")
|
||||
keyFile := c.GlobalString("key")
|
||||
if (certFile != "" && keyFile == "") || (certFile == "" && keyFile != "") {
|
||||
Fatalln("Both certificate and key are required to enable https.")
|
||||
}
|
||||
tls := (certFile != "" && keyFile != "")
|
||||
return api.Config{
|
||||
Address: c.GlobalString("address"),
|
||||
TLS: tls,
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
RateLimit: c.GlobalInt("ratelimit"),
|
||||
}
|
||||
}
|
||||
|
||||
// Tries to get os/arch/platform specific information
|
||||
// Returns a map of current os/arch/platform/memstats
|
||||
func getSystemData() map[string]string {
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Minimalist Object Storage, (C) 2014 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 api
|
||||
|
||||
import router "github.com/gorilla/mux"
|
||||
|
||||
type minioAPI struct{}
|
||||
|
||||
// New api
|
||||
func New(config Config) API {
|
||||
var api = minioAPI{}
|
||||
|
||||
mux := router.NewRouter()
|
||||
mux.HandleFunc("/", api.listBucketsHandler).Methods("GET")
|
||||
mux.HandleFunc("/{bucket}", api.listObjectsHandler).Methods("GET")
|
||||
mux.HandleFunc("/{bucket}", api.putBucketHandler).Methods("PUT")
|
||||
mux.HandleFunc("/{bucket}", api.headBucketHandler).Methods("HEAD")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.headObjectHandler).Methods("HEAD")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.putObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}").Methods("PUT")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.listObjectPartsHandler).Queries("uploadId", "{uploadId:.*}").Methods("GET")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.completeMultipartUploadHandler).Queries("uploadId", "{uploadId:.*}").Methods("POST")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.newMultipartUploadHandler).Methods("POST")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.abortMultipartUploadHandler).Queries("uploadId", "{uploadId:.*}").Methods("DELETE")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.getObjectHandler).Methods("GET")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.putObjectHandler).Methods("PUT")
|
||||
|
||||
// not implemented yet
|
||||
mux.HandleFunc("/{bucket}", api.deleteBucketHandler).Methods("DELETE")
|
||||
|
||||
// unsupported API
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.deleteObjectHandler).Methods("DELETE")
|
||||
|
||||
handler := validContentTypeHandler(mux)
|
||||
handler = timeValidityHandler(handler)
|
||||
handler = ignoreResourcesHandler(handler)
|
||||
handler = validateAuthHeaderHandler(handler)
|
||||
handler = rateLimitHandler(handler, config.RateLimit)
|
||||
handler = loggingHandler(handler)
|
||||
return API{config, handler}
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
/*
|
||||
* Minimalist Object Storage, (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 web
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/minio/minio/pkg/api/config"
|
||||
"github.com/minio/minio/pkg/iodine"
|
||||
"github.com/minio/minio/pkg/utils/crypto/keys"
|
||||
"github.com/minio/minio/pkg/utils/log"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultWeb = "polygon"
|
||||
)
|
||||
|
||||
type webAPI struct {
|
||||
conf config.Config
|
||||
webPath string
|
||||
}
|
||||
|
||||
// No encoder interface exists, so we create one.
|
||||
type encoder interface {
|
||||
Encode(v interface{}) error
|
||||
}
|
||||
|
||||
// HTTPHandler - http wrapper handler
|
||||
func HTTPHandler() http.Handler {
|
||||
mux := mux.NewRouter()
|
||||
var api = webAPI{}
|
||||
|
||||
if err := api.conf.SetupConfig(); err != nil {
|
||||
log.Fatal(iodine.New(err, nil))
|
||||
}
|
||||
|
||||
api.webPath = filepath.Join(api.conf.GetConfigPath(), defaultWeb)
|
||||
mux.Handle("/{polygon:.*}", http.FileServer(http.Dir(api.webPath))).Methods("GET")
|
||||
mux.HandleFunc("/access", api.accessHandler).Methods("POST")
|
||||
return mux
|
||||
}
|
||||
|
||||
func writeResponse(w http.ResponseWriter, response interface{}) []byte {
|
||||
var bytesBuffer bytes.Buffer
|
||||
var encoder encoder
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
encoder = json.NewEncoder(&bytesBuffer)
|
||||
w.Header().Set("Server", "Minio Management Console")
|
||||
w.Header().Set("Connection", "close")
|
||||
encoder.Encode(response)
|
||||
return bytesBuffer.Bytes()
|
||||
}
|
||||
|
||||
func (web *webAPI) accessHandler(w http.ResponseWriter, req *http.Request) {
|
||||
var err error
|
||||
var accesskey, secretkey []byte
|
||||
username := req.FormValue("username")
|
||||
if len(username) <= 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = web.conf.ReadConfig()
|
||||
if err != nil {
|
||||
log.Error.Println(iodine.New(err, nil))
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if web.conf.IsUserExists(username) {
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
return
|
||||
}
|
||||
|
||||
var user = config.User{}
|
||||
user.Name = username
|
||||
|
||||
accesskey, err = keys.GenerateRandomAlphaNumeric(keys.MinioAccessID)
|
||||
if err != nil {
|
||||
log.Error.Println(iodine.New(err, nil))
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
user.AccessKey = string(accesskey)
|
||||
|
||||
secretkey, err = keys.GenerateRandomBase64(keys.MinioSecretID)
|
||||
if err != nil {
|
||||
log.Error.Println(iodine.New(err, nil))
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
user.SecretKey = string(secretkey)
|
||||
|
||||
web.conf.AddUser(user)
|
||||
err = web.conf.WriteConfig()
|
||||
if err != nil {
|
||||
log.Error.Println(iodine.New(err, nil))
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
err = web.conf.ReadConfig()
|
||||
if err != nil {
|
||||
log.Error.Println(iodine.New(err, nil))
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// Get user back for sending it over HTTP reply
|
||||
user = web.conf.GetUser(username)
|
||||
w.Write(writeResponse(w, user))
|
||||
}
|
|
@ -23,21 +23,24 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
func (server *minioAPI) isValidOp(w http.ResponseWriter, req *http.Request, acceptsContentType contentType) bool {
|
||||
// MinioAPI -
|
||||
type MinioAPI struct{}
|
||||
|
||||
func (api MinioAPI) isValidOp(w http.ResponseWriter, req *http.Request, acceptsContentType contentType) bool {
|
||||
vars := mux.Vars(req)
|
||||
bucket := vars["bucket"]
|
||||
log.Println(bucket)
|
||||
return true
|
||||
}
|
||||
|
||||
// GET Bucket (List Multipart uploads)
|
||||
// ListMultipartUploadsHandler - GET Bucket (List Multipart uploads)
|
||||
// -------------------------
|
||||
// This operation lists in-progress multipart uploads. An in-progress
|
||||
// multipart upload is a multipart upload that has been initiated,
|
||||
// using the Initiate Multipart Upload request, but has not yet been completed or aborted.
|
||||
// This operation returns at most 1,000 multipart uploads in the response.
|
||||
//
|
||||
func (server *minioAPI) listMultipartUploadsHandler(w http.ResponseWriter, req *http.Request) {
|
||||
func (api MinioAPI) ListMultipartUploadsHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
log.Println(acceptsContentType)
|
||||
|
||||
|
@ -51,21 +54,21 @@ func (server *minioAPI) listMultipartUploadsHandler(w http.ResponseWriter, req *
|
|||
log.Println(bucket)
|
||||
}
|
||||
|
||||
// GET Bucket (List Objects)
|
||||
// ListObjectsHandler - GET Bucket (List Objects)
|
||||
// -------------------------
|
||||
// This implementation of the GET operation returns some or all (up to 1000)
|
||||
// of the objects in a bucket. You can use the request parameters as selection
|
||||
// criteria to return a subset of the objects in a bucket.
|
||||
//
|
||||
func (server *minioAPI) listObjectsHandler(w http.ResponseWriter, req *http.Request) {
|
||||
func (api MinioAPI) ListObjectsHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// verify if bucket allows this operation
|
||||
if !server.isValidOp(w, req, acceptsContentType) {
|
||||
if !api.isValidOp(w, req, acceptsContentType) {
|
||||
return
|
||||
}
|
||||
|
||||
if isRequestUploads(req.URL.Query()) {
|
||||
server.listMultipartUploadsHandler(w, req)
|
||||
api.ListMultipartUploadsHandler(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -80,11 +83,11 @@ func (server *minioAPI) listObjectsHandler(w http.ResponseWriter, req *http.Requ
|
|||
|
||||
}
|
||||
|
||||
// GET Service
|
||||
// ListBucketsHandler - GET Service
|
||||
// -----------
|
||||
// This implementation of the GET operation returns a list of all buckets
|
||||
// owned by the authenticated sender of the request.
|
||||
func (server *minioAPI) listBucketsHandler(w http.ResponseWriter, req *http.Request) {
|
||||
func (api MinioAPI) ListBucketsHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// uncomment this when we have webcli
|
||||
// without access key credentials one cannot list buckets
|
||||
|
@ -95,10 +98,10 @@ func (server *minioAPI) listBucketsHandler(w http.ResponseWriter, req *http.Requ
|
|||
log.Println(acceptsContentType)
|
||||
}
|
||||
|
||||
// PUT Bucket
|
||||
// PutBucketHandler - PUT Bucket
|
||||
// ----------
|
||||
// This implementation of the PUT operation creates a new bucket for authenticated request
|
||||
func (server *minioAPI) putBucketHandler(w http.ResponseWriter, req *http.Request) {
|
||||
func (api MinioAPI) PutBucketHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// uncomment this when we have webcli
|
||||
// without access key credentials one cannot create a bucket
|
||||
|
@ -107,7 +110,7 @@ func (server *minioAPI) putBucketHandler(w http.ResponseWriter, req *http.Reques
|
|||
// return
|
||||
// }
|
||||
if isRequestBucketACL(req.URL.Query()) {
|
||||
server.putBucketACLHandler(w, req)
|
||||
api.PutBucketACLHandler(w, req)
|
||||
return
|
||||
}
|
||||
// read from 'x-amz-acl'
|
||||
|
@ -122,10 +125,10 @@ func (server *minioAPI) putBucketHandler(w http.ResponseWriter, req *http.Reques
|
|||
log.Println(bucket)
|
||||
}
|
||||
|
||||
// PUT Bucket ACL
|
||||
// PutBucketACLHandler - PUT Bucket ACL
|
||||
// ----------
|
||||
// This implementation of the PUT operation modifies the bucketACL for authenticated request
|
||||
func (server *minioAPI) putBucketACLHandler(w http.ResponseWriter, req *http.Request) {
|
||||
func (api MinioAPI) PutBucketACLHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// read from 'x-amz-acl'
|
||||
aclType := getACLType(req)
|
||||
|
@ -139,13 +142,13 @@ func (server *minioAPI) putBucketACLHandler(w http.ResponseWriter, req *http.Req
|
|||
log.Println(bucket)
|
||||
}
|
||||
|
||||
// HEAD Bucket
|
||||
// HeadBucketHandler - HEAD Bucket
|
||||
// ----------
|
||||
// This operation is useful to determine if a bucket exists.
|
||||
// The operation returns a 200 OK if the bucket exists and you
|
||||
// have permission to access it. Otherwise, the operation might
|
||||
// return responses such as 404 Not Found and 403 Forbidden.
|
||||
func (server *minioAPI) headBucketHandler(w http.ResponseWriter, req *http.Request) {
|
||||
func (api MinioAPI) HeadBucketHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
log.Println(acceptsContentType)
|
||||
|
|
@ -18,6 +18,15 @@ package api
|
|||
|
||||
import "encoding/xml"
|
||||
|
||||
// Config - http server config
|
||||
type Config struct {
|
||||
Address string
|
||||
TLS bool
|
||||
CertFile string
|
||||
KeyFile string
|
||||
RateLimit int
|
||||
}
|
||||
|
||||
// Limit number of objects in a given response
|
||||
const (
|
||||
maxObjectList = 1000
|
|
@ -22,7 +22,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/pkg/api/config"
|
||||
"github.com/minio/minio/pkg/server/config"
|
||||
"github.com/minio/minio/pkg/utils/crypto/keys"
|
||||
)
|
||||
|
||||
|
@ -128,7 +128,8 @@ func parseDate(req *http.Request) (time.Time, error) {
|
|||
return time.Time{}, errors.New("invalid request")
|
||||
}
|
||||
|
||||
func validContentTypeHandler(h http.Handler) http.Handler {
|
||||
// ValidContentTypeHandler -
|
||||
func ValidContentTypeHandler(h http.Handler) http.Handler {
|
||||
return contentTypeHandler{h}
|
||||
}
|
||||
|
||||
|
@ -141,7 +142,8 @@ func (h contentTypeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
h.handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func timeValidityHandler(h http.Handler) http.Handler {
|
||||
// TimeValidityHandler -
|
||||
func TimeValidityHandler(h http.Handler) http.Handler {
|
||||
return timeHandler{h}
|
||||
}
|
||||
|
||||
|
@ -170,9 +172,10 @@ func (h timeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
h.handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// ValidateAuthHeaderHandler -
|
||||
// validate auth header handler is wrapper handler used for API request validation with authorization header.
|
||||
// Current authorization layer supports S3's standard HMAC based signature request.
|
||||
func validateAuthHeaderHandler(h http.Handler) http.Handler {
|
||||
func ValidateAuthHeaderHandler(h http.Handler) http.Handler {
|
||||
return validateAuthHandler{h}
|
||||
}
|
||||
|
||||
|
@ -206,10 +209,11 @@ func (h validateAuthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// IgnoreResourcesHandler -
|
||||
// Ignore resources handler is wrapper handler used for API request resource validation
|
||||
// Since we do not support all the S3 queries, it is necessary for us to throw back a
|
||||
// valid error message indicating such a feature is not implemented.
|
||||
func ignoreResourcesHandler(h http.Handler) http.Handler {
|
||||
func IgnoreResourcesHandler(h http.Handler) http.Handler {
|
||||
return resourceHandler{h}
|
||||
}
|
||||
|
|
@ -94,8 +94,8 @@ func getLogMessage(logMessage *logMessage, w http.ResponseWriter, req *http.Requ
|
|||
return js
|
||||
}
|
||||
|
||||
// loggingHandler logs requests
|
||||
func loggingHandler(h http.Handler) http.Handler {
|
||||
// LoggingHandler logs requests
|
||||
func LoggingHandler(h http.Handler) http.Handler {
|
||||
logger, _ := fileLogger("access.log")
|
||||
return &logHandler{handler: h, logger: logger}
|
||||
}
|
|
@ -32,14 +32,14 @@ const (
|
|||
maxPartsList = 1000
|
||||
)
|
||||
|
||||
// GET Object
|
||||
// GetObjectHandler - GET Object
|
||||
// ----------
|
||||
// This implementation of the GET operation retrieves object. To use GET,
|
||||
// you must have READ access to the object.
|
||||
func (server *minioAPI) getObjectHandler(w http.ResponseWriter, req *http.Request) {
|
||||
func (api MinioAPI) GetObjectHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// verify if this operation is allowed
|
||||
if !server.isValidOp(w, req, acceptsContentType) {
|
||||
if !api.isValidOp(w, req, acceptsContentType) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -51,13 +51,13 @@ func (server *minioAPI) getObjectHandler(w http.ResponseWriter, req *http.Reques
|
|||
|
||||
}
|
||||
|
||||
// HEAD Object
|
||||
// HeadObjectHandler - HEAD Object
|
||||
// -----------
|
||||
// The HEAD operation retrieves metadata from an object without returning the object itself.
|
||||
func (server *minioAPI) headObjectHandler(w http.ResponseWriter, req *http.Request) {
|
||||
func (api MinioAPI) HeadObjectHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// verify if this operation is allowed
|
||||
if !server.isValidOp(w, req, acceptsContentType) {
|
||||
if !api.isValidOp(w, req, acceptsContentType) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -68,13 +68,13 @@ func (server *minioAPI) headObjectHandler(w http.ResponseWriter, req *http.Reque
|
|||
log.Println(bucket, object)
|
||||
}
|
||||
|
||||
// PUT Object
|
||||
// PutObjectHandler - PUT Object
|
||||
// ----------
|
||||
// This implementation of the PUT operation adds an object to a bucket.
|
||||
func (server *minioAPI) putObjectHandler(w http.ResponseWriter, req *http.Request) {
|
||||
func (api MinioAPI) PutObjectHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// verify if this operation is allowed
|
||||
if !server.isValidOp(w, req, acceptsContentType) {
|
||||
if !api.isValidOp(w, req, acceptsContentType) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -120,11 +120,11 @@ func (server *minioAPI) putObjectHandler(w http.ResponseWriter, req *http.Reques
|
|||
|
||||
/// Multipart API
|
||||
|
||||
// New multipart upload
|
||||
func (server *minioAPI) newMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
|
||||
// NewMultipartUploadHandler - New multipart upload
|
||||
func (api MinioAPI) NewMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// handle ACL's here at bucket level
|
||||
if !server.isValidOp(w, req, acceptsContentType) {
|
||||
if !api.isValidOp(w, req, acceptsContentType) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -140,11 +140,11 @@ func (server *minioAPI) newMultipartUploadHandler(w http.ResponseWriter, req *ht
|
|||
log.Println(bucket, object)
|
||||
}
|
||||
|
||||
// Upload part
|
||||
func (server *minioAPI) putObjectPartHandler(w http.ResponseWriter, req *http.Request) {
|
||||
// PutObjectPartHandler - Upload part
|
||||
func (api MinioAPI) PutObjectPartHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// handle ACL's here at bucket level
|
||||
if !server.isValidOp(w, req, acceptsContentType) {
|
||||
if !api.isValidOp(w, req, acceptsContentType) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -189,11 +189,11 @@ func (server *minioAPI) putObjectPartHandler(w http.ResponseWriter, req *http.Re
|
|||
log.Println(uploadID, partID)
|
||||
}
|
||||
|
||||
// Abort multipart upload
|
||||
func (server *minioAPI) abortMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
|
||||
// AbortMultipartUploadHandler - Abort multipart upload
|
||||
func (api MinioAPI) AbortMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// handle ACL's here at bucket level
|
||||
if !server.isValidOp(w, req, acceptsContentType) {
|
||||
if !api.isValidOp(w, req, acceptsContentType) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -205,11 +205,11 @@ func (server *minioAPI) abortMultipartUploadHandler(w http.ResponseWriter, req *
|
|||
log.Println(bucket, object)
|
||||
}
|
||||
|
||||
// List object parts
|
||||
func (server *minioAPI) listObjectPartsHandler(w http.ResponseWriter, req *http.Request) {
|
||||
// ListObjectPartsHandler - List object parts
|
||||
func (api MinioAPI) ListObjectPartsHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// handle ACL's here at bucket level
|
||||
if !server.isValidOp(w, req, acceptsContentType) {
|
||||
if !api.isValidOp(w, req, acceptsContentType) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -224,11 +224,11 @@ func (server *minioAPI) listObjectPartsHandler(w http.ResponseWriter, req *http.
|
|||
log.Println(bucket, object)
|
||||
}
|
||||
|
||||
// Complete multipart upload
|
||||
func (server *minioAPI) completeMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
|
||||
// CompleteMultipartUploadHandler - Complete multipart upload
|
||||
func (api MinioAPI) CompleteMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
|
||||
acceptsContentType := getContentType(req)
|
||||
// handle ACL's here at bucket level
|
||||
if !server.isValidOp(w, req, acceptsContentType) {
|
||||
if !api.isValidOp(w, req, acceptsContentType) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -261,14 +261,14 @@ func (server *minioAPI) completeMultipartUploadHandler(w http.ResponseWriter, re
|
|||
|
||||
/// Delete API
|
||||
|
||||
// Delete bucket
|
||||
func (server *minioAPI) deleteBucketHandler(w http.ResponseWriter, req *http.Request) {
|
||||
// DeleteBucketHandler - Delete bucket
|
||||
func (api MinioAPI) DeleteBucketHandler(w http.ResponseWriter, req *http.Request) {
|
||||
error := getErrorCode(NotImplemented)
|
||||
w.WriteHeader(error.HTTPStatusCode)
|
||||
}
|
||||
|
||||
// Delete object
|
||||
func (server *minioAPI) deleteObjectHandler(w http.ResponseWriter, req *http.Request) {
|
||||
// DeleteObjectHandler - Delete object
|
||||
func (api MinioAPI) DeleteObjectHandler(w http.ResponseWriter, req *http.Request) {
|
||||
error := getErrorCode(NotImplemented)
|
||||
w.WriteHeader(error.HTTPStatusCode)
|
||||
}
|
|
@ -41,8 +41,8 @@ func (c rateLimit) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
c.Remove() // remove
|
||||
}
|
||||
|
||||
// rateLimitHandler limits the number of concurrent http requests
|
||||
func rateLimitHandler(handle http.Handler, limit int) http.Handler {
|
||||
// RateLimitHandler limits the number of concurrent http requests
|
||||
func RateLimitHandler(handle http.Handler, limit int) http.Handler {
|
||||
return rateLimit{
|
||||
handler: handle,
|
||||
rateQueue: make(chan bool, limit),
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Minimalist Object Storage, (C) 2014 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 server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
router "github.com/gorilla/mux"
|
||||
jsonRPC "github.com/gorilla/rpc/v2"
|
||||
"github.com/minio/minio/pkg/server/api"
|
||||
"github.com/minio/minio/pkg/server/rpc"
|
||||
)
|
||||
|
||||
func registerAPI(mux *router.Router) http.Handler {
|
||||
api := api.MinioAPI{}
|
||||
|
||||
mux.HandleFunc("/", api.ListBucketsHandler).Methods("GET")
|
||||
mux.HandleFunc("/{bucket}", api.ListObjectsHandler).Methods("GET")
|
||||
mux.HandleFunc("/{bucket}", api.PutBucketHandler).Methods("PUT")
|
||||
mux.HandleFunc("/{bucket}", api.HeadBucketHandler).Methods("HEAD")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.HeadObjectHandler).Methods("HEAD")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.PutObjectPartHandler).Queries("partNumber", "{partNumber:[0-9]+}", "uploadId", "{uploadId:.*}").Methods("PUT")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.ListObjectPartsHandler).Queries("uploadId", "{uploadId:.*}").Methods("GET")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.CompleteMultipartUploadHandler).Queries("uploadId", "{uploadId:.*}").Methods("POST")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.NewMultipartUploadHandler).Methods("POST")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.AbortMultipartUploadHandler).Queries("uploadId", "{uploadId:.*}").Methods("DELETE")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.GetObjectHandler).Methods("GET")
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.PutObjectHandler).Methods("PUT")
|
||||
|
||||
// not implemented yet
|
||||
mux.HandleFunc("/{bucket}", api.DeleteBucketHandler).Methods("DELETE")
|
||||
|
||||
// unsupported API
|
||||
mux.HandleFunc("/{bucket}/{object:.*}", api.DeleteObjectHandler).Methods("DELETE")
|
||||
|
||||
return mux
|
||||
}
|
||||
|
||||
func registerOthers(mux http.Handler, conf api.Config) http.Handler {
|
||||
mux = api.ValidContentTypeHandler(mux)
|
||||
mux = api.TimeValidityHandler(mux)
|
||||
mux = api.IgnoreResourcesHandler(mux)
|
||||
mux = api.ValidateAuthHeaderHandler(mux)
|
||||
mux = api.RateLimitHandler(mux, conf.RateLimit)
|
||||
mux = api.LoggingHandler(mux)
|
||||
return mux
|
||||
}
|
||||
|
||||
func registerRPC(mux *router.Router, r *jsonRPC.Server) http.Handler {
|
||||
mux.Handle("/rpc", r)
|
||||
return mux
|
||||
}
|
||||
|
||||
// APIHandler api handler
|
||||
func APIHandler(conf api.Config) http.Handler {
|
||||
mux := router.NewRouter()
|
||||
return registerOthers(registerAPI(mux), conf)
|
||||
}
|
||||
|
||||
// RPCHandler rpc handler
|
||||
func RPCHandler() http.Handler {
|
||||
return registerRPC(router.NewRouter(), rpc.HelloServiceHandler())
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Minimalist Object Storage, (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 rpc
|
||||
|
||||
import "net/http"
|
||||
|
||||
// HelloArgs - hello args
|
||||
type HelloArgs struct {
|
||||
Who string
|
||||
}
|
||||
|
||||
// HelloReply - hello reply
|
||||
type HelloReply struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
// HelloService -
|
||||
type HelloService struct{}
|
||||
|
||||
// Say -
|
||||
func (h *HelloService) Say(r *http.Request, args *HelloArgs, reply *HelloReply) error {
|
||||
reply.Message = "Hello, " + args.Who + "!"
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Minimalist Object Storage, (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 rpc
|
||||
|
||||
import (
|
||||
"github.com/gorilla/rpc/v2"
|
||||
"github.com/gorilla/rpc/v2/json"
|
||||
)
|
||||
|
||||
// HelloServiceHandler -
|
||||
func HelloServiceHandler() *rpc.Server {
|
||||
s := rpc.NewServer()
|
||||
s.RegisterCodec(json.NewCodec(), "application/json")
|
||||
s.RegisterService(new(HelloService), "")
|
||||
return s
|
||||
}
|
|
@ -14,43 +14,29 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/pkg/server/api"
|
||||
)
|
||||
|
||||
// Config - http server config
|
||||
type Config struct {
|
||||
Address string
|
||||
TLS bool
|
||||
CertFile string
|
||||
KeyFile string
|
||||
RateLimit int
|
||||
}
|
||||
|
||||
// Start http server
|
||||
func Start(a API) <-chan error {
|
||||
errCh := make(chan error)
|
||||
go start(errCh, a)
|
||||
return errCh
|
||||
}
|
||||
|
||||
func start(errCh chan error, a API) {
|
||||
func startAPI(errCh chan error, conf api.Config) {
|
||||
defer close(errCh)
|
||||
|
||||
var err error
|
||||
// Minio server config
|
||||
httpServer := &http.Server{
|
||||
Addr: a.config.Address,
|
||||
Handler: a.handler,
|
||||
Addr: conf.Address,
|
||||
Handler: APIHandler(conf),
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(a.config.Address)
|
||||
host, port, err := net.SplitHostPort(conf.Address)
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
return
|
||||
|
@ -81,11 +67,11 @@ func start(errCh chan error, a API) {
|
|||
fmt.Printf("Starting minio server on: http://%s:%s\n", host, port)
|
||||
}
|
||||
err = httpServer.ListenAndServe()
|
||||
case a.config.TLS == true:
|
||||
case conf.TLS == true:
|
||||
for _, host := range hosts {
|
||||
fmt.Printf("Starting minio server on: https://%s:%s\n", host, port)
|
||||
}
|
||||
err = httpServer.ListenAndServeTLS(a.config.CertFile, a.config.KeyFile)
|
||||
err = httpServer.ListenAndServeTLS(conf.CertFile, conf.KeyFile)
|
||||
}
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
|
@ -94,15 +80,39 @@ func start(errCh chan error, a API) {
|
|||
return
|
||||
}
|
||||
|
||||
// API is used to build api server
|
||||
type API struct {
|
||||
config Config
|
||||
handler http.Handler
|
||||
func startRPC(errCh chan error) {
|
||||
defer close(errCh)
|
||||
|
||||
rpcHandler := RPCHandler()
|
||||
var err error
|
||||
// Minio server config
|
||||
httpServer := &http.Server{
|
||||
Addr: "127.0.0.1:9001",
|
||||
Handler: rpcHandler,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
err = httpServer.ListenAndServe()
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
}
|
||||
errCh <- nil
|
||||
return
|
||||
}
|
||||
|
||||
// StartServer APIFactory builds api server
|
||||
func StartServer(conf Config) error {
|
||||
for err := range Start(New(conf)) {
|
||||
// StartServices starts basic services for a server
|
||||
func StartServices(conf api.Config) error {
|
||||
apiErrCh := make(chan error)
|
||||
rpcErrCh := make(chan error)
|
||||
|
||||
go startAPI(apiErrCh, conf)
|
||||
go startRPC(rpcErrCh)
|
||||
|
||||
select {
|
||||
case err := <-apiErrCh:
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case err := <-rpcErrCh:
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
Loading…
Reference in New Issue