func (cnsmr *consumer) establishWebsocketConnection(path string, authToken string) (*websocket.Conn, error) { header := http.Header{"Origin": []string{"http://localhost"}, "Authorization": []string{authToken}} dialer := websocket.Dialer{NetDial: cnsmr.proxyDial, TLSClientConfig: cnsmr.tlsConfig} url := cnsmr.endpoint + path cnsmr.debugPrinter.Print("WEBSOCKET REQUEST:", "GET "+path+" HTTP/1.1\n"+ "Host: "+cnsmr.endpoint+"\n"+ "Upgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Version: 13\nSec-WebSocket-Key: [HIDDEN]\n"+ headersString(header)) ws, resp, err := dialer.Dial(url, header) if resp != nil { cnsmr.debugPrinter.Print("WEBSOCKET RESPONSE:", resp.Proto+" "+resp.Status+"\n"+ headersString(resp.Header)) } if resp != nil && resp.StatusCode == http.StatusUnauthorized { bodyData, _ := ioutil.ReadAll(resp.Body) err = noaa_errors.NewUnauthorizedError(string(bodyData)) return ws, err } if err == nil && cnsmr.callback != nil { cnsmr.callback() } if err != nil { return nil, errors.New(fmt.Sprintf("Error dialing loggregator server: %s.\nPlease ask your Cloud Foundry Operator to check the platform configuration (loggregator endpoint is %s).", err.Error(), cnsmr.endpoint)) } return ws, err }
fakeConsumer = testapi.NewFakeLoggregatorConsumer() configRepo = testconfig.NewRepositoryWithDefaults() configRepo.SetLoggregatorEndpoint("loggregator-server.test.com") configRepo.SetAccessToken("the-access-token") fakeTokenRefresher = &testapi.FakeAuthenticationRepository{} }) JustBeforeEach(func() { logsRepo = NewLoggregatorLogsRepository(configRepo, fakeConsumer, fakeTokenRefresher) }) Describe("RecentLogsFor", func() { Context("when a noaa_errors.UnauthorizedError occurs", func() { BeforeEach(func() { fakeConsumer.RecentReturns.Err = []error{ noaa_errors.NewUnauthorizedError("i'm sorry dave"), nil, } }) It("refreshes the access token", func() { _, err := logsRepo.RecentLogsFor("app-guid") Expect(err).ToNot(HaveOccurred()) Expect(fakeTokenRefresher.RefreshTokenCalled).To(BeTrue()) }) }) Context("when an error occurs", func() { BeforeEach(func() { fakeConsumer.RecentReturns.Err = []error{errors.New("oops")} })
/* httpRecent connects to loggregator via its 'recentlogs' http(s) endpoint and returns a slice of recent messages. It does not guarantee any order of the messages; they are in the order returned by loggregator. */ func (cnsmr *consumer) httpRecentLogs(appGuid string, authToken string) ([]*events.Envelope, error) { endpointUrl, err := url.ParseRequestURI(cnsmr.endpoint) if err != nil { return nil, err } scheme := "https" if endpointUrl.Scheme == "ws" { scheme = "http" } recentPath := fmt.Sprintf("%s://%s/apps/%s/recentlogs", scheme, endpointUrl.Host, appGuid) transport := &http.Transport{Proxy: cnsmr.proxy, TLSClientConfig: cnsmr.tlsConfig} client := &http.Client{Transport: transport} req, _ := http.NewRequest("GET", recentPath, nil) req.Header.Set("Authorization", authToken) resp, err := client.Do(req) if err != nil { return nil, errors.New(fmt.Sprintf("Error dialing loggregator server: %s.\nPlease ask your Cloud Foundry Operator to check the platform configuration (loggregator endpoint is %s).", err.Error(), cnsmr.endpoint)) } defer resp.Body.Close() if resp.StatusCode == http.StatusUnauthorized { data, _ := ioutil.ReadAll(resp.Body) return nil, noaa_errors.NewUnauthorizedError(string(data)) } if resp.StatusCode == http.StatusBadRequest { return nil, ErrBadRequest } if resp.StatusCode != http.StatusOK { return nil, ErrNotFound } contentType := resp.Header.Get("Content-Type") if len(strings.TrimSpace(contentType)) == 0 { return nil, ErrBadResponse } matches := boundaryRegexp.FindStringSubmatch(contentType) if len(matches) != 2 || len(strings.TrimSpace(matches[1])) == 0 { return nil, ErrBadResponse } reader := multipart.NewReader(resp.Body, matches[1]) var buffer bytes.Buffer messages := make([]*events.Envelope, 0, 200) for part, loopErr := reader.NextPart(); loopErr == nil; part, loopErr = reader.NextPart() { buffer.Reset() msg := new(events.Envelope) _, err := buffer.ReadFrom(part) if err != nil { break } proto.Unmarshal(buffer.Bytes(), msg) messages = append(messages, msg) } return messages, err }