373 lines
8.2 KiB
Go
373 lines
8.2 KiB
Go
// Copyright 2021 Harran Ali <harran.m@gmail.com>. All rights reserved.
|
|
// Copyright (c) 2024 Zeni Kim <zenik@smarteching.com>
|
|
// Use of this source code is governed by MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package core
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"git.smarteching.com/goffee/core/logger"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type Context struct {
|
|
Request *Request
|
|
Response *Response
|
|
GetValidator func() *Validator
|
|
GetJWT func() *JWT
|
|
GetGorm func() *gorm.DB
|
|
GetCache func() *Cache
|
|
GetHashing func() *Hashing
|
|
GetMailer func() *Mailer
|
|
GetEventsManager func() *EventsManager
|
|
GetLogger func() *logger.Logger
|
|
}
|
|
|
|
// TODO enhance
|
|
func (c *Context) DebugAny(variable interface{}) {
|
|
var formatted string
|
|
m := reflect.ValueOf(variable)
|
|
if m.Kind() == reflect.Pointer {
|
|
formatted = fmt.Sprintf("\n\nType: [pointer] %v (%v) \nMemory Address: %v \nValue: %v\n\n", m.Type(), m.Elem().Kind(), m, m.Elem())
|
|
} else {
|
|
formatted = fmt.Sprintf("\n\nType: %v (%v) \nValue: %v\n\n", m.Type(), m.Kind(), variable)
|
|
}
|
|
fmt.Println(formatted)
|
|
c.Response.HttpResponseWriter.Write([]byte(formatted))
|
|
}
|
|
|
|
func (c *Context) Next() {
|
|
ResolveApp().Next(c)
|
|
}
|
|
|
|
func (c *Context) prepare(ctx *Context) {
|
|
ctx.Request.httpRequest.ParseMultipartForm(int64(app.Config.Request.MaxUploadFileSize))
|
|
}
|
|
|
|
func (c *Context) GetPathParam(key string) interface{} {
|
|
return c.Request.httpPathParams.ByName(key)
|
|
}
|
|
|
|
func (c *Context) GetRequestParam(key string) interface{} {
|
|
return c.Request.httpRequest.FormValue(key)
|
|
}
|
|
|
|
func (c *Context) RequestParamExists(key string) bool {
|
|
return c.Request.httpRequest.Form.Has(key)
|
|
}
|
|
|
|
func (c *Context) GetRequesForm() interface{} {
|
|
return c.Request.httpRequest.Form
|
|
}
|
|
|
|
func (c *Context) GetRequesBodyMap() map[string]interface{} {
|
|
var dat map[string]any
|
|
body := c.Request.httpRequest.Body
|
|
if body != nil {
|
|
if content, err := io.ReadAll(body); err == nil {
|
|
json.Unmarshal(content, &dat)
|
|
}
|
|
}
|
|
return dat
|
|
}
|
|
|
|
// get json body and bind to dest interface
|
|
func (c *Context) GetRequesBodyStruct(dest interface{}) error {
|
|
body := c.Request.httpRequest.Body
|
|
if body != nil {
|
|
value := reflect.ValueOf(dest)
|
|
if value.Kind() != reflect.Ptr {
|
|
fmt.Println("dest is not a pointer")
|
|
return errors.New("dest is not a pointer")
|
|
}
|
|
err := json.NewDecoder(body).Decode(dest)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *Context) GetHeader(key string) string {
|
|
return c.Request.httpRequest.Header.Get(key)
|
|
}
|
|
|
|
func (c *Context) GetCookie() (UserCookie, error) {
|
|
|
|
user, err := GetCookie(c.Request.httpRequest)
|
|
if err != nil {
|
|
return user, err
|
|
}
|
|
return user, nil
|
|
}
|
|
|
|
func (c *Context) GetUploadedFile(name string) *UploadedFileInfo {
|
|
file, fileHeader, err := c.Request.httpRequest.FormFile(name)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("error with file,[%v]", err.Error()))
|
|
}
|
|
defer file.Close()
|
|
ext := strings.TrimPrefix(path.Ext(fileHeader.Filename), ".")
|
|
tmpFilePath := filepath.Join(os.TempDir(), fileHeader.Filename)
|
|
tmpFile, err := os.Create(tmpFilePath)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("error with file,[%v]", err.Error()))
|
|
}
|
|
buff := make([]byte, 100)
|
|
for {
|
|
n, err := file.Read(buff)
|
|
if err != nil && err != io.EOF {
|
|
panic("error with uploaded file")
|
|
}
|
|
if n == 0 {
|
|
break
|
|
}
|
|
n, _ = tmpFile.Write(buff[:n])
|
|
}
|
|
tmpFileInfo, err := os.Stat(tmpFilePath)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("error with file,[%v]", err.Error()))
|
|
}
|
|
defer tmpFile.Close()
|
|
uploadedFileInfo := &UploadedFileInfo{
|
|
FullPath: tmpFilePath,
|
|
Name: fileHeader.Filename,
|
|
NameWithoutExtension: strings.TrimSuffix(fileHeader.Filename, path.Ext(fileHeader.Filename)),
|
|
Extension: ext,
|
|
Size: int(tmpFileInfo.Size()),
|
|
}
|
|
return uploadedFileInfo
|
|
}
|
|
|
|
func (c *Context) MoveFile(sourceFilePath string, destFolderPath string) error {
|
|
o := syscall.Umask(0)
|
|
defer syscall.Umask(o)
|
|
newFileName := filepath.Base(sourceFilePath)
|
|
os.MkdirAll(destFolderPath, 766)
|
|
srcFileInfo, err := os.Stat(sourceFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !srcFileInfo.Mode().IsRegular() {
|
|
return errors.New("can not move file, not in a regular mode")
|
|
}
|
|
srcFile, err := os.Open(sourceFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer srcFile.Close()
|
|
destFilePath := filepath.Join(destFolderPath, newFileName)
|
|
destFile, err := os.Create(destFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
buff := make([]byte, 1024*8)
|
|
for {
|
|
n, err := srcFile.Read(buff)
|
|
if err != nil && err != io.EOF {
|
|
panic(fmt.Sprintf("error moving file %v", sourceFilePath))
|
|
}
|
|
if n == 0 {
|
|
break
|
|
}
|
|
_, err = destFile.Write(buff[:n])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
destFile.Close()
|
|
err = os.Remove(sourceFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *Context) CopyFile(sourceFilePath string, destFolderPath string) error {
|
|
o := syscall.Umask(0)
|
|
defer syscall.Umask(o)
|
|
newFileName := filepath.Base(sourceFilePath)
|
|
os.MkdirAll(destFolderPath, 766)
|
|
srcFileInfo, err := os.Stat(sourceFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !srcFileInfo.Mode().IsRegular() {
|
|
return errors.New("can not move file, not in a regular mode")
|
|
}
|
|
srcFile, err := os.Open(sourceFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer srcFile.Close()
|
|
destFilePath := filepath.Join(destFolderPath, newFileName)
|
|
destFile, err := os.Create(destFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
buff := make([]byte, 1024*8)
|
|
for {
|
|
n, err := srcFile.Read(buff)
|
|
if err != nil && err != io.EOF {
|
|
panic(fmt.Sprintf("error moving file %v", sourceFilePath))
|
|
}
|
|
if n == 0 {
|
|
break
|
|
}
|
|
_, err = destFile.Write(buff[:n])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
destFile.Close()
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Context) MapToJson(v any) string {
|
|
r := reflect.ValueOf(v)
|
|
if r.Kind() != reflect.Map {
|
|
panic("parameter is not a map")
|
|
}
|
|
j, err := json.Marshal(v)
|
|
if err != nil {
|
|
panic(err.Error())
|
|
}
|
|
return string(j)
|
|
}
|
|
|
|
type UploadedFileInfo struct {
|
|
FullPath string
|
|
Name string
|
|
NameWithoutExtension string
|
|
Extension string
|
|
Size int
|
|
}
|
|
|
|
func (c *Context) GetBaseDirPath() string {
|
|
return basePath
|
|
}
|
|
|
|
func (c *Context) CastToString(value interface{}) string {
|
|
if !basicType(value) {
|
|
panic("can not cast to string")
|
|
}
|
|
|
|
return fmt.Sprintf("%v", value)
|
|
}
|
|
|
|
func (c Context) GetUserAgent() string {
|
|
return c.Request.httpRequest.UserAgent()
|
|
}
|
|
|
|
func (c *Context) CastToInt(value interface{}) int {
|
|
var i int
|
|
if !basicType(value) {
|
|
panic("can not cast to int")
|
|
}
|
|
i, ok := value.(int)
|
|
if ok {
|
|
return i
|
|
}
|
|
_i, ok := value.(int32)
|
|
if ok {
|
|
i := int(_i)
|
|
return i
|
|
}
|
|
_ii, ok := value.(int64)
|
|
if ok {
|
|
i := int(_ii)
|
|
return i
|
|
}
|
|
f, ok := value.(float32)
|
|
if ok {
|
|
i := int(f)
|
|
return i
|
|
}
|
|
ff, ok := value.(float64)
|
|
if ok {
|
|
i := int(ff)
|
|
return i
|
|
}
|
|
s, ok := value.(string)
|
|
if ok {
|
|
fff, err := strconv.ParseFloat(s, 64)
|
|
if err != nil {
|
|
panic("error casting to int")
|
|
}
|
|
i = int(fff)
|
|
return i
|
|
}
|
|
panic("error casting to int")
|
|
}
|
|
|
|
func (c *Context) CastToFloat(value interface{}) float64 {
|
|
if !basicType(value) {
|
|
panic("can not cast to float")
|
|
}
|
|
v := reflect.ValueOf(value)
|
|
if v.Kind() == reflect.Pointer {
|
|
v = v.Elem()
|
|
}
|
|
var str string
|
|
var ok bool
|
|
if v.Kind() == reflect.Float64 {
|
|
f, ok := value.(float64)
|
|
if !ok {
|
|
panic("error casting to float")
|
|
}
|
|
return f
|
|
}
|
|
if v.Kind() == reflect.Float32 {
|
|
s := fmt.Sprintf("%v", value)
|
|
f, err := strconv.ParseFloat(s, 64)
|
|
if err != nil {
|
|
panic("error casting to float")
|
|
}
|
|
return f
|
|
}
|
|
if v.Kind() == reflect.String {
|
|
str, ok = value.(string)
|
|
if !ok {
|
|
panic("error casting to float")
|
|
}
|
|
}
|
|
if v.CanInt() {
|
|
i, ok := value.(int)
|
|
if !ok {
|
|
panic("error casting to float")
|
|
}
|
|
str = fmt.Sprintf("%v.0", i)
|
|
}
|
|
f, err := strconv.ParseFloat(str, 64)
|
|
if err != nil {
|
|
panic("error casting to float")
|
|
}
|
|
return f
|
|
}
|
|
|
|
func basicType(value interface{}) bool {
|
|
v := reflect.ValueOf(value)
|
|
if v.Kind() == reflect.Pointer {
|
|
v = v.Elem()
|
|
}
|
|
if !(v.Kind() == reflect.Array ||
|
|
v.Kind() == reflect.Slice ||
|
|
v.Kind() == reflect.Map ||
|
|
v.Kind() == reflect.Struct ||
|
|
v.Kind() == reflect.Interface ||
|
|
v.Kind() == reflect.Func) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|