예제 #1
0
func createDecorator(name string, order *callOrder) kapusta.DecoratorFunc {
	return func(c kapusta.IClient) kapusta.IClient {
		return kapusta.ClientFunc(func(r *http.Request) (*http.Response, error) {
			*order = append(*order, name)
			return c.Do(r)
		})
	}
}
예제 #2
0
파일: decorator.go 프로젝트: go-st/kapusta
// HeadersDecorator returns a DecoratorFunc that adds the given HTTP headers to every request done by a Client.
func HeadersDecorator(values map[string]string) kapusta.DecoratorFunc {
	return func(c kapusta.IClient) kapusta.IClient {
		return kapusta.ClientFunc(func(r *http.Request) (*http.Response, error) {
			for key, value := range values {
				r.Header.Add(key, value)
			}
			return c.Do(r)
		})
	}
}
예제 #3
0
파일: decorator.go 프로젝트: go-st/kapusta
// RecoverDecorator returns a DecoratorFunc that recovers panic and convert it to error
func RecoverDecorator() kapusta.DecoratorFunc {
	return func(c kapusta.IClient) kapusta.IClient {
		return kapusta.ClientFunc(func(r *http.Request) (res *http.Response, err error) {
			defer func() {
				if r := recover(); r != nil {
					err = fmt.Errorf("recovered panic: %v", r)
				}
			}()
			return c.Do(r)
		})
	}
}
예제 #4
0
func (s *TestSuite) TestPanicDecorator(c *C) {
	panicTriggerDecorator := func(c kapusta.IClient) kapusta.IClient {
		return kapusta.ClientFunc(func(r *http.Request) (res *http.Response, err error) {
			panic("oops")
		})
	}
	r, _ := http.NewRequest("GET", "/", nil)
	client := kapusta.Decorate(s.dummyClient, panicTriggerDecorator, RecoverDecorator())
	res, err := client.Do(r)

	c.Assert(res, IsNil)
	c.Assert(err, ErrorMatches, "*oops")
}
예제 #5
0
파일: log.go 프로젝트: go-st/kapusta
// LoggerDecorator returns DecoratorFunc that logs before and after request
func LoggerDecorator(logger logger.ILogger, dumpRequests bool) kapusta.DecoratorFunc {
	return func(c kapusta.IClient) kapusta.IClient {
		return kapusta.ClientFunc(func(r *http.Request) (*http.Response, error) {
			logger.Debugf("start request: %v", r.URL)
			var bodyBytes []byte

			if dumpRequests {
				// We should preserve Body before Do and restore it after Do, because Body is io.ReadCloser and
				// it will have already been read after Do. DumpRequestOut is going to read Body again.

				if r.Body != nil {
					bodyBytes, _ = ioutil.ReadAll(r.Body)
				}
				// Restore the io.ReadCloser to its original state
				r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
			}

			response, err := c.Do(r)

			if dumpRequests {
				// Restore the io.ReadCloser to its original state again, because it has been already read by Do
				r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))

				if requestDump, requestReadErr := httputil.DumpRequestOut(r, true); requestReadErr == nil {
					logger.Debugf("dump request to %v:\n%s", r.URL, string(requestDump))
				} else {
					logger.Debugf("can't dump request to %v\nError: %v", r.URL, requestReadErr)
				}
			}

			if err != nil {
				logger.Errorf("done request: %v, error: %v", r.URL, err)
				return nil, err
			}

			logger.Debugf("done request: %v, HTTP status: %s", r.URL, response.Status)

			if dumpRequests {
				if responseDump, responseReadErr := httputil.DumpResponse(response, true); responseReadErr == nil {
					logger.Debugf("dump response from %v:\n%s", r.URL, string(responseDump))
				} else {
					logger.Debugf("can't dump response from %v\nError: %v", r.URL, responseReadErr)
				}
			}

			return response, err
		})
	}
}
예제 #6
0
파일: decorator.go 프로젝트: go-st/kapusta
// BaseURLDecorator returns a DecoratorFunc that replaces scheme and host in request from specified baseURL
func BaseURLDecorator(baseURL string) kapusta.DecoratorFunc {
	parsed, err := url.Parse(baseURL)

	if err != nil {
		panic(err)
	}

	return func(c kapusta.IClient) kapusta.IClient {
		return kapusta.ClientFunc(func(r *http.Request) (*http.Response, error) {
			r.URL.Scheme = parsed.Scheme
			r.URL.Host = parsed.Host

			return c.Do(r)
		})
	}
}