Skip to content

Commit

Permalink
refactor (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
piusalfred authored Oct 25, 2024
1 parent 2039723 commit a68716a
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 82 deletions.
14 changes: 8 additions & 6 deletions auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,15 @@ func (c *Client) RefreshAccessToken(ctx context.Context,
if params.SetTokenExpiresIn60 {
queryParams["set_token_expires_in_60_days"] = "true"
}
req := &whttp.Request[any]{
Type: whttp.RequestTypeRefreshToken,
BaseURL: c.baseURL,
Method: http.MethodGet,
Endpoints: []string{c.apiVersion, "/oauth/access_token"},
QueryParams: queryParams,

opts := []whttp.RequestOption[any]{
whttp.WithRequestType[any](whttp.RequestTypeRefreshToken),
whttp.WithRequestEndpoints[any](c.apiVersion, "/oauth/access_token"),
whttp.WithRequestQueryParams[any](queryParams),
}

req := whttp.MakeRequest[any](http.MethodGet, c.baseURL, opts...)

res := &RefreshAccessTokenResponse{}
decoder := whttp.ResponseDecoderJSON(res, whttp.DecodeOptions{
DisallowUnknownFields: false,
Expand Down
18 changes: 10 additions & 8 deletions business/business.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,21 @@ func (s *BaseSender) Send(ctx context.Context, config *config.Config, request *B
params["fields"] = fields
}

req := &whttp.Request[any]{
Type: request.Type,
Method: request.Method,
BaseURL: config.BaseURL,
Endpoints: []string{config.APIVersion, config.PhoneNumberID, Endpoint},
QueryParams: params,
Bearer: config.AccessToken,
opts := []whttp.RequestOption[any]{
whttp.WithRequestEndpoints[any](config.APIVersion, config.PhoneNumberID, Endpoint),
whttp.WithRequestQueryParams[any](params),
whttp.WithRequestBearer[any](config.AccessToken),
whttp.WithRequestType[any](request.Type),
whttp.WithRequestAppSecret[any](config.AppSecret),
whttp.WithRequestSecured[any](config.SecureRequests),
}

if request.Payload != nil {
req.Message = &request.Payload
opts = append(opts, whttp.WithRequestMessage[any](&request.Payload))
}

req := whttp.MakeRequest[any](request.Method, config.BaseURL, opts...)

response := &Response{}

decoder := whttp.ResponseDecoderJSON(response, whttp.DecodeOptions{
Expand Down
37 changes: 19 additions & 18 deletions flow/flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,27 +401,28 @@ func (client *BaseClient) UpdateFlowJSON(ctx context.Context,
return nil, fmt.Errorf("read config: %w", err)
}

req := &whttp.Request[any]{
Type: whttp.RequestTypeUploadMedia,
Method: http.MethodPost,
Bearer: conf.AccessToken,
QueryParams: nil,
BaseURL: conf.BaseURL,
Endpoints: []string{conf.APIVersion, conf.PhoneNumberID, "media"},
Metadata: nil,
Message: nil,
Form: &whttp.RequestForm{
Fields: map[string]string{
"name": request.Name,
"asset_type": "FLOW_JSON",
},
FormFile: &whttp.FormFile{
Name: "file",
Path: request.File,
},
form := &whttp.RequestForm{
Fields: map[string]string{
"name": request.Name,
"asset_type": "FLOW_JSON",
},
FormFile: &whttp.FormFile{
Name: "file",
Path: request.File,
},
}

opts := []whttp.RequestOption[any]{
whttp.WithRequestType[any](whttp.RequestTypeUploadMedia),
whttp.WithRequestBearer[any](conf.AccessToken),
whttp.WithRequestForm[any](form),
whttp.WithRequestEndpoints[any](conf.APIVersion, conf.PhoneNumberID, "media"),
whttp.WithRequestAppSecret[any](conf.AppSecret),
whttp.WithRequestSecured[any](conf.SecureRequests),
}

req := whttp.MakeRequest[any](http.MethodPost, conf.BaseURL, opts...)

var resp UpdateFlowJSONResponse
decoder := whttp.ResponseDecoderJSON(&resp, whttp.DecodeOptions{
DisallowUnknownFields: true,
Expand Down
16 changes: 9 additions & 7 deletions flow/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,17 @@ func (client *BaseClient) GetFlowMetrics(ctx context.Context, request *MetricsRe
request.MetricName, request.Granularity, request.Since.Format(time.DateOnly), request.Until.Format(time.DateOnly)),
}

req := &whttp.Request[any]{
Type: whttp.RequestTypeGetFlowMetrics,
Method: http.MethodGet,
Bearer: conf.AccessToken,
QueryParams: queryParams,
BaseURL: conf.BaseURL,
Endpoints: []string{conf.APIVersion, request.FlowID},
opts := []whttp.RequestOption[any]{
whttp.WithRequestType[any](whttp.RequestTypeGetFlowMetrics),
whttp.WithRequestBearer[any](conf.AccessToken),
whttp.WithRequestQueryParams[any](queryParams),
whttp.WithRequestSecured[any](conf.SecureRequests),
whttp.WithRequestAppSecret[any](conf.AppSecret),
whttp.WithRequestEndpoints[any](conf.APIVersion, request.FlowID),
}

req := whttp.MakeRequest[any](http.MethodGet, conf.BaseURL, opts...)

var resp MetricsAPIResponse
decoder := whttp.ResponseDecoderJSON(&resp, whttp.DecodeOptions{
DisallowUnknownFields: true,
Expand Down
81 changes: 44 additions & 37 deletions media/media.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,16 @@ func (s *BaseClient) Download(ctx context.Context, request *DownloadRequest, dec
if err != nil {
return fmt.Errorf("%w: config read: %w", ErrMediaDownload, err)
}
req := &whttp.Request[any]{
Type: whttp.RequestTypeDownloadMedia,
Method: http.MethodGet,
BaseURL: request.URL,
Bearer: conf.AccessToken,

opts := []whttp.RequestOption[any]{
whttp.WithRequestAppSecret[any](conf.AppSecret),
whttp.WithRequestSecured[any](conf.SecureRequests),
whttp.WithRequestBearer[any](conf.AccessToken),
whttp.WithRequestType[any](whttp.RequestTypeDownloadMedia),
}

req := whttp.MakeRequest[any](http.MethodGet, request.URL, opts...)

for i := 0; i <= request.Retries; i++ {
if err := s.Sender.Send(ctx, req, decoder); err != nil {
if i < request.Retries {
Expand Down Expand Up @@ -316,15 +319,17 @@ func (s *BaseClient) Delete(ctx context.Context, req *BaseRequest) (*DeleteMedia
queryParams["phone_number_id"] = phoneNumberID
}

request := &whttp.Request[any]{
Type: whttp.RequestTypeDeleteMedia,
Method: http.MethodDelete,
Bearer: conf.AccessToken,
BaseURL: conf.BaseURL,
QueryParams: queryParams,
Endpoints: []string{conf.APIVersion, req.MediaID},
opts := []whttp.RequestOption[any]{
whttp.WithRequestAppSecret[any](conf.AppSecret),
whttp.WithRequestSecured[any](conf.SecureRequests),
whttp.WithRequestBearer[any](conf.AccessToken),
whttp.WithRequestType[any](whttp.RequestTypeDeleteMedia),
whttp.WithRequestQueryParams[any](queryParams),
whttp.WithRequestEndpoints[any](conf.APIVersion, req.MediaID),
}

request := whttp.MakeRequest[any](http.MethodDelete, conf.BaseURL, opts...)

var resp DeleteMediaResponse
decoder := whttp.ResponseDecoderJSON(&resp, whttp.DecodeOptions{
DisallowUnknownFields: true,
Expand Down Expand Up @@ -354,15 +359,16 @@ func (s *BaseClient) GetInfo(ctx context.Context, req *BaseRequest) (*Informatio
queryParams["phone_number_id"] = phoneNumberID
}

request := &whttp.Request[any]{
Type: whttp.RequestTypeGetMedia,
Method: http.MethodGet,
Bearer: conf.AccessToken,
QueryParams: queryParams,
BaseURL: conf.BaseURL,
Endpoints: []string{conf.APIVersion, req.MediaID},
opts := []whttp.RequestOption[any]{
whttp.WithRequestAppSecret[any](conf.AppSecret),
whttp.WithRequestSecured[any](conf.SecureRequests),
whttp.WithRequestType[any](whttp.RequestTypeGetMedia),
whttp.WithRequestQueryParams[any](queryParams),
whttp.WithRequestEndpoints[any](conf.APIVersion, req.MediaID),
}

request := whttp.MakeRequest[any](http.MethodGet, conf.BaseURL, opts...)

var info Information
decoder := whttp.ResponseDecoderJSON(&info, whttp.DecodeOptions{
DisallowUnknownFields: true,
Expand All @@ -388,27 +394,28 @@ func (s *BaseClient) Upload(ctx context.Context, req *UploadRequest) (*UploadMed
return nil, fmt.Errorf("%w: media type not supported", ErrMediaUpload)
}

request := &whttp.Request[any]{
Type: whttp.RequestTypeUploadMedia,
Method: http.MethodPost,
Bearer: conf.AccessToken,
QueryParams: nil,
BaseURL: conf.BaseURL,
Endpoints: []string{conf.APIVersion, conf.PhoneNumberID, "media"},
Metadata: nil,
Message: nil,
Form: &whttp.RequestForm{
Fields: map[string]string{
"type": string(req.MediaType),
"messaging_product": "whatsapp",
},
FormFile: &whttp.FormFile{
Name: "file",
Path: req.Filename,
},
form := &whttp.RequestForm{
Fields: map[string]string{
"type": string(req.MediaType),
"messaging_product": "whatsapp",
},
FormFile: &whttp.FormFile{
Name: "file",
Path: req.Filename,
},
}

opts := []whttp.RequestOption[any]{
whttp.WithRequestAppSecret[any](conf.AppSecret),
whttp.WithRequestSecured[any](conf.SecureRequests),
whttp.WithRequestBearer[any](conf.AccessToken),
whttp.WithRequestType[any](whttp.RequestTypeUploadMedia),
whttp.WithRequestEndpoints[any](conf.APIVersion, conf.PhoneNumberID, "media"),
whttp.WithRequestForm[any](form),
}

request := whttp.MakeRequest[any](http.MethodPost, conf.BaseURL, opts...)

var resp UploadMediaResponse
decoder := whttp.ResponseDecoderJSON(&resp, whttp.DecodeOptions{
DisallowUnknownFields: true,
Expand Down
100 changes: 100 additions & 0 deletions pkg/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,108 @@ type (
Name string
Path string
}

RequestOption[T any] func(request *Request[T])
)

// MakeRequest creates a new request with the provided options.
func MakeRequest[T any](method, baseURL string, options ...RequestOption[T]) *Request[T] {
req := &Request[T]{
Method: method,
BaseURL: baseURL,
Headers: make(map[string]string),
QueryParams: make(map[string]string),
}

for _, option := range options {
if option != nil {
option(req)
}
}

return req
}

// NewRequestWithContext ...
func NewRequestWithContext[T any](ctx context.Context, method, baseURL string,
options ...RequestOption[T],
) (*http.Request, error) {
req := MakeRequest[T](method, baseURL, options...)

return RequestWithContext(ctx, req)
}

// WithRequestType sets the request type for the request.
func WithRequestType[T any](requestType RequestType) RequestOption[T] {
return func(request *Request[T]) {
request.Type = requestType
}
}

// WithRequestBearer sets the bearer token for the request.
func WithRequestBearer[T any](bearer string) RequestOption[T] {
return func(request *Request[T]) {
request.Bearer = bearer
}
}

// WithRequestEndpoints sets the endpoints for the request.
func WithRequestEndpoints[T any](endpoints ...string) RequestOption[T] {
return func(request *Request[T]) {
request.Endpoints = endpoints
}
}

// WithRequestMetadata sets the metadata for the request.
func WithRequestMetadata[T any](metadata types.Metadata) RequestOption[T] {
return func(request *Request[T]) {
request.Metadata = metadata
}
}

// WithRequestHeaders sets the headers for the request.
func WithRequestHeaders[T any](headers map[string]string) RequestOption[T] {
return func(request *Request[T]) {
request.Headers = headers
}
}

// WithRequestQueryParams sets the query parameters for the request.
func WithRequestQueryParams[T any](queryParams map[string]string) RequestOption[T] {
return func(request *Request[T]) {
request.QueryParams = queryParams
}
}

// WithRequestMessage sets the message for the request.
func WithRequestMessage[T any](message *T) RequestOption[T] {
return func(request *Request[T]) {
request.Message = message
}
}

func WithRequestForm[T any](form *RequestForm) RequestOption[T] {
return func(request *Request[T]) {
request.Form = form
}
}

// WithRequestAppSecret sets the app secret for the request and turns on secure requests.
func WithRequestAppSecret[T any](appSecret string) RequestOption[T] {
return func(request *Request[T]) {
if request.AppSecret != "" {
request.AppSecret = appSecret
}
}
}

// WithRequestSecured sets the request to be secure.
func WithRequestSecured[T any](secured bool) RequestOption[T] {
return func(request *Request[T]) {
request.SecureRequests = secured
}
}

var errNilRequest = errors.New("nil request provided")

func RequestWithContext[T any](ctx context.Context, req *Request[T]) (*http.Request, error) {
Expand Down
14 changes: 8 additions & 6 deletions qrcode/qrcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,16 @@ func (sender *BaseSender) Send(ctx context.Context, conf *config.Config, req *Ba
endpoints = append(endpoints, req.QRCodeID)
}

request := &whttp.Request[any]{
Type: req.Type,
Method: req.Method,
BaseURL: conf.BaseURL,
Endpoints: endpoints,
QueryParams: req.QueryParams,
opts := []whttp.RequestOption[any]{
whttp.WithRequestType[any](req.Type),
whttp.WithRequestEndpoints[any](endpoints...),
whttp.WithRequestQueryParams[any](req.QueryParams),
whttp.WithRequestAppSecret[any](conf.AppSecret),
whttp.WithRequestSecured[any](conf.SecureRequests),
}

request := whttp.MakeRequest[any](req.Method, conf.BaseURL, opts...)

response := &Response{}

decoder := whttp.ResponseDecoderJSON(response, whttp.DecodeOptions{
Expand Down

0 comments on commit a68716a

Please sign in to comment.