261 lines
7.4 KiB
Go
261 lines
7.4 KiB
Go
/*
|
||
* Copyright (c) 2020 Alex <alex@webz.asia>
|
||
*
|
||
* 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 <alex@webz.asia>
|
||
* @copyright Copyright (c) 2020 Alex <alex@webz.asia>
|
||
* @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
|
||
}
|