diff --git a/cmd/bucket-handlers.go b/cmd/bucket-handlers.go index eda75d76e..37757c46a 100644 --- a/cmd/bucket-handlers.go +++ b/cmd/bucket-handlers.go @@ -20,6 +20,7 @@ import ( "encoding/base64" "encoding/xml" "io" + "net" "net/http" "net/url" "path" @@ -322,6 +323,13 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, // Write success response. writeSuccessResponseXML(w, encodedSuccessResponse) + // Get host and port from Request.RemoteAddr failing which + // fill them with empty strings. + host, port, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + host, port = "", "" + } + // Notify deleted event for objects. for _, dobj := range deletedObjects { eventNotify(eventData{ @@ -331,6 +339,9 @@ func (api objectAPIHandlers) DeleteMultipleObjectsHandler(w http.ResponseWriter, Name: dobj.ObjectName, }, ReqParams: extractReqParams(r), + UserAgent: r.UserAgent(), + Host: host, + Port: port, }) } } @@ -520,12 +531,21 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h w.Header().Set("ETag", `"`+objInfo.MD5Sum+`"`) w.Header().Set("Location", getObjectLocation(bucket, object)) + // Get host and port from Request.RemoteAddr. + host, port, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + host, port = "", "" + } + // Notify object created event. defer eventNotify(eventData{ Type: ObjectCreatedPost, Bucket: objInfo.Bucket, ObjInfo: objInfo, ReqParams: extractReqParams(r), + UserAgent: r.UserAgent(), + Host: host, + Port: port, }) if successRedirect != "" { diff --git a/cmd/bucket-notification-datatypes.go b/cmd/bucket-notification-datatypes.go index d9a888778..7f7aec6e6 100644 --- a/cmd/bucket-notification-datatypes.go +++ b/cmd/bucket-notification-datatypes.go @@ -176,6 +176,14 @@ const ( eventVersion = "2.0" ) +// sourceInfo represents information on the client that triggered the +// event notification. +type sourceInfo struct { + Host string `json:"host"` + Port string `json:"port"` + UserAgent string `json:"userAgent"` +} + // NotificationEvent represents an Amazon an S3 bucket notification event. type NotificationEvent struct { EventVersion string `json:"eventVersion"` @@ -187,6 +195,7 @@ type NotificationEvent struct { RequestParameters map[string]string `json:"requestParameters"` ResponseElements map[string]string `json:"responseElements"` S3 eventMeta `json:"s3"` + Source sourceInfo `json:"source"` } // Represents the minio sqs type and account id's. diff --git a/cmd/event-notifier.go b/cmd/event-notifier.go index 0ecf54b2f..687748c1a 100644 --- a/cmd/event-notifier.go +++ b/cmd/event-notifier.go @@ -29,6 +29,10 @@ import ( "github.com/Sirupsen/logrus" ) +const ( + minioEventSource = "minio:s3" +) + type externalNotifier struct { // Per-bucket notification config. This is updated via // PutBucketNotification API. @@ -82,6 +86,9 @@ type eventData struct { Bucket string ObjInfo ObjectInfo ReqParams map[string]string + Host string + Port string + UserAgent string } // New notification event constructs a new notification event message from @@ -114,7 +121,7 @@ func newNotificationEvent(event eventData) NotificationEvent { // http://docs.aws.amazon.com/AmazonS3/latest/dev/notification-content-structure.html nEvent := NotificationEvent{ EventVersion: eventVersion, - EventSource: eventSource, + EventSource: minioEventSource, AwsRegion: region, EventTime: eventTime.Format(timeFormatAMZ), EventName: event.Type.String(), @@ -135,6 +142,11 @@ func newNotificationEvent(event eventData) NotificationEvent { ARN: bucketARNPrefix + event.Bucket, }, }, + Source: sourceInfo{ + Host: event.Host, + Port: event.Port, + UserAgent: event.UserAgent, + }, } // Escape the object name. For example "red flower.jpg" becomes "red+flower.jpg". diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 062512598..e33fe680b 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -20,6 +20,7 @@ import ( "encoding/hex" "encoding/xml" "io/ioutil" + "net" "net/http" "net/url" "path" @@ -372,12 +373,21 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re // Write success response. writeSuccessResponseXML(w, encodedSuccessResponse) + // Get host and port from Request.RemoteAddr. + host, port, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + host, port = "", "" + } + // Notify object created event. eventNotify(eventData{ Type: ObjectCreatedCopy, Bucket: dstBucket, ObjInfo: objInfo, ReqParams: extractReqParams(r), + UserAgent: r.UserAgent(), + Host: host, + Port: port, }) } @@ -503,12 +513,21 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req w.Header().Set("ETag", "\""+objInfo.MD5Sum+"\"") writeSuccessResponseHeadersOnly(w) + // Get host and port from Request.RemoteAddr. + host, port, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + host, port = "", "" + } + // Notify object created event. eventNotify(eventData{ Type: ObjectCreatedPut, Bucket: bucket, ObjInfo: objInfo, ReqParams: extractReqParams(r), + UserAgent: r.UserAgent(), + Host: host, + Port: port, }) } @@ -930,12 +949,21 @@ func (api objectAPIHandlers) CompleteMultipartUploadHandler(w http.ResponseWrite // Write success response. writeSuccessResponseXML(w, encodedSuccessResponse) + // Get host and port from Request.RemoteAddr. + host, port, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + host, port = "", "" + } + // Notify object created event. eventNotify(eventData{ Type: ObjectCreatedCompleteMultipartUpload, Bucket: bucket, ObjInfo: objInfo, ReqParams: extractReqParams(r), + UserAgent: r.UserAgent(), + Host: host, + Port: port, }) } @@ -971,6 +999,12 @@ func (api objectAPIHandlers) DeleteObjectHandler(w http.ResponseWriter, r *http. } writeSuccessNoContent(w) + // Get host and port from Request.RemoteAddr. + host, port, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + host, port = "", "" + } + // Notify object deleted event. eventNotify(eventData{ Type: ObjectRemovedDelete, @@ -979,5 +1013,8 @@ func (api objectAPIHandlers) DeleteObjectHandler(w http.ResponseWriter, r *http. Name: object, }, ReqParams: extractReqParams(r), + UserAgent: r.UserAgent(), + Host: host, + Port: port, }) }