// An HTTP handler for matching incoming requests with existing watches. func (self *matchHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { // The standard library does not support keep-alive timeouts, // so we'll just have to close the connection after every request // (or we could hope that clients remember to close their // connections (but if they don't, then we can't shutdown)). w.Header().Set("Connection", "close") defer func() { if e := recover(); e != nil { var str string switch u := e.(type) { case error: str = u.Error() default: str = fmt.Sprintf("%+v", e) } log.Printf("panic: (%d) %s", GOOSE_ERROR, str) http.Error(w, str, GOOSE_ERROR) } }() // Build a match expression from the request expr := watchdb.NewMatchExpr(self.DataSourceName, req.URL.Path, req.Method) // Lookup the associated watch, if any m, err := self.ws.Match(expr) if err != nil { http.Error(w, err.Error(), GOOSE_ERROR) return } // TODO: m.MatchType == watchdb.PASSTHRU tag := "" if m.IsMatch() { tag = m.Tag() } // Record the event. self.ep.Trace(eventdb.NewMessage(tag, req, map[string]string{ "dataSourceName": self.DataSourceName, })) // Return an error code if we don't find any matching watches. if !m.IsMatch() { http.Error(w, "This request did not match any watches.", GOOSE_CONF_ERROR) return } // Otherwise, return an echo. m.Echo().ServeHTTP(w, req) }
func TestMatchWithService(t *testing.T) { ws, err := Start() if err != nil { t.Error(err) return } defer ws.Stop() w := fakeWatch() ws.Add(w) expr := watchdb.NewMatchExpr("dummy-service", w.Path, w.Method) m, err := ws.Match(expr) if err != nil { t.Error(err) return } if m.Tag() != w.Tag { t.Error("expected: %s, got: %s", w.Tag, m.Tag()) return } }
func TestMatchHandler(t *testing.T) { const ( LISTEN_ADDR = ":9002" WATCHED_URL = "http://127.0.0.1:9002/foo" WATCH_BODY = "hello, world" DSN = "dummy-service" ) ws, err := worker.Start() if err != nil { t.Error(err) return } defer ws.Stop() echo := &fakeResponse{body: WATCH_BODY} w := watchdb.NewWatch(DSN, "/foo", "GET", "redis:watch:1234", echo) _, _, err = ws.Add(w) if err != nil { t.Error(err) return } mx := watchdb.NewMatchExpr(DSN, "/foo", "GET") m, _ := ws.Match(mx) if !m.IsMatch() { t.Errorf("watchdb doesn't recognize the watch") return } ep := eventdb.NopEventProvider() mux := NewMatchHandler(DSN, ws, ep) s, err := StartHttpServer(LISTEN_ADDR, mux) if err != nil { t.Error(err) return } defer s.Stop() resp, err := http.Get(WATCHED_URL) if err != nil { t.Error(err) return } if resp.StatusCode != 200 { t.Errorf("expected: %d, got: %d", 200, resp.StatusCode) return } bufr := bufio.NewReader(resp.Body) yy, err := ioutil.ReadAll(bufr) resp.Body.Close() if err != nil { t.Error(err) return } str := string(yy) if str != WATCH_BODY { t.Errorf("unexpected: %s", str) t.Errorf("expected: \"%s\", got: \"%s\"", WATCH_BODY, str) // Fprintln adds a '\n', oops. spew.Dump(yy) spew.Dump(str) return } }