Restructure API handlers, add JSON RPC simple HelloService right now.

This commit is contained in:
Harshavardhana 2015-06-30 20:15:48 -07:00
parent 335c7827eb
commit 4addf7a996
24 changed files with 273 additions and 294 deletions

View File

@ -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
View File

@ -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 {

View File

@ -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}
}

View File

@ -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))
}

View File

@ -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)

View File

@ -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

View File

@ -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}
}

View File

@ -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}
}

View File

@ -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)
}

View File

@ -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),

77
pkg/server/router.go Normal file
View File

@ -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())
}

38
pkg/server/rpc/methods.go Normal file
View File

@ -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
}

30
pkg/server/rpc/server.go Normal file
View File

@ -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
}

View File

@ -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
}