Example #1
0
func (d *Database) notify(event string, object *fosp.Object) {
	dbLog.Debug("Event %s on object %s occured", event, object.URL)
	users := subscribedUsers(object, event, 0)
	dbLog.Debug("Users %v should be notified", users)
	for _, user := range users {
		notification := fosp.NewNotification(event, object.URL)
		if event != fosp.DELETED {
			if serialized, err := json.Marshal(object); err == nil {
				notification.Body = bytes.NewBuffer(serialized)
			} else {
				dbLog.Error("Unable to serialize object %s for sending notification :: %s", object.URL, err)
				continue
			}
		}
		d.server.routeNotification(user, notification)
	}
}
Example #2
0
func parseMessage(in io.Reader) (msg fosp.Message, seq uint64, err error) {
	var (
		firstLine []byte
		rawurl    string
		isPrefix  bool
		readerErr error
		fragments [][]byte
		code      int
		msgURL    *url.URL
		reader    *bufio.Reader
		ok        bool
	)
	err = errors.New("Failed to parse message, unknown error")
	if reader, ok = in.(*bufio.Reader); !ok {
		reader = bufio.NewReader(in)
	}
	if firstLine, isPrefix, readerErr = reader.ReadLine(); isPrefix {
		err = errors.New("First line of message is too long")
		return
	} else if readerErr != nil && readerErr != io.EOF {
		err = newNestedError("Reader error", readerErr)
		return
	}
	if fragments = bytes.Split(firstLine, []byte(" ")); len(fragments) < 2 {
		err = errors.New("First line does not consist of at least 2 parts")
		return
	}
	identifier := string(fragments[0])
	switch identifier {
	case fosp.OPTIONS, fosp.AUTH, fosp.GET, fosp.LIST, fosp.CREATE, fosp.PATCH, fosp.DELETE, fosp.READ, fosp.WRITE:
		if len(fragments) != 3 {
			err = errors.New("Request line does not consist of 3 parts")
			return
		}
		rawurl = string(fragments[1])
		if rawurl != "*" {
			rawurl = "fosp://" + string(fragments[1])
			if msgURL, err = url.Parse(rawurl); err != nil {
				err = errors.New("Invalid request URL")
				return
			}
			msgURL.Path = path.Clean(msgURL.Path)
			if msgURL.Path == "." {
				msgURL.Path = "/"
			}
		}
		if seq, err = strconv.ParseUint(string(fragments[2]), 10, 64); err != nil || seq < 1 {
			err = newNestedError("The request sequence number is not valid", err)
			return
		}
		req := fosp.NewRequest(identifier, msgURL)
		if req.Header, err = textproto.NewReader(reader).ReadMIMEHeader(); err != nil && err != io.EOF {
			err = newNestedError("The request header is not valid", err)
			return
		}
		req.Body = reader
		return req, seq, nil
	case fosp.SUCCEEDED, fosp.FAILED:
		if len(fragments) != 3 {
			err = errors.New("Response line does not consist of 3 parts")
			return
		}
		if code, err = strconv.Atoi(string(fragments[1])); err != nil {
			err = newNestedError("Status code is invalid", err)
			return
		}
		if seq, err = strconv.ParseUint(string(fragments[2]), 10, 64); err != nil || seq < 1 {
			err = newNestedError("The response sequence number is not valid", err)
			if seq < 1 {
				err = errors.New("The sequence number is 0")
			}
			return
		}
		resp := fosp.NewResponse(identifier, uint(code))
		if resp.Header, err = textproto.NewReader(reader).ReadMIMEHeader(); err != nil && err != io.EOF {
			err = newNestedError("The response header is not valid", err)
			return
		}
		resp.Body = reader
		return resp, seq, nil
	case fosp.CREATED, fosp.UPDATED, fosp.DELETED:
		if len(fragments) != 2 {
			err = errors.New("Notification line does not consist of 2 parts")
			return
		}
		rawurl = string(fragments[1])
		if rawurl != "*" {
			rawurl = "fosp://" + string(fragments[1])
			if msgURL, err = url.Parse(rawurl); err != nil {
				err = errors.New("Invalid request URL")
				return
			}
			msgURL.Path = path.Clean(msgURL.Path)
			if msgURL.Path == "." {
				msgURL.Path = "/"
			}
		}
		evt := fosp.NewNotification(identifier, msgURL)
		if evt.Header, err = textproto.NewReader(reader).ReadMIMEHeader(); err != nil && err != io.EOF {
			err = newNestedError("The notification header is not valid", err)
			return
		}
		evt.Body = reader
		return evt, seq, nil
	default:
		err = errors.New("Unrecognized identifier " + identifier)
		return
	}
}