/* * Copyright (c) 2020 Alex * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * @author Alex * @copyright Copyright (c) 2020 Alex * @since 29.12.2020 * */ package dtoLib import ( "errors" "fmt" "net/http" "net/url" "github.com/go-convert/fields" ) type PaginationContainer struct { Pagination Pagination `json:"pagination"` } type Pagination struct { Page int `json:"page"` PerPage int `json:"per_page"` Total int `json:"total"` } type ApiResponse struct { Code int32 `json:"code"` Type string `json:"type"` Message string `json:"message"` Data interface{} `json:"data"` *PaginationContainer } type ApiErrorResponse struct { Code int32 `json:"code"` Type string `json:"type"` Message string `json:"message"` Errors []error `json:"errors"` Data interface{} `json:"data"` } type SearchParams url.Values // AllApiResponses returns full map of map ApiResponse structure func AllApiResponses() map[string]map[string]ApiResponse { return responseMap } // AddNewApiResponse adds new api response by name, returns error if already exists func AddNewApiResponse(name string, response map[string]ApiResponse) error { if _, ok := responseMap[name]; ok { return errors.New("this name already exists") } responseMap[name] = response return nil } // AllApiErrorResponses returns full map of map ApiErrorResponse structure func AllApiErrorResponses() map[string]map[string]ApiErrorResponse { return errorResponseMap } // AddNewApiErrorResponse adds new error api response by name, returns error if already exists func AddNewApiErrorResponse(name string, response map[string]ApiErrorResponse) error { if _, ok := errorResponseMap[name]; ok { return errors.New("this name already exists") } errorResponseMap[name] = response return nil } // NotCreated returns http response code and error response object func NotCreated(name string, errors []error) (int, ApiErrorResponse) { response, ok := errorResponseMap[name][StatusNotCreated] if ok { response.Errors = errors if len(errors) == 1 { response.Data = errors[0].Error() } } else { // fallback to other response, have to support it by default return FallbackToFailedError(name, errors) } return http.StatusNotAcceptable, response } // Created returns http response code and regular response object func Created(name string, data interface{}) (int, ApiResponse) { response, ok := responseMap[name][StatusCreated] if ok { response.Data = data } else { // fallback to other response, have to support it by default return FallbackToFailed(name) } return http.StatusCreated, response } // NotUpdated returns http response code and error response object func NotUpdated(name string, errors []error) (int, ApiErrorResponse) { response, ok := errorResponseMap[name][StatusNotUpdated] if ok { response.Errors = errors if len(errors) == 1 { response.Data = errors[0].Error() } } else { // fallback to other response, have to support it by default return FallbackToFailedError(name, errors) } return http.StatusNotAcceptable, response } // Updated returns http response code and regular response object func Updated(name string, data interface{}) (int, ApiResponse) { response, ok := responseMap[name][StatusUpdated] if ok { response.Data = data } else { // fallback to other response, have to support it by default return FallbackToFailed(name) } return http.StatusAccepted, response } // NotDeleted returns http response code and error response object func NotDeleted(name string, errors []error) (int, ApiErrorResponse) { response, ok := errorResponseMap[name][StatusNotDeleted] if ok { response.Errors = errors if len(errors) == 1 { response.Data = errors[0].Error() } } else { // fallback to other response, have to support it by default return FallbackToFailedError(name, errors) } return http.StatusNotFound, response } // Deleted returns http response code and regular response object func Deleted(name string, data interface{}) (int, ApiResponse) { response, ok := responseMap[name][StatusDeleted] if ok { response.Data = data } else { // fallback to other response, have to support it by default return FallbackToFailed(name) } return http.StatusOK, response } // NotFound returns http response code and error response object func NotFound(name string, errors []error) (int, ApiErrorResponse) { response, ok := errorResponseMap[name][StatusNotFound] if ok { response.Errors = errors if len(errors) == 1 { response.Data = errors[0].Error() } } else { // fallback to other response, have to support it by default return FallbackToFailedError(name, errors) } return http.StatusNotFound, response } // Found returns http response code and regular response object(found data and pagination) func Found(name string, data interface{}, pagination interface{}) (int, ApiResponse) { response, ok := responseMap[name][StatusFound] if ok { response.Data = data } else { // fallback to other response, have to support it by default return FallbackToFailed(name) } if nil != pagination { dtoPagination := &Pagination{} fields.Сonvert(pagination, "pagination", dtoPagination) response.PaginationContainer = &PaginationContainer{Pagination: *dtoPagination} } return http.StatusOK, response } // Ok returns http response code and regular response object func Ok(name string, data interface{}) (int, ApiResponse) { response, ok := responseMap[name][StatusOk] if ok { response.Data = data } else { // fallback to other response, have to support it by default return FallbackToFailed(name) } return http.StatusOK, response } // Failed returns http response code and error response object func Failed(name string, errors []error) (int, ApiErrorResponse) { response, ok := errorResponseMap[name][StatusFailed] if ok { response.Errors = errors if len(errors) == 1 { response.Data = errors[0].Error() } } else { // fallback to other response, have to support it by default return FallbackToFailedError(name, errors) } return http.StatusInternalServerError, response } // FallbackToFailedError returns http response code and error response object as a fallback to predefined failed error response func FallbackToFailedError(name string, errs []error) (int, ApiErrorResponse) { errs = append(errs, fmt.Errorf("fallback to failed - no proper response for '%s' type", name)) response := errorResponseMap[TypeSystem][StatusFailed] response.Errors = errs if len(errs) == 1 { response.Data = errs[0].Error() } return http.StatusInternalServerError, response } // FallbackToFailed returns http response code and regular response object as a fallback to predefined failed response func FallbackToFailed(name string) (int, ApiResponse) { response := responseMap[TypeSystem][StatusFailed] response.Data = fmt.Errorf("fallback to failed - no proper response for '%s' type", name).(interface{}) return http.StatusInternalServerError, response }