httpclient

package module
v0.0.0-...-ff2f47c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 9, 2023 License: MIT Imports: 12 Imported by: 0

README

HTTP Client GO library

Install
import:
- package: github.com/best-expendables-v2/httpclient
  version: x.x.x
Middlewares
  • middleware.Authentication
  • middleware.RequestLogger
  • middleware.ResponseLogger
  • middleware.Newrelic
  • middleware.NewNewrelicApiGateway
  • middleware.Opentrace
  • middleware.NetworkProfiler
  • middleware.RequestID
RequestLogger/ResponseLogger

Since we use request-dependent logging, we have to pass context with logger to each request.
Otherwise middleware will use logger which was injected via constructor middleware.NewRequestLogger(logger)

NetworkProfiler

Network profiler collects metrics about the network and set the report into context.
Low overhead cost allows to use it for production.

You can find the report into the response log:

{"content":{"response":{...}, "network": {...}}

"reused": (bool) - Connection was taken from the keep-alive pool
"connection": Time elapsed for connection establishing (ignores on keep-alive connection)
"dns": Time elapsed for DNS lookup (ignores on keep-alive connection)

Or for some cases you can get the report from response e.g.:

package main(
	"net/http"
    
	"github.com/best-expendables-v2/httpclient/middleware"
	"github.com/best-expendables-v2/httpclient/net/profile"
)
	

transport = middleware.WithMiddleware(nil, NewNetworkProfiler)

c := &http.Client{
	Transport: transport,
}
response, _ := c.Get("http://localhost")
report := profile.ReportFromResponse(response)
Examples
1) Context-independent middlewares.

One client for whole life time of application We can keep one client for whole application lifetime and pass context for each http request.

package main

import (
	"net/http"

	"github.com/best-expendables-v2/httpclient/middleware"
	log "github.com/best-expendables-v2/logger"
)

func main() {
	logger := log.NewLoggerFactory(log.InfoLevel).
		Logger(context.TODO())

	transport = middleware.WithMiddleware(
		http.DefaultTransport,
		middleware.NewRequestLogger(logger),
		middleware.NewResponseLogger(logger),
		middleware.NewOpentrace(),
	)
	
	client := http.Client{
		Transport: transport,
	}
	
	request, _ := http.NewRequest(http.MethodGet, srv.URL, nil)
	request = request.WithContext(ctx)
}
2) Context-dependent middlewares.

New client for each incoming request.
For compatibility with old code, we can create middleware for each http incoming request.
In this case application will spend more resources for memory allocation and garbage collecting.

package main

import (
	"net/http"

	"github.com/best-expendables-v2/httpclient/middleware"
	log "github.com/best-expendables-v2/logger"
)

func main() {
	logger := log.NewLoggerFactory(log.InfoLevel).
		Logger(context.TODO())

	transport = middleware.WithMiddleware(
		http.DefaultTransport,
		middleware.NewRequestLogger(logger),
		middleware.NewResponseLogger(logger),
		middleware.NewOpentrace(),
	)
	
	client := http.Client{
		Transport: transport,
	}
	
	request, _ := http.NewRequest(http.MethodGet, srv.URL, nil)
	request = request.WithContext(ctx)
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewDefaultHttpClient

func NewDefaultHttpClient(defaultEntry logger.Entry, timeout time.Duration) *http.Client

func NewHttpClientWithMiddlewares

func NewHttpClientWithMiddlewares(timeout time.Duration, middlewares ...middleware.Middleware) *http.Client

func WithHeaderSetterFn

func WithHeaderSetterFn(setterFn HeaderSetterFn) option

WithHeaders

func WithResponseParser

func WithResponseParser(p ResponseParser) option

WithResponseParser custom response parsing format

func WithTimeout

func WithTimeout(timeout time.Duration) option

WithTimeout timeout option

func WithTransport

func WithTransport(rt http.RoundTripper) option

WithTransport custom transport option

Types

type ApiResponse

type ApiResponse struct {
	Data interface{} `json:"data"`
}

ApiResponse data structure to extract restful response

type BaseClient

type BaseClient struct {
	// contains filtered or unexported fields
}

func NewBaseClient

func NewBaseClient(url string, opts ...option) *BaseClient

func (*BaseClient) DoRequest

func (c *BaseClient) DoRequest(ctx context.Context, method, path string, queryParams url.Values, body, result interface{}) error

type DefaultApiResponseParser

type DefaultApiResponseParser struct{}

func (*DefaultApiResponseParser) Parse

func (p *DefaultApiResponseParser) Parse(r io.Reader, result interface{}) error

type Error

type Error struct {
	Code    int
	Message string
}

func (*Error) Error

func (e *Error) Error() string

type HeaderSetterFn

type HeaderSetterFn func(r *http.Request)

type ResponseParser

type ResponseParser interface {
	Parse(r io.Reader, result interface{}) error
}

Directories

Path Synopsis
_examples
net

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL