Example #1
0
File: ls.go Project: bosky101/mc
// doList - list all entities inside a folder
func doList(clnt client.Client, recursive bool) error {
	var err error
	for contentCh := range clnt.List(recursive) {
		if contentCh.Err != nil {
			switch err := iodine.ToError(contentCh.Err).(type) {
			// handle this specifically for filesystem
			case client.ISBrokenSymlink:
				console.Errors(ErrorMessage{
					Message: "Failed with",
					Error:   iodine.New(err, nil),
				})
				continue
			}
			if os.IsNotExist(iodine.ToError(contentCh.Err)) || os.IsPermission(iodine.ToError(contentCh.Err)) {
				console.Errors(ErrorMessage{
					Message: "Failed with",
					Error:   iodine.New(contentCh.Err, nil),
				})
				continue
			}
			err = contentCh.Err
			break
		}
		console.Prints(parseContent(contentCh.Content))
	}
	if err != nil {
		return iodine.New(err, map[string]string{"Target": clnt.URL().String()})
	}
	return nil
}
Example #2
0
// PutBucketACLHandler - PUT Bucket ACL
// ----------
// This implementation of the PUT operation modifies the bucketACL for authenticated request
func (api Minio) PutBucketACLHandler(w http.ResponseWriter, req *http.Request) {
	// Ticket master block
	{
		op := Operation{}
		op.ProceedCh = make(chan struct{})
		api.OP <- op
		// block until Ticket master gives us a go
		<-op.ProceedCh
	}

	acceptsContentType := getContentType(req)

	// read from 'x-amz-acl'
	aclType := getACLType(req)
	if aclType == unsupportedACLType {
		writeErrorResponse(w, req, NotImplemented, acceptsContentType, req.URL.Path)
		return
	}

	vars := mux.Vars(req)
	bucket := vars["bucket"]

	err := api.Donut.SetBucketMetadata(bucket, map[string]string{"acl": getACLTypeString(aclType)})
	switch iodine.ToError(err).(type) {
	case nil:
		writeSuccessResponse(w, acceptsContentType)
	case donut.BucketNameInvalid:
		writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path)
	case donut.BucketNotFound:
		writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path)
	default:
		log.Error.Println(iodine.New(err, nil))
		writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
	}
}
Example #3
0
// ListBucketsHandler - GET Service
// -----------
// This implementation of the GET operation returns a list of all buckets
// owned by the authenticated sender of the request.
func (api Minio) ListBucketsHandler(w http.ResponseWriter, req *http.Request) {
	// Ticket master block
	{
		op := Operation{}
		op.ProceedCh = make(chan struct{})
		api.OP <- op
		// block until Ticket master gives us a go
		<-op.ProceedCh
	}

	acceptsContentType := getContentType(req)
	// uncomment this when we have webcli
	// without access key credentials one cannot list buckets
	// if _, err := stripAuth(req); err != nil {
	//	writeErrorResponse(w, req, AccessDenied, acceptsContentType, req.URL.Path)
	//	return
	// }

	buckets, err := api.Donut.ListBuckets()
	switch iodine.ToError(err).(type) {
	case nil:
		// generate response
		response := generateListBucketsResponse(buckets)
		encodedSuccessResponse := encodeSuccessResponse(response, acceptsContentType)
		// write headers
		setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse))
		// write response
		w.Write(encodedSuccessResponse)
	default:
		log.Error.Println(iodine.New(err, nil))
		writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
	}
}
Example #4
0
func doCatCmd(sourceURL string) (string, error) {
	sourceClnt, err := source2Client(sourceURL)
	if err != nil {
		return "Unable to create client: " + sourceURL, iodine.New(err, nil)
	}
	reader, size, err := sourceClnt.GetObject(0, 0)
	if err != nil {
		return "Unable to retrieve file: " + sourceURL, iodine.New(err, nil)
	}
	defer reader.Close()
	_, err = io.CopyN(os.Stdout, reader, int64(size))
	if err != nil {
		switch e := iodine.ToError(err).(type) {
		case *os.PathError:
			if e.Err == syscall.EPIPE {
				// stdout closed by the user. Gracefully exit.
				return "", nil
			}
			return "Writing data to stdout failed, unexpected problem.. please report this error", iodine.New(err, nil)
		default:
			return "Reading data from source failed: " + sourceURL, iodine.New(err, nil)
		}
	}
	return "", nil
}
Example #5
0
// 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) {
	acceptsContentType := getContentType(req)

	resources := getBucketMultipartResources(req.URL.Query())
	if resources.MaxUploads == 0 {
		resources.MaxUploads = maxObjectList
	}

	vars := mux.Vars(req)
	bucket := vars["bucket"]

	resources, err := server.driver.ListMultipartUploads(bucket, resources)
	switch iodine.ToError(err).(type) {
	case nil: // success
		{
			// generate response
			response := generateListMultipartUploadsResult(bucket, resources)
			encodedSuccessResponse := encodeSuccessResponse(response, acceptsContentType)
			// write headers
			setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse))
			// write body
			w.Write(encodedSuccessResponse)
		}
	case drivers.BucketNotFound:
		{
			writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path)
		}
	default:
		{
			log.Error.Println(iodine.New(err, nil))
			writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
		}
	}

}
Example #6
0
// 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) {
	acceptsContentType := getContentType(req)

	vars := mux.Vars(req)
	bucket := vars["bucket"]

	_, err := server.driver.GetBucketMetadata(bucket)
	switch iodine.ToError(err).(type) {
	case nil:
		{
			writeSuccessResponse(w, acceptsContentType)
		}
	case drivers.BucketNotFound:
		{
			error := getErrorCode(NoSuchBucket)
			w.WriteHeader(error.HTTPStatusCode)
		}
	case drivers.BucketNameInvalid:
		{
			error := getErrorCode(InvalidBucketName)
			w.WriteHeader(error.HTTPStatusCode)
		}
	default:
		{
			log.Error.Println(iodine.New(err, nil))
			error := getErrorCode(InternalError)
			w.WriteHeader(error.HTTPStatusCode)
		}
	}
}
Example #7
0
// 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) {
	acceptsContentType := getContentType(req)
	// read from 'x-amz-acl'
	aclType := getACLType(req)
	if aclType == unsupportedACLType {
		writeErrorResponse(w, req, NotImplemented, acceptsContentType, req.URL.Path)
		return
	}

	vars := mux.Vars(req)
	bucket := vars["bucket"]
	err := server.driver.SetBucketMetadata(bucket, getACLTypeString(aclType))
	switch iodine.ToError(err).(type) {
	case nil:
		{
			writeSuccessResponse(w, acceptsContentType)
		}
	case drivers.BucketNameInvalid:
		{
			writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path)
		}
	case drivers.BucketNotFound:
		{
			writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path)
		}
	default:
		{
			log.Error.Println(iodine.New(err, nil))
			writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
		}
	}
}
Example #8
0
// 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 (api Minio) HeadBucketHandler(w http.ResponseWriter, req *http.Request) {
	// Ticket master block
	{
		op := Operation{}
		op.ProceedCh = make(chan struct{})
		api.OP <- op
		// block until Ticket master gives us a go
		<-op.ProceedCh
	}

	acceptsContentType := getContentType(req)

	vars := mux.Vars(req)
	bucket := vars["bucket"]

	_, err := api.Donut.GetBucketMetadata(bucket)
	switch iodine.ToError(err).(type) {
	case nil:
		writeSuccessResponse(w, acceptsContentType)
	case donut.BucketNotFound:
		error := getErrorCode(NoSuchBucket)
		w.WriteHeader(error.HTTPStatusCode)
	case donut.BucketNameInvalid:
		error := getErrorCode(InvalidBucketName)
		w.WriteHeader(error.HTTPStatusCode)
	default:
		log.Error.Println(iodine.New(err, nil))
		error := getErrorCode(InternalError)
		w.WriteHeader(error.HTTPStatusCode)
	}
}
Example #9
0
func (s *MySuite) TestInvalidTcpAddr(c *C) {
	os.Setenv(envCountKey, "")
	n := &minNet{}
	_, err := n.Listen("tcp", "abc")
	c.Assert(err, Not(IsNil))
	c.Assert(regexp.MustCompile("^missing port in address abc$").MatchString(iodine.ToError(err).Error()), Equals, true)
}
Example #10
0
// runListCmd - is a handler for mc ls command
func runListCmd(ctx *cli.Context) {
	args := ctx.Args()
	if globalAliasFlag {
		if !ctx.Args().Present() {
			args = []string{"."}
		}
	} else if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "ls", 1) // last argument is exit code
	}

	config := mustGetMcConfig()
	for _, arg := range args {
		targetURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		// if recursive strip off the "..."
		newTargetURL := stripRecursiveURL(targetURL)
		err = doListCmd(newTargetURL, isURLRecursive(targetURL))
		if err != nil {
			console.Fatalf("Failed to list : %s. %s\n", targetURL, err)
		}
	}
}
Example #11
0
func runCatCmd(ctx *cli.Context) {
	if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "cat", 1) // last argument is exit code
	}
	if !isMcConfigExists() {
		console.Fatalf("Please run \"mc config generate\". %s\n", errNotConfigured{})
	}
	config := mustGetMcConfig()
	// Convert arguments to URLs: expand alias, fix format...
	for _, arg := range ctx.Args() {
		sourceURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		errorMsg, err := doCatCmd(sourceURL)
		if err != nil {
			console.Fatalln(errorMsg)
		}
	}
}
Example #12
0
// runMakeBucketCmd is the handler for mc mb command
func runMakeBucketCmd(ctx *cli.Context) {
	if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "mb", 1) // last argument is exit code
	}
	if !isMcConfigExists() {
		console.Fatalf("Please run \"mc config generate\". %s\n", errNotConfigured{})
	}
	config := mustGetMcConfig()
	for _, arg := range ctx.Args() {
		targetURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		msg, err := doMakeBucketCmd(targetURL)
		if err != nil {
			console.Fatalln(msg)
		}
		console.Infoln(msg)
	}
}
Example #13
0
// AbortMultipartUploadHandler - Abort multipart upload
func (api Minio) AbortMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
	// Ticket master block
	{
		op := Operation{}
		op.ProceedCh = make(chan struct{})
		api.OP <- op
		// block until Ticket master gives us a go
		<-op.ProceedCh
	}

	acceptsContentType := getContentType(req)
	if !api.isValidOp(w, req, acceptsContentType) {
		return
	}

	vars := mux.Vars(req)
	bucket := vars["bucket"]
	object := vars["object"]

	objectResourcesMetadata := getObjectResources(req.URL.Query())

	err := api.Donut.AbortMultipartUpload(bucket, object, objectResourcesMetadata.UploadID)
	switch iodine.ToError(err).(type) {
	case nil:
		setCommonHeaders(w, getContentTypeString(acceptsContentType), 0)
		w.WriteHeader(http.StatusNoContent)
	case donut.InvalidUploadID:
		writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path)
	default:
		log.Error.Println(iodine.New(err, nil))
		writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
	}
}
Example #14
0
// 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) {
	acceptsContentType := getContentType(req)
	// uncomment this when we have webcli
	// without access key credentials one cannot list buckets
	// if _, err := stripAuth(req); err != nil {
	//	writeErrorResponse(w, req, AccessDenied, acceptsContentType, req.URL.Path)
	//	return
	// }
	buckets, err := server.driver.ListBuckets()
	switch iodine.ToError(err).(type) {
	case nil:
		{
			// generate response
			response := generateListBucketsResponse(buckets)
			encodedSuccessResponse := encodeSuccessResponse(response, acceptsContentType)
			// write headers
			setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse))
			// write response
			w.Write(encodedSuccessResponse)
		}
	default:
		{
			log.Error.Println(iodine.New(err, nil))
			writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
		}
	}
}
Example #15
0
func (s *MySuite) TestInvalidNetwork(c *C) {
	os.Setenv(envCountKey, "")
	n := &minNet{}
	_, err := n.Listen("foo", "")
	c.Assert(err, Not(IsNil))
	c.Assert(regexp.MustCompile("^unknown network foo$").MatchString(iodine.ToError(err).Error()), Equals, true)
}
Example #16
0
func doCatCmd(sourceURL string) (string, error) {
	sourceClnt, err := source2Client(sourceURL)
	if err != nil {
		return "Unable to create client: " + sourceURL, NewIodine(iodine.New(err, nil))
	}
	// ignore size, since os.Stat() would not return proper size all the time for local filesystem
	// for example /proc files.
	reader, _, err := sourceClnt.GetObject(0, 0)
	if err != nil {
		return "Unable to retrieve file: " + sourceURL, NewIodine(iodine.New(err, nil))
	}
	defer reader.Close()
	// read till EOF
	_, err = io.Copy(os.Stdout, reader)
	if err != nil {
		switch e := iodine.ToError(err).(type) {
		case *os.PathError:
			if e.Err == syscall.EPIPE {
				// stdout closed by the user. Gracefully exit.
				return "", nil
			}
			return "Writing data to stdout failed, unexpected problem.. please report this error", iodine.New(err, nil)
		default:
			return "Reading data from source failed: " + sourceURL, NewIodine(iodine.New(err, nil))
		}
	}
	return "", nil
}
Example #17
0
// Abort multipart upload
func (server *minioAPI) abortMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
	acceptsContentType := getContentType(req)
	// handle ACL's here at bucket level
	if !server.isValidOp(w, req, acceptsContentType) {
		return
	}

	vars := mux.Vars(req)
	bucket := vars["bucket"]
	object := vars["object"]

	objectResourcesMetadata := getObjectResources(req.URL.Query())

	err := server.driver.AbortMultipartUpload(bucket, object, objectResourcesMetadata.UploadID)
	switch iodine.ToError(err).(type) {
	case nil:
		{
			setCommonHeaders(w, getContentTypeString(acceptsContentType), 0)
			w.WriteHeader(http.StatusNoContent)
		}
	case drivers.InvalidUploadID:
		{
			writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path)
		}
	default:
		{
			log.Error.Println(iodine.New(err, nil))
			writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
		}
	}
}
Example #18
0
func runAccessCmd(ctx *cli.Context) {
	if !ctx.Args().Present() || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "access", 1) // last argument is exit code
	}
	config := mustGetMcConfig()
	acl := bucketACL(ctx.Args().First())
	if !acl.isValidBucketACL() {
		console.Fatalf("Valid types are [private, public, readonly]. %s\n", errInvalidACL{acl: acl.String()})
	}
	for _, arg := range ctx.Args().Tail() {
		targetURL, err := getExpandedURL(arg, config.Aliases)
		if err != nil {
			switch e := iodine.ToError(err).(type) {
			case errUnsupportedScheme:
				console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
			default:
				console.Fatalf("Unable to parse argument %s. %s\n", arg, err)
			}
		}
		msg, err := doUpdateAccessCmd(targetURL, acl)
		if err != nil {
			console.Fatalln(msg)
		}
		console.Infoln(msg)
	}
}
Example #19
0
// doConfig is the handler for "mc config" sub-command.
func doConfig(arg string, aliases []string) (string, error) {
	configPath, err := getMcConfigPath()
	if err != nil {
		return "Unable to determine config file path.", NewIodine(iodine.New(err, nil))
	}
	err = saveConfig(arg, aliases)
	if err != nil {
		switch iodine.ToError(err).(type) {
		case errConfigExists:
			return "Configuration file [" + configPath + "]", NewIodine(iodine.New(err, nil))
		case errInvalidArgument:
			return "Incorrect usage, please use \"mc config help\" ", NewIodine(iodine.New(err, nil))
		case errAliasExists:
			return "Alias name: [" + aliases[0] + "]", NewIodine(iodine.New(err, nil))
		case errInvalidAliasName:
			return "Alias [" + aliases[0] + "] is reserved word or invalid", NewIodine(iodine.New(err, nil))
		case errInvalidURL:
			return "Alias [" + aliases[1] + "] is invalid URL", NewIodine(iodine.New(err, nil))
		default:
			// unexpected error
			return "Unable to modify config file [" + configPath + "].", NewIodine(iodine.New(err, nil))
		}
	}
	if arg == "alias" {
		return "Alias written to [" + configPath + "].", nil
	}
	return "", NewIodine(iodine.New(errUnexpected{}, nil))
}
Example #20
0
// GetObjectHandler - GET Object
// ----------
// This implementation of the GET operation retrieves object. To use GET,
// you must have READ access to the object.
func (api Minio) GetObjectHandler(w http.ResponseWriter, req *http.Request) {
	// ticket master block
	{
		op := Operation{}
		op.ProceedCh = make(chan struct{})
		api.OP <- op
		// block until Ticket master gives us a go
		<-op.ProceedCh
	}

	acceptsContentType := getContentType(req)
	if !api.isValidOp(w, req, acceptsContentType) {
		return
	}

	var object, bucket string
	vars := mux.Vars(req)
	bucket = vars["bucket"]
	object = vars["object"]

	metadata, err := api.Donut.GetObjectMetadata(bucket, object)
	switch iodine.ToError(err).(type) {
	case nil: // success
		{
			httpRange, err := getRequestedRange(req, metadata.Size)
			if err != nil {
				writeErrorResponse(w, req, InvalidRange, acceptsContentType, req.URL.Path)
				return
			}
			switch httpRange.start == 0 && httpRange.length == 0 {
			case true:
				setObjectHeaders(w, metadata)
				if _, err := api.Donut.GetObject(w, bucket, object); err != nil {
					// unable to write headers, we've already printed data. Just close the connection.
					log.Error.Println(iodine.New(err, nil))
				}
			case false:
				metadata.Size = httpRange.length
				setRangeObjectHeaders(w, metadata, httpRange)
				w.WriteHeader(http.StatusPartialContent)
				if _, err := api.Donut.GetPartialObject(w, bucket, object, httpRange.start, httpRange.length); err != nil {
					// unable to write headers, we've already printed data. Just close the connection.
					log.Error.Println(iodine.New(err, nil))
				}
			}
		}
	case donut.BucketNameInvalid:
		writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path)
	case donut.BucketNotFound:
		writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path)
	case donut.ObjectNotFound:
		writeErrorResponse(w, req, NoSuchKey, acceptsContentType, req.URL.Path)
	case donut.ObjectNameInvalid:
		writeErrorResponse(w, req, NoSuchKey, acceptsContentType, req.URL.Path)
	default:
		log.Error.Println(iodine.New(err, nil))
		writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
	}
}
Example #21
0
// 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 (api Minio) ListMultipartUploadsHandler(w http.ResponseWriter, req *http.Request) {
	// Ticket master block
	{
		op := Operation{}
		op.ProceedCh = make(chan struct{})
		api.OP <- op
		// block until ticket master gives us a go
		<-op.ProceedCh
	}

	acceptsContentType := getContentType(req)
	if !api.isValidOp(w, req, acceptsContentType) {
		return
	}

	resources := getBucketMultipartResources(req.URL.Query())
	if resources.MaxUploads < 0 {
		writeErrorResponse(w, req, InvalidMaxUploads, acceptsContentType, req.URL.Path)
		return
	}
	if resources.MaxUploads == 0 {
		resources.MaxUploads = maxObjectList
	}

	vars := mux.Vars(req)
	bucket := vars["bucket"]

	var signature *donut.Signature
	if _, ok := req.Header["Authorization"]; ok {
		// Init signature V4 verification
		var err error
		signature, err = InitSignatureV4(req)
		if err != nil {
			writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
			return
		}
	}

	resources, err := api.Donut.ListMultipartUploads(bucket, resources, signature)
	switch iodine.ToError(err).(type) {
	case nil: // success
		{
			// generate response
			response := generateListMultipartUploadsResponse(bucket, resources)
			encodedSuccessResponse := encodeSuccessResponse(response, acceptsContentType)
			// write headers
			setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse))
			// write body
			w.Write(encodedSuccessResponse)
		}
	case donut.SignatureDoesNotMatch:
		writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
	case donut.BucketNotFound:
		writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path)
	default:
		log.Error.Println(iodine.New(err, nil))
		writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
	}
}
Example #22
0
// CompleteMultipartUploadHandler - Complete multipart upload
func (api Minio) CompleteMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
	// Ticket master block
	{
		op := Operation{}
		op.ProceedCh = make(chan struct{})
		api.OP <- op
		// block until Ticket master gives us a go
		<-op.ProceedCh
	}

	acceptsContentType := getContentType(req)
	if !api.isValidOp(w, req, acceptsContentType) {
		return
	}

	vars := mux.Vars(req)
	bucket := vars["bucket"]
	object := vars["object"]

	objectResourcesMetadata := getObjectResources(req.URL.Query())

	var signature *donut.Signature
	if _, ok := req.Header["Authorization"]; ok {
		// Init signature V4 verification
		var err error
		signature, err = InitSignatureV4(req)
		if err != nil {
			writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
			return
		}
	}
	metadata, err := api.Donut.CompleteMultipartUpload(bucket, object, objectResourcesMetadata.UploadID, req.Body, signature)
	switch iodine.ToError(err).(type) {
	case nil:
		{
			response := generateCompleteMultpartUploadResponse(bucket, object, "", metadata.MD5Sum)
			encodedSuccessResponse := encodeSuccessResponse(response, acceptsContentType)
			// write headers
			setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse))
			// write body
			w.Write(encodedSuccessResponse)
		}
	case donut.InvalidUploadID:
		writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path)
	case donut.InvalidPartOrder:
		writeErrorResponse(w, req, InvalidPartOrder, acceptsContentType, req.URL.Path)
	case donut.MissingDateHeader:
		writeErrorResponse(w, req, RequestTimeTooSkewed, acceptsContentType, req.URL.Path)
	case donut.SignatureDoesNotMatch:
		writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
	case donut.IncompleteBody:
		writeErrorResponse(w, req, IncompleteBody, acceptsContentType, req.URL.Path)
	case donut.MalformedXML:
		writeErrorResponse(w, req, MalformedXML, acceptsContentType, req.URL.Path)
	default:
		log.Error.Println(iodine.New(err, nil))
		writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
	}
}
Example #23
0
func (s *MySuite) TestInvalidCountEnvVariable(c *C) {
	os.Setenv(envCountKey, "a")
	n := &minNet{}
	expected := regexp.MustCompile("^found invalid count value: LISTEN_FDS=a$")
	err := n.getInheritedListeners()
	c.Assert(err, Not(IsNil))
	c.Assert(expected.MatchString(iodine.ToError(err).Error()), Equals, true)
}
Example #24
0
func (s *MySuite) TestInheritErrorOnListenTCPWithInvalidCount(c *C) {
	os.Setenv(envCountKey, "a")
	n := &minNet{}
	expected := regexp.MustCompile("^found invalid count value: LISTEN_FDS=a$")
	_, err := n.Listen("tcp", ":0")
	c.Assert(err, Not(IsNil))
	c.Assert(expected.MatchString(iodine.ToError(err).Error()), Equals, true)
}
Example #25
0
// CompleteMultipartUploadHandler - Complete multipart upload
func (api Minio) CompleteMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
	// Ticket master block
	{
		op := Operation{}
		op.ProceedCh = make(chan struct{})
		api.OP <- op
		// block until Ticket master gives us a go
		<-op.ProceedCh
	}

	acceptsContentType := getContentType(req)
	if !api.isValidOp(w, req, acceptsContentType) {
		return
	}

	decoder := xml.NewDecoder(req.Body)
	parts := &CompleteMultipartUpload{}
	err := decoder.Decode(parts)
	if err != nil {
		log.Error.Println(iodine.New(err, nil))
		writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
		return
	}
	if !sort.IsSorted(completedParts(parts.Part)) {
		writeErrorResponse(w, req, InvalidPartOrder, acceptsContentType, req.URL.Path)
		return
	}

	vars := mux.Vars(req)
	bucket := vars["bucket"]
	object := vars["object"]

	objectResourcesMetadata := getObjectResources(req.URL.Query())

	partMap := make(map[int]string)
	for _, part := range parts.Part {
		partMap[part.PartNumber] = part.ETag
	}

	metadata, err := api.Donut.CompleteMultipartUpload(bucket, object, objectResourcesMetadata.UploadID, partMap)
	switch iodine.ToError(err).(type) {
	case nil:
		{
			response := generateCompleteMultpartUploadResult(bucket, object, "", metadata.MD5Sum)
			encodedSuccessResponse := encodeSuccessResponse(response, acceptsContentType)
			// write headers
			setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse))
			// write body
			w.Write(encodedSuccessResponse)
		}
	case donut.InvalidUploadID:
		writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path)
	default:
		log.Error.Println(iodine.New(err, nil))
		writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
	}
}
Example #26
0
// NewMultipartUploadHandler - New multipart upload
func (api Minio) NewMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
	// Ticket master block
	{
		op := Operation{}
		op.ProceedCh = make(chan struct{})
		api.OP <- op
		// block until Ticket master gives us a go
		<-op.ProceedCh
	}

	acceptsContentType := getContentType(req)
	if !api.isValidOp(w, req, acceptsContentType) {
		return
	}

	if !isRequestUploads(req.URL.Query()) {
		writeErrorResponse(w, req, MethodNotAllowed, acceptsContentType, req.URL.Path)
		return
	}

	var object, bucket string
	vars := mux.Vars(req)
	bucket = vars["bucket"]
	object = vars["object"]

	var signature *donut.Signature
	if _, ok := req.Header["Authorization"]; ok {
		// Init signature V4 verification
		var err error
		signature, err = InitSignatureV4(req)
		if err != nil {
			writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
			return
		}
	}

	uploadID, err := api.Donut.NewMultipartUpload(bucket, object, req.Header.Get("Content-Type"), signature)
	switch iodine.ToError(err).(type) {
	case nil:
		{
			response := generateInitiateMultipartUploadResponse(bucket, object, uploadID)
			encodedSuccessResponse := encodeSuccessResponse(response, acceptsContentType)
			// write headers
			setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse))
			// write body
			w.Write(encodedSuccessResponse)
		}
	case donut.SignatureDoesNotMatch:
		writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
	case donut.ObjectExists:
		writeErrorResponse(w, req, MethodNotAllowed, acceptsContentType, req.URL.Path)
	default:
		log.Error.Println(iodine.New(err, nil))
		writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
	}
}
Example #27
0
func testGetDirectoryReturnsObjectNotFound(c *check.C, create func() Driver) {
	drivers := create()
	err := drivers.CreateBucket("bucket", "")
	c.Assert(err, check.IsNil)

	_, err = drivers.CreateObject("bucket", "dir1/dir2/object", "", "", int64(len("hello world")),
		bytes.NewBufferString("hello world"))
	c.Assert(err, check.IsNil)

	var byteBuffer bytes.Buffer
	length, err := drivers.GetObject(&byteBuffer, "bucket", "dir1")
	c.Assert(length, check.Equals, int64(0))
	switch err := iodine.ToError(err).(type) {
	case ObjectNotFound:
		{
			c.Assert(err.Bucket, check.Equals, "bucket")
			c.Assert(err.Object, check.Equals, "dir1")
		}
	default:
		{
			// force a failure with a line number
			c.Assert(err, check.Equals, "ObjectNotFound")
		}
	}
	c.Assert(len(byteBuffer.Bytes()), check.Equals, 0)

	var byteBuffer2 bytes.Buffer
	length, err = drivers.GetObject(&byteBuffer, "bucket", "dir1/")
	c.Assert(length, check.Equals, int64(0))
	switch err := iodine.ToError(err).(type) {
	case ObjectNotFound:
		{
			c.Assert(err.Bucket, check.Equals, "bucket")
			c.Assert(err.Object, check.Equals, "dir1/")
		}
	default:
		{
			// force a failure with a line number
			c.Assert(err, check.Equals, "ObjectNotFound")
		}
	}
	c.Assert(len(byteBuffer2.Bytes()), check.Equals, 0)
}
Example #28
0
// runDiffCmd - is a handler for mc diff command
func runDiffCmd(ctx *cli.Context) {
	if len(ctx.Args()) != 2 || ctx.Args().First() == "help" {
		cli.ShowCommandHelpAndExit(ctx, "diff", 1) // last argument is exit code
	}
	if !isMcConfigExists() {
		console.Fatalf("Please run \"mc config generate\". %s\n", errNotConfigured{})
	}

	config := mustGetMcConfig()
	firstURL := ctx.Args().First()
	secondURL := ctx.Args()[1]

	var err error
	firstURL, err = getExpandedURL(firstURL, config.Aliases)
	if err != nil {
		switch e := iodine.ToError(err).(type) {
		case errUnsupportedScheme:
			console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
		default:
			console.Fatalf("Unable to parse argument %s. %s\n", firstURL, err)
		}
	}
	secondURL, err = getExpandedURL(secondURL, config.Aliases)
	if err != nil {
		switch e := iodine.ToError(err).(type) {
		case errUnsupportedScheme:
			console.Fatalf("Unknown type of URL %s. %s\n", e.url, err)
		default:
			console.Fatalf("Unable to parse argument %s. %s\n", secondURL, err)
		}
	}
	if isURLRecursive(secondURL) {
		console.Fatalf("Second URL cannot be recursive. %s\n", errInvalidArgument{})
	}
	newFirstURL := stripRecursiveURL(firstURL)
	for diff := range doDiffCmd(newFirstURL, secondURL, isURLRecursive(firstURL)) {
		if diff.err != nil {
			console.Fatalln(diff.message)
		}
		console.Infoln(diff.message)
	}
}
Example #29
0
// 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) {
	acceptsContentType := getContentType(req)
	// verify if this operation is allowed
	if !server.isValidOp(w, req, acceptsContentType) {
		return
	}

	var object, bucket string
	vars := mux.Vars(req)
	bucket = vars["bucket"]
	object = vars["object"]

	metadata, err := server.driver.GetObjectMetadata(bucket, object)
	switch iodine.ToError(err).(type) {
	case nil: // success
		{
			httpRange, err := getRequestedRange(req, metadata.Size)
			if err != nil {
				writeErrorResponse(w, req, InvalidRange, acceptsContentType, req.URL.Path)
				return
			}
			switch httpRange.start == 0 && httpRange.length == 0 {
			case true:
				setObjectHeaders(w, metadata)
				if _, err := server.driver.GetObject(w, bucket, object); err != nil {
					// unable to write headers, we've already printed data. Just close the connection.
					log.Error.Println(iodine.New(err, nil))
				}
			case false:
				metadata.Size = httpRange.length
				setRangeObjectHeaders(w, metadata, httpRange)
				w.WriteHeader(http.StatusPartialContent)
				if _, err := server.driver.GetPartialObject(w, bucket, object, httpRange.start, httpRange.length); err != nil {
					// unable to write headers, we've already printed data. Just close the connection.
					log.Error.Println(iodine.New(err, nil))
				}
			}
		}
	case drivers.ObjectNotFound:
		{
			writeErrorResponse(w, req, NoSuchKey, acceptsContentType, req.URL.Path)
		}
	case drivers.ObjectNameInvalid:
		{
			writeErrorResponse(w, req, NoSuchKey, acceptsContentType, req.URL.Path)
		}
	default:
		{
			log.Error.Println(iodine.New(err, nil))
			writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
		}
	}
}
Example #30
0
// Complete multipart upload
func (server *minioAPI) completeMultipartUploadHandler(w http.ResponseWriter, req *http.Request) {
	acceptsContentType := getContentType(req)
	// handle ACL's here at bucket level
	if !server.isValidOp(w, req, acceptsContentType) {
		return
	}

	decoder := xml.NewDecoder(req.Body)
	parts := &CompleteMultipartUpload{}
	err := decoder.Decode(parts)
	if err != nil {
		log.Error.Println(iodine.New(err, nil))
		writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
		return
	}
	if !sort.IsSorted(completedParts(parts.Part)) {
		writeErrorResponse(w, req, InvalidPartOrder, acceptsContentType, req.URL.Path)
		return
	}

	vars := mux.Vars(req)
	bucket := vars["bucket"]
	object := vars["object"]
	objectResourcesMetadata := getObjectResources(req.URL.Query())

	partMap := make(map[int]string)
	for _, part := range parts.Part {
		partMap[part.PartNumber] = part.ETag
	}

	etag, err := server.driver.CompleteMultipartUpload(bucket, object, objectResourcesMetadata.UploadID, partMap)
	switch iodine.ToError(err).(type) {
	case nil:
		{
			response := generateCompleteMultpartUploadResult(bucket, object, "", etag)
			encodedSuccessResponse := encodeSuccessResponse(response, acceptsContentType)
			// write headers
			setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse))
			// write body
			w.Write(encodedSuccessResponse)
		}
	case drivers.InvalidUploadID:
		{
			writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path)
		}
	default:
		{
			log.Error.Println(iodine.New(err, nil))
			writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
		}
	}
}