Skip to content

Commit

Permalink
Refactored execution of request
Browse files Browse the repository at this point in the history
  • Loading branch information
mymmrac committed Aug 13, 2021
1 parent b40fc80 commit 14a2817
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 90 deletions.
151 changes: 62 additions & 89 deletions bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,13 @@ var json = jsoniter.ConfigCompatibleWithStandardLibrary
const (
defaultBotAPIServer = "https://api.telegram.org"

jsonContentType = "application/json"
contentTypeJSON = "application/json"

tokenRegexp = `^\d{9,10}:[\w-]{35}$` //nolint:gosec

attachFile = `attach://`

omitEmptySuffix = ",omitempty"

ansiReset = "\u001B[0m"
ansiRed = "\u001B[31m"
ansiYellow = "\u001B[33m"
ansiBlue = "\u001B[34m"
)

var (
Expand Down Expand Up @@ -144,41 +139,71 @@ func (a APIError) Error() string {
return fmt.Sprintf("%d %q", a.ErrorCode, a.Description)
}

func (b *Bot) apiRequest(methodName string, parameters interface{}) (*apiResponse, error) {
url := b.apiURL + "/bot" + b.token + "/" + methodName

buffer := &bytes.Buffer{}
err := json.NewEncoder(buffer).Encode(parameters)
func (b *Bot) performRequest(methodName string, parameters, v interface{}) error {
resp, err := b.executeRequest(methodName, parameters)
if err != nil {
return nil, fmt.Errorf("encode json: %w", err)
return fmt.Errorf("execute: %w", err)
}

req := fasthttp.AcquireRequest()
req.SetRequestURI(url)
req.Header.SetContentType(jsonContentType)
req.Header.SetMethod(fasthttp.MethodPost)
req.SetBodyRaw(buffer.Bytes())
if !resp.Ok {
return fmt.Errorf("api: %w", resp.APIError)
}

resp := fasthttp.AcquireResponse()
err = b.client.Do(req, resp)
if err != nil {
return nil, fmt.Errorf("request: %w", err)
if resp.Result != nil {
err = json.Unmarshal(resp.Result, &v)
if err != nil {
return fmt.Errorf("unmarshal to %s: %w", reflect.TypeOf(v), err)
}
}

if statusCode := resp.StatusCode(); statusCode >= fasthttp.StatusInternalServerError {
b.log.Errorf("Internal server error, status code: %d", statusCode)
return nil, fmt.Errorf("internal server error: %d", statusCode)
return nil
}

func (b *Bot) executeRequest(methodName string, parameters interface{}) (*apiResponse, error) {
isDirectFile := false
var fileParams map[string]*os.File

p, ok := parameters.(fileCompatible)
if ok {
fileParams = p.fileParameters()
for _, file := range fileParams {
if file != nil {
isDirectFile = true
break
}
}
}

apiResp := &apiResponse{}
err = json.Unmarshal(resp.Body(), apiResp)
if isDirectFile {
params, err := toParams(parameters)
if err != nil {
return nil, fmt.Errorf("get params: %w", err)
}

resp, err := b.apiRequestMultipartFormData(methodName, params, fileParams)
if err != nil {
return nil, fmt.Errorf("request multipart form data: %w", err)
}
return resp, nil
}

resp, err := b.apiRequest(methodName, parameters)
if err != nil {
return nil, fmt.Errorf("decode json: %w", err)
return nil, fmt.Errorf("request: %w", err)
}
return resp, nil
}

b.log.Debugf("API response %s: %s", methodName, apiResp.String())
func (b *Bot) apiRequest(methodName string, parameters interface{}) (*apiResponse, error) {
url := b.apiURL + "/bot" + b.token + "/" + methodName

return apiResp, nil
buffer := &bytes.Buffer{}
err := json.NewEncoder(buffer).Encode(parameters)
if err != nil {
return nil, fmt.Errorf("encode json: %w", err)
}

return b.callAPI(methodName, url, contentTypeJSON, buffer)
}

func (b *Bot) apiRequestMultipartFormData(methodName string,
Expand Down Expand Up @@ -218,23 +243,26 @@ func (b *Bot) apiRequestMultipartFormData(methodName string,

err := writer.Close()
if err != nil {
return nil, err
return nil, fmt.Errorf("closing writer: %w", err)
}

return b.callAPI(methodName, url, writer.FormDataContentType(), buffer)
}

func (b *Bot) callAPI(methodName, url, contentType string, buffer *bytes.Buffer) (*apiResponse, error) {
req := fasthttp.AcquireRequest()
req.SetRequestURI(url)
req.Header.SetContentType(writer.FormDataContentType())
req.Header.SetContentType(contentType)
req.Header.SetMethod(fasthttp.MethodPost)
req.SetBodyRaw(buffer.Bytes())

resp := fasthttp.AcquireResponse()
err = b.client.Do(req, resp)
err := b.client.Do(req, resp)
if err != nil {
return nil, fmt.Errorf("multipart request: %w", err)
return nil, fmt.Errorf("request: %w", err)
}

if statusCode := resp.StatusCode(); statusCode >= fasthttp.StatusInternalServerError {
b.log.Errorf("Internal server error, status code: %d", statusCode)
return nil, fmt.Errorf("internal server error: %d", statusCode)
}

Expand All @@ -249,61 +277,6 @@ func (b *Bot) apiRequestMultipartFormData(methodName string,
return apiResp, nil
}

func (b *Bot) performRequest(methodName string, parameters, v interface{}) error {
resp, err := b.executeRequest(methodName, parameters)
if err != nil {
return fmt.Errorf("execute: %w", err)
}

if !resp.Ok {
return fmt.Errorf("api: %w", resp.APIError)
}

if resp.Result != nil {
err = json.Unmarshal(resp.Result, &v)
if err != nil {
return fmt.Errorf("unmarshal to %s: %w", reflect.TypeOf(v), err)
}
}

return nil
}

func (b *Bot) executeRequest(methodName string, parameters interface{}) (*apiResponse, error) {
isDirectFile := false
var fileParams map[string]*os.File

p, ok := parameters.(fileCompatible)
if ok {
fileParams = p.fileParameters()
for _, file := range fileParams {
if file != nil {
isDirectFile = true
break
}
}
}

if isDirectFile {
params, err := toParams(parameters)
if err != nil {
return nil, fmt.Errorf("get params: %w", err)
}

resp, err := b.apiRequestMultipartFormData(methodName, params, fileParams)
if err != nil {
return nil, fmt.Errorf("request multipart form data: %w", err)
}
return resp, nil
}

resp, err := b.apiRequest(methodName, parameters)
if err != nil {
return nil, fmt.Errorf("request: %w", err)
}
return resp, nil
}

func toParams(v interface{}) (map[string]string, error) {
paramsStruct := reflect.ValueOf(v).Elem()
if paramsStruct.Kind() != reflect.Struct {
Expand Down
2 changes: 1 addition & 1 deletion helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func respondWithError(ctx *fasthttp.RequestCtx, err error) {
errMsg, _ := json.Marshal(map[string]string{"error": err.Error()})

ctx.SetStatusCode(fasthttp.StatusBadRequest)
ctx.SetContentType(jsonContentType)
ctx.SetContentType(contentTypeJSON)

_, _ = ctx.Write(errMsg)
}
5 changes: 5 additions & 0 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ type logMode string
const (
debugMode logMode = "DEBUG"
errorMode logMode = "ERROR"

ansiReset = "\u001B[0m"
ansiRed = "\u001B[31m"
ansiYellow = "\u001B[33m"
ansiBlue = "\u001B[34m"
)

type logger struct {
Expand Down

0 comments on commit 14a2817

Please sign in to comment.