func (h *handler) handleChanges() error { // http://wiki.apache.org/couchdb/HTTP_database_API#Changes var options db.ChangesOptions options.Since = h.getIntQuery("since", 0) options.Limit = int(h.getIntQuery("limit", 0)) options.Conflicts = (h.getQuery("style") == "all_docs") options.IncludeDocs = (h.getBoolQuery("include_docs")) // Get the channels as parameters to an imaginary "bychannel" filter. // The default is all channels the user can access. userChannels := h.user.Channels filter := h.getQuery("filter") if filter != "" { if filter != "sync_gateway/bychannel" { return &base.HTTPError{http.StatusBadRequest, "Unknown filter; try sync_gateway/bychannel"} } channelsParam := h.getQuery("channels") if channelsParam == "" { return &base.HTTPError{http.StatusBadRequest, "Missing 'channels' filter parameter"} } userChannels = channels.SimplifyChannels(strings.Split(channelsParam, ","), true) userChannels = h.user.ExpandWildCardChannel(userChannels) if err := h.user.AuthorizeAllChannels(userChannels); err != nil { return err } } switch h.getQuery("feed") { case "continuous": return h.handleContinuousChanges(userChannels, options) case "longpoll": options.Wait = true } return h.handleSimpleChanges(userChannels, options) }
// Top-level handler for _changes feed requests. func (h *handler) handleChanges() error { // http://wiki.apache.org/couchdb/HTTP_database_API#Changes // http://docs.couchdb.org/en/latest/api/database/changes.html var options db.ChangesOptions options.Since = channels.TimedSetFromString(h.getQuery("since")) options.Limit = int(h.getIntQuery("limit", 0)) options.Conflicts = (h.getQuery("style") == "all_docs") options.IncludeDocs = (h.getBoolQuery("include_docs")) options.Terminator = make(chan bool) defer close(options.Terminator) // Get the channels as parameters to an imaginary "bychannel" filter. // The default is all channels the user can access. userChannels := channels.SetOf("*") filter := h.getQuery("filter") if filter != "" { if filter != "sync_gateway/bychannel" { return base.HTTPErrorf(http.StatusBadRequest, "Unknown filter; try sync_gateway/bychannel") } channelsParam := h.getQuery("channels") if channelsParam == "" { return base.HTTPErrorf(http.StatusBadRequest, "Missing 'channels' filter parameter") } var err error userChannels, err = channels.SetFromArray(strings.Split(channelsParam, ","), channels.ExpandStar) if err != nil { return err } if len(userChannels) == 0 { return base.HTTPErrorf(http.StatusBadRequest, "Empty channel list") } } h.db.ChangesClientStats.Increment() defer h.db.ChangesClientStats.Decrement() switch h.getQuery("feed") { case "normal", "": return h.sendSimpleChanges(userChannels, options) case "longpoll": options.Wait = true return h.sendSimpleChanges(userChannels, options) case "continuous": return h.sendContinuousChangesByHTTP(userChannels, options) case "websocket": return h.sendContinuousChangesByWebSocket(userChannels, options) default: return base.HTTPErrorf(http.StatusBadRequest, "Unknown feed type") } }
func (h *handler) handleChanges() error { // http://wiki.apache.org/couchdb/HTTP_database_API#Changes var options db.ChangesOptions options.Since = channels.TimedSetFromString(h.getQuery("since")) options.Limit = int(h.getIntQuery("limit", 0)) options.Conflicts = (h.getQuery("style") == "all_docs") options.IncludeDocs = (h.getBoolQuery("include_docs")) // Get the channels as parameters to an imaginary "bychannel" filter. // The default is all channels the user can access. userChannels := channels.SetOf("*") filter := h.getQuery("filter") if filter != "" { if filter != "sync_gateway/bychannel" { return &base.HTTPError{http.StatusBadRequest, "Unknown filter; try sync_gateway/bychannel"} } channelsParam := h.getQuery("channels") if channelsParam == "" { return &base.HTTPError{http.StatusBadRequest, "Missing 'channels' filter parameter"} } var err error userChannels, err = channels.SetFromArray(strings.Split(channelsParam, ","), channels.ExpandStar) if err != nil { return err } if len(userChannels) == 0 { return &base.HTTPError{http.StatusBadRequest, "Empty channel list"} } } switch h.getQuery("feed") { case "continuous": return h.handleContinuousChanges(userChannels, options) case "longpoll": options.Wait = true } return h.handleSimpleChanges(userChannels, options) }
// Top-level handler for _changes feed requests. Accepts GET or POST requests. func (h *handler) handleChanges() error { // http://wiki.apache.org/couchdb/HTTP_database_API#Changes // http://docs.couchdb.org/en/latest/api/database/changes.html restExpvars.Add("changesFeeds_total", 1) restExpvars.Add("changesFeeds_active", 1) defer restExpvars.Add("changesFeeds_active", -1) var feed string var options db.ChangesOptions var filter string var channelsArray []string if h.rq.Method == "GET" { // GET request has parameters in URL: feed = h.getQuery("feed") options.Since = channels.TimedSetFromString(h.getQuery("since")) options.Limit = int(h.getIntQuery("limit", 0)) options.Conflicts = (h.getQuery("style") == "all_docs") options.IncludeDocs = (h.getBoolQuery("include_docs")) filter = h.getQuery("filter") channelsParam := h.getQuery("channels") if channelsParam != "" { channelsArray = strings.Split(channelsParam, ",") } } else { // POST request has parameters in JSON body: body, err := h.readBody() if err != nil { return err } feed, options, filter, channelsArray, err = readChangesOptionsFromJSON(body) if err != nil { return err } } // Get the channels as parameters to an imaginary "bychannel" filter. // The default is all channels the user can access. userChannels := channels.SetOf("*") if filter != "" { if filter != "sync_gateway/bychannel" { return base.HTTPErrorf(http.StatusBadRequest, "Unknown filter; try sync_gateway/bychannel") } if channelsArray == nil { return base.HTTPErrorf(http.StatusBadRequest, "Missing 'channels' filter parameter") } var err error userChannels, err = channels.SetFromArray(channelsArray, channels.ExpandStar) if err != nil { return err } if len(userChannels) == 0 { return base.HTTPErrorf(http.StatusBadRequest, "Empty channel list") } } h.db.ChangesClientStats.Increment() defer h.db.ChangesClientStats.Decrement() options.Terminator = make(chan bool) defer close(options.Terminator) switch feed { case "normal", "": return h.sendSimpleChanges(userChannels, options) case "longpoll": options.Wait = true return h.sendSimpleChanges(userChannels, options) case "continuous": return h.sendContinuousChangesByHTTP(userChannels, options) case "websocket": return h.sendContinuousChangesByWebSocket(userChannels, options) default: return base.HTTPErrorf(http.StatusBadRequest, "Unknown feed type") } }