chris 2 лет назад
Родитель
Сommit
bf2822f75d

+ 4 - 2
.gitignore

@@ -1,3 +1,5 @@
-/storage/
+storage
 .idea
 .idea
-*.log
+*.log
+deploy/docker-composer/conf
+deploy/docker-composer/data

+ 125 - 111
README.md

@@ -1,86 +1,39 @@
-# Nunu - An Elegant Golang Scaffold 
+# Nunu
+[中文介绍](https://github.com/go-nunu/nunu-layout-advanced/blob/main/README_zh.md)
 
 
-[简体中文介绍](https://github.com/go-nunu/nunu-layout-advanced/blob/main/README_zh.md)
 
 
 Nunu is an application scaffold based on Golang. Its name comes from the character Nunu in League of Legends, who is a little boy riding on the shoulder of a snowman. Like Nunu, This Project also stands on the shoulders of giants, and it is composed of various third-party libraries, including gin, gorm, wire, viper, zap, golang-jwt, go-redis, testify, sonyflake, go-survey, cobra, etc. These libraries are very popular in the Golang ecosystem, and their combination can help you quickly build an efficient and reliable application.
 Nunu is an application scaffold based on Golang. Its name comes from the character Nunu in League of Legends, who is a little boy riding on the shoulder of a snowman. Like Nunu, This Project also stands on the shoulders of giants, and it is composed of various third-party libraries, including gin, gorm, wire, viper, zap, golang-jwt, go-redis, testify, sonyflake, go-survey, cobra, etc. These libraries are very popular in the Golang ecosystem, and their combination can help you quickly build an efficient and reliable application.
 
 
 ![Nunu](https://github.com/go-nunu/nunu/blob/main/.github/assets/banner.png)
 ![Nunu](https://github.com/go-nunu/nunu/blob/main/.github/assets/banner.png)
 
 
+
 ## Features
 ## Features
 
 
-- **Gin**: A fast and lightweight Golang HTTP web framework.
-- **Gorm**: A powerful Golang ORM library that supports multiple databases.
-- **Wire**: A Golang compile-time dependency injection framework.
-- **Viper**: A Golang configuration management library that supports multiple file formats.
-- **Zap**: A fast and structured Golang logging library.
-- **Golang-jwt**: A Golang JWT authentication library.
-- **Go-redis**: A Golang Redis client library.
-- **Testify**: A Golang testing toolkit that provides assertions and mocking.
-- **Sonyflake**: A Golang distributed unique ID generator library.
-- **robfig-cron**: A great Crontab library.
+- **Gin**: https://github.com/gin-gonic/gin
+- **Gorm**: https://github.com/go-gorm/gorm
+- **Wire**: https://github.com/google/wire
+- **Viper**: https://github.com/spf13/viper
+- **Zap**: https://github.com/uber-go/zap
+- **Golang-jwt**: https://github.com/golang-jwt/jwt
+- **Go-redis**: https://github.com/go-redis/redis
+- **Testify**: https://github.com/stretchr/testify
+- **Sonyflake**: https://github.com/sony/sonyflake
+- **robfig-cron**: https://github.com/robfig/cron
 - More...
 - More...
 ## Features
 ## Features
-* **Easy to use and customize**: Nunu provides a simple and intuitive API for building web applications. You can easily customize the application to meet specific needs.
-* **High performance and scalability**: Nunu is designed to be high-performance and scalable. It uses the latest technologies and best practices to ensure that your application can handle high traffic and large amounts of data.
-* **Secure and reliable**: Nunu places great emphasis on security. It provides built-in authentication, authorization, and encryption support. It also uses reliable third-party libraries to ensure that your application is secure and reliable.
+* **Low learning cost and customization**: Nunu encapsulates some popular libraries that Gopher is most familiar with. You can easily customize your application to meet specific needs.
+* **High performance and scalability**: Nunu aims to have high performance and scalability. It uses the latest technology and best practices to ensure that your application can handle high traffic and large amounts of data.
+* **Secure and reliable**: Nunu uses stable and reliable third-party libraries to ensure the security and reliability of your application.
 * **Modular and extensible**: Nunu is designed to be modular and extensible. You can easily add new features and functionality by using third-party libraries or writing your own modules.
 * **Modular and extensible**: Nunu is designed to be modular and extensible. You can easily add new features and functionality by using third-party libraries or writing your own modules.
-* **Well-documented and thoroughly tested**: Nunu is well-documented and thoroughly tested. It provides comprehensive documentation and examples to help you get started quickly. It also includes a suite of tests to ensure that your application works as expected.
-## Requirements
-To use Nunu, you need to install the following software on your system:
-
-* Golang 1.16 or higher
-* MySQL 5.7 or higher (optional)
-* Redis (optional)
-## Installation
-
-You can install Nunu with the following command:
-
-```bash
-go install github.com/go-nunu/nunu@latest
-```
-
-## Usage
-
-Using Nunu is very simple, you just need to follow these steps:
-
-1. Create a new project
-
-```bash
-nunu new my_project
-```
-
-2. Enter the project directory
+* **Complete documentation and testing**: Nunu has complete documentation and testing. It provides comprehensive documentation and examples to help you get started quickly. It also includes a set of test suites to ensure that your application works as expected.
 
 
-```bash
-cd my_project
-```
-
-3. Run the project
-
-```bash
-nunu run
-```
-
-4. Open http://localhost:8000/ in your browser, and you will see a welcome page.
+## Preview
+![Nunu](https://github.com/go-nunu/nunu/blob/main/.github/assets/iterm.png)
 
 
 ## Directory Structure
 ## Directory Structure
-
-The directory structure of Nunu is as follows:
-
-
 ```
 ```
 .
 .
 ├── cmd
 ├── cmd
-│   ├── job
-│   │   ├── wire
-│   │   │   ├── wire.go
-│   │   │   └── wire_gen.go
-│   │   └── main.go
-│   ├── migration
-│   │   ├── wire
-│   │   │   ├── wire.go
-│   │   │   └── wire_gen.go
-│   │   └── main.go
 │   └── server
 │   └── server
 │       ├── wire
 │       ├── wire
 │       │   ├── wire.go
 │       │   ├── wire.go
@@ -89,72 +42,133 @@ The directory structure of Nunu is as follows:
 ├── config
 ├── config
 │   ├── local.yml
 │   ├── local.yml
 │   └── prod.yml
 │   └── prod.yml
-├── deploy
-│   └── Dockerfile
 ├── internal
 ├── internal
-│   ├── database
-│   │   └── migration.go
+│   ├── dao
+│   │   ├── dao.go
+│   │   └── user.go
 │   ├── handler
 │   ├── handler
+│   │   ├── handler.go
 │   │   └── user.go
 │   │   └── user.go
-│   ├── job
-│   │   └── job.go
 │   ├── middleware
 │   ├── middleware
-│   │   ├── cors.go
-│   │   ├── jwt.go
-│   │   ├── log.go
-│   │   └── sign.go
+│   │   └── cors.go
 │   ├── model
 │   ├── model
 │   │   └── user.go
 │   │   └── user.go
 │   ├── provider
 │   ├── provider
 │   │   └── provider.go
 │   │   └── provider.go
-│   ├── dao
-│   │   └── user.go
 │   ├── server
 │   ├── server
 │   │   └── http.go
 │   │   └── http.go
 │   └── service
 │   └── service
-│       ├── user.go
-│       └── user_test.go
+│       ├── service.go
+│       └── user.go
 ├── pkg
 ├── pkg
 │   ├── config
 │   ├── config
 │   │   └── config.go
 │   │   └── config.go
-│   ├── db
-│   │   └── db.go
-│   ├── log
-│   │   ├── storage
-│   │   │   └── logs
-│   │   │       └── server.log
-│   │   ├── log.go
-│   │   └── log_test.go
-│   ├── md5
-│   │   └── md5.go
-│   ├── rdb
-│   │   └── redis.go
-│   ├── resp
-│   │   └── resp.go
-│   ├── sonyflake
-│   │   └── sonyflake.go
-│   └── uuid
-│       └── uuid.go
-├── storage
-│   └── logs
-│       └── server.log
-├── test
-│   └── server
-│       └── handler
-│           ├── storage
-│           │   └── logs
-│           │       └── server.log
-│           └── user_test.go
-├── web
-│   └── index.html
+│   ├── helper
+│   │   ├── md5
+│   │   │   └── md5.go
+│   │   ├── resp
+│   │   │   └── resp.go
+│   │   ├── sonyflake
+│   │   │   └── sonyflake.go
+│   │   └── uuid
+│   │       └── uuid.go
+│   ├── http
+│   │   └── http.go
+│   └── log
+│       └── log.go
 ├── LICENSE
 ├── LICENSE
 ├── README.md
 ├── README.md
 ├── README_zh.md
 ├── README_zh.md
 ├── go.mod
 ├── go.mod
 └── go.sum
 └── go.sum
+```
+
+
+This is the directory structure of a classic Golang project, which includes the following directories:
+
+- `cmd`: Contains the code for command-line applications, such as `main.go`.
+- `config`: Contains configuration files, such as `config.yaml`.
+- `internal`: Contains internal code that is not exposed externally.
+    - `dao`: Contains the code for Data Access Objects (DAOs).
+    - `handler`: Contains the code for HTTP request handlers.
+    - `middleware`: Contains the code for HTTP middleware.
+    - `model`: Contains the code for data models.
+    - `provider`: Contains the code for dependency injection.
+    - `server`: Contains the code for HTTP servers.
+    - `service`: Contains the code for business logic.
+- `pkg`: Contains reusable code that is exposed externally.
+    - `config`: Contains the code for reading configuration files.
+    - `helper`: Contains the code for helper functions.
+    - `http`: Contains HTTP-related code.
+    - `log`: Contains code related to logging.
+
+## Requirements
+To use Nunu, you need to install the following software on your system:
+
+* Golang 1.16 or higher
+* MySQL 5.7 or higher (optional)
+* Redis (optional)
+
+## Installation
+
+You can install Nunu using the following command:
+
+```bash
+go install github.com/go-nunu/nunu@latest
+```
+
+## Usage
+
+### Creating a New Project
+
+You can create a new Golang project using the following command:
+
+```bash
+nunu new projectName
+```
+
+This command will create a directory named `projectName` and generate an elegant Golang project structure within it.
 
 
+### Creating Components
 
 
+You can create handlers, services, and daos for your project using the following commands:
+
+```bash
+nunu create handler user
+nunu create service user
+nunu create dao user
+```
+or
+```
+nunu create hsd user
+```
+
+These commands will create components named `UserHandler`, `UserService`, and `UserDao`, respectively, and place them in the correct directories.
+
+### Starting the Project
+
+You can quickly start your project using the following command:
+
+```bash
+nunu run
 ```
 ```
 
 
+This command will start your Golang project and support file update hot reload.
+
+### Compiling wire.go
+
+You can quickly compile your `wire.go` file using the following command:
+
+```bash
+nunu wire
+```
+
+This command will compile your `wire.go` file and generate the required dependencies.
+
+## Contributing
+
+If you find any issues or have any improvement suggestions, please feel free to raise an issue or submit a pull request. We welcome your contributions!
+
 ## License
 ## License
-Nunu is licensed under the MIT License. For more information, see the LICENSE file.
+
+Nunu is released under the MIT license. See [LICENSE](LICENSE) for more information.

+ 123 - 110
README_zh.md

@@ -1,84 +1,37 @@
-# Nunu - 一个优雅的 Golang 脚手架
-[英文介绍](https://github.com/go-nunu/nunu-layout-advanced/blob/main/README.md)
+# Nunu
+[英文介绍](https://github.com/go-nunu/nunu/blob/main/README.md)
 
 
-Nunu是一个基于Golang的应用脚手架,它的名字来自于英雄联盟中的角色,努努是一个骑在雪怪肩膀上的小男孩,和努努一样,该项目是站在巨人的肩膀上,它是由各种第三方库组合而成的,包括gin、gorm、wire、viper、zap、golang-jwt、go-redis、testify、sonyflake、go-survey、cobra等。这些库都是Golang生态中非常流行的库,它们的组合可以帮助你快速构建一个高效、可靠的应用程序。
+Nunu是一个基于Golang的应用脚手架,它的名字来自于英雄联盟中的游戏角色,一个骑在雪怪肩膀上的小男孩,和努努一样,该项目是站在巨人的肩膀上,它是由各种第三方库组合而成的,包括gin、gorm、wire、viper、zap、golang-jwt、go-redis、testify、sonyflake、go-survey、cobra等。这些库都是Golang生态中非常流行的库,它们的组合可以帮助你快速构建一个高效、可靠的应用程序。
 
 
 ![Nunu](https://github.com/go-nunu/nunu/blob/main/.github/assets/banner.png)
 ![Nunu](https://github.com/go-nunu/nunu/blob/main/.github/assets/banner.png)
 
 
-## 功能
 
 
-- **Gin**: 一个快速和轻量级的 Golang HTTP web 框架。
-- **Gorm**: 一个强大的 Golang ORM 库,支持多种数据库。
-- **Wire**: 一个 Golang 编译时依赖注入框架。
-- **Viper**: 一个 Golang 配置管理库,支持多种文件格式。
-- **Zap**: 一个快速和结构化的 Golang 日志库。
-- **Golang-jwt**: 一个 Golang JWT 认证库。
-- **Go-redis**: 一个 Golang Redis 客户端库。
-- **Testify**: 一个 Golang 测试工具包,提供断言和模拟。
-- **Sonyflake**: 一个 Golang 分布式唯一 ID 生成器库。
-- **robfig-cron**: 一个很棒的Crontab库。
+## 功能
+- **Gin**: https://github.com/gin-gonic/gin
+- **Gorm**: https://github.com/go-gorm/gorm
+- **Wire**: https://github.com/google/wire
+- **Viper**: https://github.com/spf13/viper
+- **Zap**: https://github.com/uber-go/zap
+- **Golang-jwt**: https://github.com/golang-jwt/jwt
+- **Go-redis**: https://github.com/go-redis/redis
+- **Testify**: https://github.com/stretchr/testify
+- **Sonyflake**: https://github.com/sony/sonyflake
+- **robfig-cron**: https://github.com/robfig/cron
 - More...
 - More...
 ## 特性
 ## 特性
-* **易于使用和定制**:Nunu提供了一个简单直观的API,用于构建Web应用程序。您可以轻松定制应用程序以满足特定需求。
+* **超低学习成本和定制**:Nunu封装了Gopher最熟悉的一些流行库。您可以轻松定制应用程序以满足特定需求。
 * **高性能和可扩展性**:Nunu旨在具有高性能和可扩展性。它使用最新的技术和最佳实践,确保您的应用程序可以处理高流量和大量数据。
 * **高性能和可扩展性**:Nunu旨在具有高性能和可扩展性。它使用最新的技术和最佳实践,确保您的应用程序可以处理高流量和大量数据。
-* **安全可靠**:Nunu非常注重安全性。它提供了内置的身份验证、授权和加密支持。它还使用可靠的第三方库,确保您的应用程序安全可靠。
+* **安全可靠**:Nunu使用了稳定可靠的第三方库,确保您的应用程序安全可靠。
 * **模块化和可扩展**:Nunu旨在具有模块化和可扩展性。您可以通过使用第三方库或编写自己的模块轻松添加新功能和功能。
 * **模块化和可扩展**:Nunu旨在具有模块化和可扩展性。您可以通过使用第三方库或编写自己的模块轻松添加新功能和功能。
 * **文档完善和测试完备**:Nunu文档完善,测试完备。它提供了全面的文档和示例,帮助您快速入门。它还包括一套测试套件,确保您的应用程序按预期工作。
 * **文档完善和测试完备**:Nunu文档完善,测试完备。它提供了全面的文档和示例,帮助您快速入门。它还包括一套测试套件,确保您的应用程序按预期工作。
-## 要求
-要使用Nunu,您需要在系统上安装以下软件:
-
-* Golang 1.16或更高版本
-* MySQL5.7或更高版本(可选)
-* Redis(可选)
-## 安装
-
-你可以通过以下命令来安装Nunu:
-
-```bash
-go install github.com/go-nunu/nunu@latest
-```
-
-## 使用
-
-使用Nunu非常简单,你只需要按照以下步骤即可:
-
-1. 创建一个新的项目
-
-```bash
-nunu new my_project
-```
 
 
-2. 进入项目目录
-
-```bash
-cd my_project
-```
-
-3. 运行项目
-
-```bash
-nunu run
-```
-
-4. 在浏览器中打开 http://localhost:8000/ ,你将看到一个欢迎页面。
+## 预览
+![Nunu](https://github.com/go-nunu/nunu/blob/main/.github/assets/iterm.png)
 
 
 ## 目录结构
 ## 目录结构
-
-Nunu的目录结构如下:
-
 ```
 ```
 .
 .
 ├── cmd
 ├── cmd
-│   ├── job
-│   │   ├── wire
-│   │   │   ├── wire.go
-│   │   │   └── wire_gen.go
-│   │   └── main.go
-│   ├── migration
-│   │   ├── wire
-│   │   │   ├── wire.go
-│   │   │   └── wire_gen.go
-│   │   └── main.go
 │   └── server
 │   └── server
 │       ├── wire
 │       ├── wire
 │       │   ├── wire.go
 │       │   ├── wire.go
@@ -87,72 +40,132 @@ Nunu的目录结构如下:
 ├── config
 ├── config
 │   ├── local.yml
 │   ├── local.yml
 │   └── prod.yml
 │   └── prod.yml
-├── deploy
-│   └── Dockerfile
 ├── internal
 ├── internal
-│   ├── database
-│   │   └── migration.go
+│   ├── dao
+│   │   ├── dao.go
+│   │   └── user.go
 │   ├── handler
 │   ├── handler
+│   │   ├── handler.go
 │   │   └── user.go
 │   │   └── user.go
-│   ├── job
-│   │   └── job.go
 │   ├── middleware
 │   ├── middleware
-│   │   ├── cors.go
-│   │   ├── jwt.go
-│   │   ├── log.go
-│   │   └── sign.go
+│   │   └── cors.go
 │   ├── model
 │   ├── model
 │   │   └── user.go
 │   │   └── user.go
 │   ├── provider
 │   ├── provider
 │   │   └── provider.go
 │   │   └── provider.go
-│   ├── dao
-│   │   └── user.go
 │   ├── server
 │   ├── server
 │   │   └── http.go
 │   │   └── http.go
 │   └── service
 │   └── service
-│       ├── user.go
-│       └── user_test.go
+│       ├── service.go
+│       └── user.go
 ├── pkg
 ├── pkg
 │   ├── config
 │   ├── config
 │   │   └── config.go
 │   │   └── config.go
-│   ├── db
-│   │   └── db.go
-│   ├── log
-│   │   ├── storage
-│   │   │   └── logs
-│   │   │       └── server.log
-│   │   ├── log.go
-│   │   └── log_test.go
-│   ├── md5
-│   │   └── md5.go
-│   ├── rdb
-│   │   └── redis.go
-│   ├── resp
-│   │   └── resp.go
-│   ├── sonyflake
-│   │   └── sonyflake.go
-│   └── uuid
-│       └── uuid.go
-├── storage
-│   └── logs
-│       └── server.log
-├── test
-│   └── server
-│       └── handler
-│           ├── storage
-│           │   └── logs
-│           │       └── server.log
-│           └── user_test.go
-├── web
-│   └── index.html
+│   ├── helper
+│   │   ├── md5
+│   │   │   └── md5.go
+│   │   ├── resp
+│   │   │   └── resp.go
+│   │   ├── sonyflake
+│   │   │   └── sonyflake.go
+│   │   └── uuid
+│   │       └── uuid.go
+│   ├── http
+│   │   └── http.go
+│   └── log
+│       └── log.go
 ├── LICENSE
 ├── LICENSE
 ├── README.md
 ├── README.md
 ├── README_zh.md
 ├── README_zh.md
 ├── go.mod
 ├── go.mod
 └── go.sum
 └── go.sum
+```
+
+这是一个经典的Golang 项目的目录结构,包含以下目录:
+
+- `cmd`:存放命令行应用的代码,例如 `main.go`。
+- `config`:存放配置文件,例如 `config.yaml`。
+- `internal`:存放项目内部的代码,不对外暴露。
+  - `dao`:存放数据访问对象(Data Access Object)的代码。
+  - `handler`:存放 HTTP 请求处理器的代码。
+  - `middleware`:存放 HTTP 中间件的代码。
+  - `model`:存放数据模型的代码。
+  - `provider`:存放依赖注入的代码。
+  - `server`:存放 HTTP 服务器的代码。
+  - `service`:存放业务逻辑的代码。
+- `pkg`:存放可重用的代码,对外暴露。
+  - `config`:存放读取配置文件的代码。
+  - `helper`:存放辅助函数的代码。
+  - `http`:存放 HTTP 相关的代码。
+  - `log`:存放日志相关的代码。
 
 
+## 要求
+要使用Nunu,您需要在系统上安装以下软件:
 
 
+* Golang 1.16或更高版本
+* MySQL5.7或更高版本(可选)
+* Redis(可选)
+
+
+## 安装
+
+您可以通过以下命令安装Nunu:
+
+```bash
+go install github.com/go-nunu/nunu@latest
 ```
 ```
 
 
+## 使用
+
+### 创建新项目
+
+您可以使用以下命令创建一个新的Golang项目:
+
+```bash
+nunu new projectName
+```
+
+此命令将创建一个名为`projectName`的目录,并在其中生成一个优雅的Golang项目结构。
+
+### 创建组件
+
+您可以使用以下命令为项目创建handler、service和dao等组件:
+
+```bash
+nunu create handler user
+nunu create service user
+nunu create dao user
+```
+或
+```
+nunu create hsd user
+```
+这些命令将分别创建一个名为`UserHandler`、`UserService`和`UserDao`的组件,并将它们放置在正确的目录中。
+
+### 启动项目
+
+您可以使用以下命令快速启动项目:
+
+```bash
+nunu run
+```
+
+此命令将启动您的Golang项目,并支持文件更新热重启。
+
+### 编译wire.go
+
+您可以使用以下命令快速编译`wire.go`:
+
+```bash
+nunu wire
+```
+
+此命令将编译您的`wire.go`文件,并生成所需的依赖项。
+
+## 贡献
+
+如果您发现任何问题或有任何改进意见,请随时提出问题或提交拉取请求。我们非常欢迎您的贡献!
+
 ## 许可证
 ## 许可证
-Nunu根据MIT许可证获得许可。有关更多信息,请参见LICENSE文件。
+
+Nunu是根据MIT许可证发布的。有关更多信息,请参见[LICENSE](LICENSE)文件。

+ 3 - 4
config/local.yml

@@ -18,10 +18,9 @@ data:
     write_timeout: 0.2s
     write_timeout: 0.2s
 
 
 log:
 log:
-  # log配置,stdout在debug级别才会开启
-  # 生产环境采用json结构化日志,方便elk采集
-  log_level: "debug"           # 高级别会过滤掉低级别的日志,debug<info<warn<error<fatal<panic
-  log_file_name: "./storage/logs/server.log"  #zap 业务日志路径
+  log_level: debug
+  encoding: console           # json or console
+  log_file_name: "./storage/logs/server.log"
   max_backups: 30              # 日志文件最多保存多少个备份
   max_backups: 30              # 日志文件最多保存多少个备份
   max_age: 7                   #  文件最多保存多少天
   max_age: 7                   #  文件最多保存多少天
   max_size: 1024               #  每个日志文件保存的最大尺寸 单位:M
   max_size: 1024               #  每个日志文件保存的最大尺寸 单位:M

+ 6 - 7
config/prod.yml

@@ -1,4 +1,4 @@
-env: prod
+env: local
 http:
 http:
   port: 8000
   port: 8000
 security:
 security:
@@ -9,19 +9,18 @@ security:
     key: 1234
     key: 1234
 data:
 data:
   mysql:
   mysql:
-    dns: root:123456@tcp(127.0.0.1:3306)/gin-db?charset=utf8mb4&parseTime=True&loc=Local
+    user: root:123456@tcp(127.0.0.1:3380)/user?charset=utf8mb4&parseTime=True&loc=Local
   redis:
   redis:
     addr: 127.0.0.1:6350
     addr: 127.0.0.1:6350
-    password: "123456"
+    password: ""
     db: 0
     db: 0
     read_timeout: 0.2s
     read_timeout: 0.2s
     write_timeout: 0.2s
     write_timeout: 0.2s
 
 
 log:
 log:
-  # log配置,stdout在debug级别才会开启
-  # 生产环境采用json结构化日志,方便elk采集
-  log_level: "debug"           # 高级别会过滤掉低级别的日志,debug<info<warn<error<fatal<panic
-  log_file_name: "./storage/logs/server.log"  #zap 业务日志路径
+  log_level: info
+  encoding: json           # json or console
+  log_file_name: "./storage/logs/server.log"
   max_backups: 30              # 日志文件最多保存多少个备份
   max_backups: 30              # 日志文件最多保存多少个备份
   max_age: 7                   #  文件最多保存多少天
   max_age: 7                   #  文件最多保存多少天
   max_size: 1024               #  每个日志文件保存的最大尺寸 单位:M
   max_size: 1024               #  每个日志文件保存的最大尺寸 单位:M

+ 6 - 21
internal/middleware/jwt.go

@@ -50,19 +50,12 @@ func (j *JWT) ParseToken(tokenString string) (*MyCustomClaims, error) {
 	}
 	}
 }
 }
 
 
-func NoAuth(log *log.Logger) gin.HandlerFunc {
-	return func(ctx *gin.Context) {
-		log.WithContext(ctx).Info("建立请求")
-		ctx.Next()
-	}
-}
-
 // StrictAuth 严格权限
 // StrictAuth 严格权限
-func StrictAuth(j *JWT, log *log.Logger) gin.HandlerFunc {
+func StrictAuth(j *JWT, logger *log.Logger) gin.HandlerFunc {
 	return func(ctx *gin.Context) {
 	return func(ctx *gin.Context) {
 		tokenString := ctx.Request.Header.Get("Authorization")
 		tokenString := ctx.Request.Header.Get("Authorization")
 		if tokenString == "" {
 		if tokenString == "" {
-			log.WithContext(ctx).Warn("请求未携带token,无权限访问", zap.Any("data", map[string]interface{}{
+			logger.WithContext(ctx).Warn("请求未携带token,无权限访问", zap.Any("data", map[string]interface{}{
 				"url":    ctx.Request.URL,
 				"url":    ctx.Request.URL,
 				"params": ctx.Params,
 				"params": ctx.Params,
 			}))
 			}))
@@ -74,7 +67,7 @@ func StrictAuth(j *JWT, log *log.Logger) gin.HandlerFunc {
 		// parseToken 解析token包含的信息
 		// parseToken 解析token包含的信息
 		claims, err := j.ParseToken(tokenString)
 		claims, err := j.ParseToken(tokenString)
 		if err != nil {
 		if err != nil {
-			log.WithContext(ctx).Error("token error", zap.Any("data", map[string]interface{}{
+			logger.WithContext(ctx).Error("token error", zap.Any("data", map[string]interface{}{
 				"url":    ctx.Request.URL,
 				"url":    ctx.Request.URL,
 				"params": ctx.Params,
 				"params": ctx.Params,
 			}))
 			}))
@@ -85,12 +78,12 @@ func StrictAuth(j *JWT, log *log.Logger) gin.HandlerFunc {
 
 
 		// 继续交由下一个路由处理,并将解析出的信息传递下去
 		// 继续交由下一个路由处理,并将解析出的信息传递下去
 		ctx.Set("claims", claims)
 		ctx.Set("claims", claims)
-		recoveryLoggerFunc(ctx, log)
+		recoveryLoggerFunc(ctx, logger)
 		ctx.Next()
 		ctx.Next()
 	}
 	}
 }
 }
 
 
-func NoStrictAuth(j *JWT, log *log.Logger) gin.HandlerFunc {
+func NoStrictAuth(j *JWT, logger *log.Logger) gin.HandlerFunc {
 	return func(ctx *gin.Context) {
 	return func(ctx *gin.Context) {
 		tokenString := ctx.Request.Header.Get("Authorization")
 		tokenString := ctx.Request.Header.Get("Authorization")
 		if tokenString == "" {
 		if tokenString == "" {
@@ -100,7 +93,6 @@ func NoStrictAuth(j *JWT, log *log.Logger) gin.HandlerFunc {
 			tokenString = ctx.Query("accessToken")
 			tokenString = ctx.Query("accessToken")
 		}
 		}
 		if tokenString == "" {
 		if tokenString == "" {
-			log.WithContext(ctx).Info("建立请求")
 			ctx.Next()
 			ctx.Next()
 			return
 			return
 		}
 		}
@@ -108,25 +100,18 @@ func NoStrictAuth(j *JWT, log *log.Logger) gin.HandlerFunc {
 		// parseToken 解析token包含的信息
 		// parseToken 解析token包含的信息
 		claims, err := j.ParseToken(tokenString)
 		claims, err := j.ParseToken(tokenString)
 		if err != nil {
 		if err != nil {
-			log.WithContext(ctx).Info("建立请求")
 			ctx.Next()
 			ctx.Next()
 			return
 			return
 		}
 		}
 
 
 		// 继续交由下一个路由处理,并将解析出的信息传递下去
 		// 继续交由下一个路由处理,并将解析出的信息传递下去
 		ctx.Set("claims", claims)
 		ctx.Set("claims", claims)
-		recoveryLoggerFunc(ctx, log)
+		recoveryLoggerFunc(ctx, logger)
 		ctx.Next()
 		ctx.Next()
 	}
 	}
 }
 }
 
 
 func recoveryLoggerFunc(ctx *gin.Context, logger *log.Logger) {
 func recoveryLoggerFunc(ctx *gin.Context, logger *log.Logger) {
-	if ctx.Request.URL.Path == "/cos/object" && ctx.Request.Method == "POST" {
-		return
-	}
 	userInfo := ctx.MustGet("claims").(*MyCustomClaims)
 	userInfo := ctx.MustGet("claims").(*MyCustomClaims)
 	logger.NewContext(ctx, zap.Int64("UserId", userInfo.UserId))
 	logger.NewContext(ctx, zap.Int64("UserId", userInfo.UserId))
-	logger.WithContext(ctx).Info("建立请求")
-
-	// 统计
 }
 }

+ 10 - 30
internal/middleware/log.go

@@ -2,7 +2,6 @@ package middleware
 
 
 import (
 import (
 	"bytes"
 	"bytes"
-	"context"
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
@@ -12,35 +11,29 @@ import (
 	"go.uber.org/zap"
 	"go.uber.org/zap"
 	"io"
 	"io"
 	"strconv"
 	"strconv"
-	"strings"
 	"time"
 	"time"
 )
 )
 
 
-func GinContextToContextMiddleware() gin.HandlerFunc {
-	return func(c *gin.Context) {
-		ctx := context.WithValue(c.Request.Context(), "GinContextKey", c)
-		c.Request = c.Request.WithContext(ctx)
-		c.Next()
-	}
-}
-func RequestLogMiddleware(log *log.Logger) gin.HandlerFunc {
+func RequestLogMiddleware(logger *log.Logger) gin.HandlerFunc {
 	return func(ctx *gin.Context) {
 	return func(ctx *gin.Context) {
+
 		// 每次请求都初始化一次配置
 		// 每次请求都初始化一次配置
 		trace := md5.Md5(uuid.GenUUID())
 		trace := md5.Md5(uuid.GenUUID())
-		log.NewContext(ctx, zap.String("trace", trace))
-		log.NewContext(ctx, zap.String("request_method", ctx.Request.Method))
+		logger.NewContext(ctx, zap.String("trace", trace))
+		logger.NewContext(ctx, zap.String("request_method", ctx.Request.Method))
 		headers, _ := json.Marshal(ctx.Request.Header)
 		headers, _ := json.Marshal(ctx.Request.Header)
-		log.NewContext(ctx, zap.String("request_headers", string(headers)))
-		log.NewContext(ctx, zap.String("request_url", ctx.Request.URL.String()))
+		logger.NewContext(ctx, zap.String("request_headers", string(headers)))
+		logger.NewContext(ctx, zap.String("request_url", ctx.Request.URL.String()))
 		if ctx.Request.Body != nil {
 		if ctx.Request.Body != nil {
 			bodyBytes, _ := ctx.GetRawData()
 			bodyBytes, _ := ctx.GetRawData()
 			ctx.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) // 关键点
 			ctx.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) // 关键点
-			log.NewContext(ctx, zap.String("request_params", string(bodyBytes)))
+			logger.NewContext(ctx, zap.String("request_params", string(bodyBytes)))
 		}
 		}
+		logger.WithContext(ctx).Info("Request")
 		ctx.Next()
 		ctx.Next()
 	}
 	}
 }
 }
-func ResponseLogMiddleware(log *log.Logger) gin.HandlerFunc {
+func ResponseLogMiddleware(logger *log.Logger) gin.HandlerFunc {
 	return func(ctx *gin.Context) {
 	return func(ctx *gin.Context) {
 		blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: ctx.Writer}
 		blw := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: ctx.Writer}
 		ctx.Writer = blw
 		ctx.Writer = blw
@@ -48,20 +41,7 @@ func ResponseLogMiddleware(log *log.Logger) gin.HandlerFunc {
 		ctx.Next()
 		ctx.Next()
 		duration := int(time.Since(startTime).Milliseconds())
 		duration := int(time.Since(startTime).Milliseconds())
 		ctx.Header("X-Response-Time", strconv.Itoa(duration))
 		ctx.Header("X-Response-Time", strconv.Itoa(duration))
-		if ctx.Request.URL.Path == "/cos/object" && ctx.Request.Method == "POST" {
-			return
-		}
-		if strings.Contains(ctx.Request.URL.Path, "storage") {
-			return
-		}
-		log.WithContext(ctx).Info("响应返回", zap.Any("response_body", blw.body.String()), zap.Any("time", fmt.Sprintf("%sms", strconv.Itoa(duration))))
-		statusCode := ctx.Writer.Status()
-		fmt.Println(statusCode)
-		//if statusCode >= 400 {
-		//ok this is an request with error, let's make a record for it
-		// now print body (or log in your preferred way)
-		//fmt.Println("Response body: " + blw.body.String())
-		//}
+		logger.WithContext(ctx).Info("Response", zap.Any("response_body", blw.body.String()), zap.Any("time", fmt.Sprintf("%sms", strconv.Itoa(duration))))
 	}
 	}
 }
 }
 
 

+ 1 - 1
internal/middleware/sign.go

@@ -11,7 +11,7 @@ import (
 	"strings"
 	"strings"
 )
 )
 
 
-func SignMiddleware(log *log.Logger, conf *viper.Viper) gin.HandlerFunc {
+func SignMiddleware(logger *log.Logger, conf *viper.Viper) gin.HandlerFunc {
 	return func(ctx *gin.Context) {
 	return func(ctx *gin.Context) {
 		timestamp, ok := ctx.Request.Header["Timestamp"]
 		timestamp, ok := ctx.Request.Header["Timestamp"]
 		if !ok || len(timestamp) == 0 {
 		if !ok || len(timestamp) == 0 {

+ 18 - 17
internal/server/http.go

@@ -9,40 +9,41 @@ import (
 )
 )
 
 
 func NewServerHTTP(
 func NewServerHTTP(
-	log *log.Logger,
+	logger *log.Logger,
 	jwt *middleware.JWT,
 	jwt *middleware.JWT,
 	userHandler *handler.UserHandler,
 	userHandler *handler.UserHandler,
 ) *gin.Engine {
 ) *gin.Engine {
 	gin.SetMode(gin.ReleaseMode)
 	gin.SetMode(gin.ReleaseMode)
 	r := gin.Default()
 	r := gin.Default()
+
 	r.Use(
 	r.Use(
-		middleware.RequestLogMiddleware(log),
 		middleware.CORSMiddleware(),
 		middleware.CORSMiddleware(),
-		middleware.NoAuth(log),
-		middleware.ResponseLogMiddleware(log),
+		middleware.ResponseLogMiddleware(logger),
 		//middleware.SignMiddleware(log),
 		//middleware.SignMiddleware(log),
 	)
 	)
-	r.GET("/", func(ctx *gin.Context) {
-		resp.HandleSuccess(ctx, map[string]interface{}{
-			"say": "Hi Nunu!",
-		})
-	})
 
 
-	noAuthRouter := r.Use(middleware.NoAuth(log))
+	// 无权限路由
+	noAuthRouter := r.Group("/").Use(middleware.RequestLogMiddleware(logger))
 	{
 	{
 		noAuthRouter.GET("/user", userHandler.GetUserById)
 		noAuthRouter.GET("/user", userHandler.GetUserById)
-
-	}
-	// 严格权限路由
-	strictAuthRouter := r.Use(middleware.StrictAuth(jwt, log))
-	{
-		strictAuthRouter.PUT("/user", userHandler.UpdateUser)
+		noAuthRouter.GET("/", func(ctx *gin.Context) {
+			logger.WithContext(ctx).Info("hello")
+			resp.HandleSuccess(ctx, map[string]interface{}{
+				"say": "Hi Nunu!",
+			})
+		})
 	}
 	}
 	// 非严格权限路由
 	// 非严格权限路由
-	noStrictAuthRouter := r.Use(middleware.NoStrictAuth(jwt, log))
+	noStrictAuthRouter := r.Group("/").Use(middleware.NoStrictAuth(jwt, logger), middleware.RequestLogMiddleware(logger))
 	{
 	{
 		noStrictAuthRouter.POST("/user", userHandler.CreateUser)
 		noStrictAuthRouter.POST("/user", userHandler.CreateUser)
 	}
 	}
 
 
+	// 严格权限路由
+	strictAuthRouter := r.Group("/").Use(middleware.StrictAuth(jwt, logger), middleware.RequestLogMiddleware(logger))
+	{
+		strictAuthRouter.PUT("/user", userHandler.UpdateUser)
+	}
+
 	return r
 	return r
 }
 }

+ 41 - 38
pkg/log/log.go

@@ -46,51 +46,54 @@ func initZap(conf *viper.Viper) *Logger {
 		MaxAge:     conf.GetInt("log.max_age"),     // 文件最多保存多少天
 		MaxAge:     conf.GetInt("log.max_age"),     // 文件最多保存多少天
 		Compress:   conf.GetBool("log.compress"),   // 是否压缩
 		Compress:   conf.GetBool("log.compress"),   // 是否压缩
 	}
 	}
-	// 是否 DEBUG
-	if conf.GetString("env") != "prod" {
-		core := zapcore.NewCore(
-			zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
-				TimeKey:        "ts",
-				LevelKey:       "level",
-				NameKey:        "Logger",
-				CallerKey:      "caller",
-				MessageKey:     "msg",
-				StacktraceKey:  "stacktrace",
-				LineEnding:     zapcore.DefaultLineEnding,
-				EncodeLevel:    zapcore.LowercaseColorLevelEncoder,
-				EncodeTime:     timeEncoder,
-				EncodeDuration: zapcore.SecondsDurationEncoder,
-				EncodeCaller:   zapcore.FullCallerEncoder,
-			}), // 编码器配置
-			//zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)),      // 打印到控制台
-			zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制台和文件
-			level, // 日志级别
-		)
-
-		// 开启开发模式,堆栈跟踪
-		caller := zap.AddCaller()
-		// 开启文件及行号
-		development := zap.Development()
-		// 设置初始化字段
-		//filed := zap.Fields(zap.String("serviceName", "serviceName"))
-		// 构造日志
-		return &Logger{zap.New(core, caller, development, zap.AddStacktrace(zap.ErrorLevel))}
 
 
+	var encoder zapcore.Encoder
+	if conf.GetString("log.encoding") == "console" {
+		encoder = zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
+			TimeKey:        "ts",
+			LevelKey:       "level",
+			NameKey:        "Logger",
+			CallerKey:      "caller",
+			MessageKey:     "msg",
+			StacktraceKey:  "stacktrace",
+			LineEnding:     zapcore.DefaultLineEnding,
+			EncodeLevel:    zapcore.LowercaseColorLevelEncoder,
+			EncodeTime:     timeEncoder,
+			EncodeDuration: zapcore.SecondsDurationEncoder,
+			EncodeCaller:   zapcore.FullCallerEncoder,
+		})
 	} else {
 	} else {
-		encoderConfig := zap.NewProductionEncoderConfig()
-		return &Logger{zap.New(zapcore.NewCore(
-			zapcore.NewJSONEncoder(encoderConfig),                                           // 编码器配置(生产环境使用json)
-			zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制台和文件
-			level, // 日志级别
-		), zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))}
-
+		encoder = zapcore.NewJSONEncoder(zapcore.EncoderConfig{
+			TimeKey:        "ts",
+			LevelKey:       "level",
+			NameKey:        "logger",
+			CallerKey:      "caller",
+			FunctionKey:    zapcore.OmitKey,
+			MessageKey:     "msg",
+			StacktraceKey:  "stacktrace",
+			LineEnding:     zapcore.DefaultLineEnding,
+			EncodeLevel:    zapcore.LowercaseLevelEncoder,
+			EncodeTime:     zapcore.EpochTimeEncoder,
+			EncodeDuration: zapcore.SecondsDurationEncoder,
+			EncodeCaller:   zapcore.ShortCallerEncoder,
+		})
 	}
 	}
+	core := zapcore.NewCore(
+		encoder, // 编码器配置
+		zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制台和文件
+		level, // 日志级别
+	)
+	if conf.GetString("env") != "prod" {
+		return &Logger{zap.New(core, zap.Development(), zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))}
+	}
+	return &Logger{zap.New(core, zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))}
+
 }
 }
 
 
 // 自定义时间编码器
 // 自定义时间编码器
 func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
 func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
-	enc.AppendString(t.Format("2006-01-02 15:04:05"))
-	//enc.AppendString(t.Format("2006-01-02 15:04:05.000000000"))
+	//enc.AppendString(t.Format("2006-01-02 15:04:05"))
+	enc.AppendString(t.Format("2006-01-02 15:04:05.000000000"))
 }
 }
 
 
 // NewContext 给指定的context添加字段
 // NewContext 给指定的context添加字段

+ 0 - 97
test/server/handler/storage/logs/server.log

@@ -1,97 +0,0 @@
-2023-06-03 00:27:49	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:33	start
-2023-06-03 00:27:49	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "0bdb3695c4ca3381d3cbbadf5b0904a2", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user", "request_params": "{\"actionType\":1,\"phone\":\"18502100065\"}"}
-2023-06-03 00:27:49	info	/Users/chris/Projects/stu/gin-starter/internal/handler/user.go:28	GetUserByID	{"sonyflake": 463376085304737894}
-2023-06-03 00:27:49	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "0bdb3695c4ca3381d3cbbadf5b0904a2", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user", "request_params": "{\"actionType\":1,\"phone\":\"18502100065\"}", "response_body": "{\"code\":1,\"message\":\"record not found\",\"data\":{}}", "time": "2ms"}
-2023-06-03 00:28:18	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:33	start
-2023-06-03 00:28:18	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "f0bba6b5830095ae2f7e56e9d7c6897e", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user", "request_params": "{\"actionType\":1,\"phone\":\"18502100065\"}"}
-2023-06-03 00:28:18	info	/Users/chris/Projects/stu/gin-starter/internal/handler/user.go:28	GetUserByID	{"sonyflake": 463376133757337702}
-2023-06-03 00:28:18	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "f0bba6b5830095ae2f7e56e9d7c6897e", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user", "request_params": "{\"actionType\":1,\"phone\":\"18502100065\"}", "response_body": "{\"code\":1,\"message\":\"record not found\",\"data\":{}}", "time": "2ms"}
-2023-06-03 00:40:03	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:40:03	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "5d1b363586f1d709bf1c4c616dbf5a42", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user", "request_params": "{\"actionType\":1,\"phone\":\"18502100065\"}"}
-2023-06-03 00:40:03	info	/Users/chris/Projects/stu/gin-starter/internal/handler/user.go:28	GetUserByID	{"sonyflake": 463377317238931558}
-2023-06-03 00:40:03	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "5d1b363586f1d709bf1c4c616dbf5a42", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user", "request_params": "{\"actionType\":1,\"phone\":\"18502100065\"}", "response_body": "{\"code\":1,\"message\":\"record not found\",\"data\":{}}", "time": "2ms"}
-2023-06-03 00:48:11	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:48:12	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "7d6f948b1edb1b283b859addb92022b9", "request_method": "POST", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user", "request_params": "{\"email\":\"5303221@gmail.com\",\"username\":\"test\"}"}
-2023-06-03 00:48:12	info	/Users/chris/Projects/stu/gin-starter/internal/handler/user.go:47	CreateUser	{"user": {"ID":1,"CreatedAt":"2023-06-03T00:48:12.007+08:00","UpdatedAt":"2023-06-03T00:48:12.007+08:00","DeletedAt":null,"Username":"test","Email":"5303221@gmail.com"}}
-2023-06-03 00:48:21	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "7d6f948b1edb1b283b859addb92022b9", "request_method": "POST", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user", "request_params": "{\"email\":\"5303221@gmail.com\",\"username\":\"test\"}", "response_body": "{\"code\":0,\"message\":\"success\",\"data\":{\"ID\":1,\"CreatedAt\":\"2023-06-03T00:48:12.007+08:00\",\"UpdatedAt\":\"2023-06-03T00:48:12.007+08:00\",\"DeletedAt\":null,\"Username\":\"test\",\"Email\":\"5303221@gmail.com\"}}", "time": "9827ms"}
-2023-06-03 00:48:51	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:48:51	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "fde7e0f0d6c2d72558de89ba9270c04b", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=aaa"}
-2023-06-03 00:48:51	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "fde7e0f0d6c2d72558de89ba9270c04b", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=aaa", "response_body": "{\"code\":1,\"message\":\"missing form body\",\"data\":{}}", "time": "0ms"}
-2023-06-03 00:49:13	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:49:13	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "12e4b2be61b6e0954a53a1a7d6e63ad5", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com"}
-2023-06-03 00:49:13	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "12e4b2be61b6e0954a53a1a7d6e63ad5", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com", "response_body": "{\"code\":1,\"message\":\"missing form body\",\"data\":{}}", "time": "0ms"}
-2023-06-03 00:49:36	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:49:36	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "1a5cccc20a9097ddb3d2e98b0fa38634", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com"}
-2023-06-03 00:49:36	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "1a5cccc20a9097ddb3d2e98b0fa38634", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com", "response_body": "{\"code\":1,\"message\":\"missing form body\",\"data\":{}}", "time": "0ms"}
-2023-06-03 00:50:09	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:50:09	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "9d13d05958c821ef4b14c855fea94854", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com"}
-2023-06-03 00:50:09	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "9d13d05958c821ef4b14c855fea94854", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com", "response_body": "{\"code\":1,\"message\":\"missing form body\",\"data\":{}}", "time": "0ms"}
-2023-06-03 00:50:44	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:50:44	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "ed2ccae0fa4accdc317ee0f6bb036312", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com"}
-2023-06-03 00:50:44	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "ed2ccae0fa4accdc317ee0f6bb036312", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com", "response_body": "{\"code\":1,\"message\":\"missing form body\",\"data\":{}}", "time": "0ms"}
-2023-06-03 00:50:53	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:50:53	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "a6dc94353e52f6ca91b7c50df42e9750", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com"}
-2023-06-03 00:50:53	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "a6dc94353e52f6ca91b7c50df42e9750", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com", "response_body": "{\"code\":1,\"message\":\"missing form body\",\"data\":{}}", "time": "0ms"}
-2023-06-03 00:51:31	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:51:31	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "332e61758a39c529cfcdd36de4e7a47c", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com"}
-2023-06-03 00:51:31	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "332e61758a39c529cfcdd36de4e7a47c", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com", "response_body": "{\"code\":1,\"message\":\"missing form body\",\"data\":{}}", "time": "0ms"}
-2023-06-03 00:51:36	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:51:36	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "a09398a82736c1127647996a007a2658", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com"}
-2023-06-03 00:57:46	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:57:46	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "996290c5fe5fd7700a6f4298612a4c8a", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user"}
-2023-06-03 00:58:34	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "996290c5fe5fd7700a6f4298612a4c8a", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user", "response_body": "{\"code\":1,\"message\":\"missing form body\",\"data\":{}}", "time": "47328ms"}
-2023-06-03 00:58:38	info	/Users/chris/Projects/stu/gin-starter/test/server/handler/user_test.go:44	start
-2023-06-03 00:58:38	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/jwt.go:55	建立请求	{"trace": "57945bf50e811ef287e0cc7c92d665ea", "request_method": "GET", "request_headers": "{}", "request_url": "/user?email=5303221@gmail.com"}
-2023-06-03 00:58:43	info	/Users/chris/Projects/stu/gin-starter/internal/handler/user.go:60	GetUserByID	{"user": {"ID":1,"CreatedAt":"2023-06-03T00:48:12.007+08:00","UpdatedAt":"2023-06-03T00:48:12.007+08:00","DeletedAt":null,"Username":"test","Email":"5303221@gmail.com"}}
-2023-06-03 00:58:43	info	/Users/chris/Projects/stu/gin-starter/internal/middleware/log.go:57	响应返回	{"trace": "57945bf50e811ef287e0cc7c92d665ea", "request_method": "GET", "request_headers": "{}", "request_url": "/user?email=5303221@gmail.com", "response_body": "{\"code\":0,\"message\":\"success\",\"data\":{\"ID\":1,\"CreatedAt\":\"2023-06-03T00:48:12.007+08:00\",\"UpdatedAt\":\"2023-06-03T00:48:12.007+08:00\",\"DeletedAt\":null,\"Username\":\"test\",\"Email\":\"5303221@gmail.com\"}}", "time": "5315ms"}
-2023-06-05 15:52:00	info	/Users/chris/Projects/stu/nunu-layout/test/server/handler/user_test.go:47	start
-2023-06-05 15:52:04	info	/Users/chris/Projects/stu/nunu-layout/internal/middleware/jwt.go:55	建立请求	{"trace": "856fe8165f39ab3d7734fca386f74b1c", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com"}
-2023-06-05 15:52:04	info	/Users/chris/Projects/stu/nunu-layout/internal/middleware/jwt.go:55	建立请求	{"trace": "856fe8165f39ab3d7734fca386f74b1c", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com"}
-2023-06-05 15:52:04	info	/Users/chris/Projects/stu/nunu-layout/internal/middleware/log.go:57	响应返回	{"trace": "856fe8165f39ab3d7734fca386f74b1c", "request_method": "GET", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"],\"Content-Type\":[\"application/json\"]}", "request_url": "/user?email=5303221@gmail.com", "response_body": "{\"code\":1,\"message\":\"missing form body\",\"data\":{}}", "time": "0ms"}
-2023-06-05 15:52:04	info	/Users/chris/Projects/stu/nunu-layout/test/server/handler/user_test.go:47	start
-2023-06-05 15:52:04	info	/Users/chris/Projects/stu/nunu-layout/internal/middleware/jwt.go:55	建立请求	{"trace": "66ab47224d8602f41e275df08e55582f", "request_method": "POST", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"]}", "request_url": "/user", "request_params": "{\"email\":\"5303221@gmail.com\",\"username\":\"test\"}"}
-2023-06-05 15:52:04	info	/Users/chris/Projects/stu/nunu-layout/internal/middleware/jwt.go:55	建立请求	{"trace": "66ab47224d8602f41e275df08e55582f", "request_method": "POST", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"]}", "request_url": "/user", "request_params": "{\"email\":\"5303221@gmail.com\",\"username\":\"test\"}"}
-2023-06-05 15:52:04	error	/Users/chris/Projects/stu/nunu-layout/internal/middleware/jwt.go:77	token error	{"trace": "66ab47224d8602f41e275df08e55582f", "request_method": "POST", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"]}", "request_url": "/user", "request_params": "{\"email\":\"5303221@gmail.com\",\"username\":\"test\"}", "data": {"params":null,"url":{"Scheme":"","Opaque":"","User":null,"Host":"","Path":"/user","RawPath":"","OmitHost":false,"ForceQuery":false,"RawQuery":"","Fragment":"","RawFragment":""}}}
-github.com/go-nunu/nunu-layout-advanced/internal/middleware.StrictAuth.func1
-	/Users/chris/Projects/stu/nunu-layout/internal/middleware/jwt.go:77
-github.com/gin-gonic/gin.(*Context).Next
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174
-github.com/go-nunu/nunu-layout-advanced/internal/middleware.NoAuth.func1
-	/Users/chris/Projects/stu/nunu-layout/internal/middleware/jwt.go:56
-github.com/gin-gonic/gin.(*Context).Next
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174
-github.com/go-nunu/nunu-layout-advanced/internal/middleware.ResponseLogMiddleware.func1
-	/Users/chris/Projects/stu/nunu-layout/internal/middleware/log.go:48
-github.com/gin-gonic/gin.(*Context).Next
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174
-github.com/go-nunu/nunu-layout-advanced/internal/middleware.NoAuth.func1
-	/Users/chris/Projects/stu/nunu-layout/internal/middleware/jwt.go:56
-github.com/gin-gonic/gin.(*Context).Next
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174
-github.com/go-nunu/nunu-layout-advanced/internal/middleware.CORSMiddleware.func1
-	/Users/chris/Projects/stu/nunu-layout/internal/middleware/cors.go:20
-github.com/gin-gonic/gin.(*Context).Next
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174
-github.com/go-nunu/nunu-layout-advanced/internal/middleware.RequestLogMiddleware.func1
-	/Users/chris/Projects/stu/nunu-layout/internal/middleware/log.go:40
-github.com/gin-gonic/gin.(*Context).Next
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174
-github.com/gin-gonic/gin.CustomRecoveryWithWriter.func1
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/recovery.go:102
-github.com/gin-gonic/gin.(*Context).Next
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174
-github.com/gin-gonic/gin.LoggerWithConfig.func1
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/logger.go:240
-github.com/gin-gonic/gin.(*Context).Next
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174
-github.com/gin-gonic/gin.(*Engine).handleHTTPRequest
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/gin.go:620
-github.com/gin-gonic/gin.(*Engine).ServeHTTP
-	/Users/chris/Go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/gin.go:576
-github.com/go-nunu/nunu-layout-advanced/test/server/handler.NewRequest
-	/Users/chris/Projects/stu/nunu-layout/test/server/handler/user_test.go:58
-github.com/go-nunu/nunu-layout-advanced/test/server/handler.TestCreateUser
-	/Users/chris/Projects/stu/nunu-layout/test/server/handler/user_test.go:84
-testing.tRunner
-	/usr/local/go/src/testing/testing.go:1576
-2023-06-05 15:52:04	info	/Users/chris/Projects/stu/nunu-layout/internal/middleware/log.go:57	响应返回	{"trace": "66ab47224d8602f41e275df08e55582f", "request_method": "POST", "request_headers": "{\"Authorization\":[\"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM\"]}", "request_url": "/user", "request_params": "{\"email\":\"5303221@gmail.com\",\"username\":\"test\"}", "response_body": "{\"code\":1,\"message\":\"token signature is invalid: signature is invalid\",\"data\":{}}", "time": "0ms"}

+ 9 - 8
test/server/handler/user_test.go

@@ -12,13 +12,10 @@ import (
 	"net/http"
 	"net/http"
 	"net/http/httptest"
 	"net/http/httptest"
 	"os"
 	"os"
+	"strings"
 	"testing"
 	"testing"
 )
 )
 
 
-var jsonHeaders = map[string]string{
-	"Content-Type":  "application/json",
-	"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM",
-}
 var headers = map[string]string{
 var headers = map[string]string{
 	"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM",
 	"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySW5mbyI6eyJ1c2VyU2lkIjoiOHpsdGxQRzhXSCIsIm5pY2tuYW1lIjoi55CD55CDIiwidXNlcklkIjowfSwiZXhwIjoxNjg3NzcwMzYzLCJqdGkiOiI4emx0bFBHOFdIIiwiaXNzIjoiaHR0cHM6Ly90ZWh1Yi5jb20vYXBpIiwibmJmIjoxNjcyMjE3NzYzLCJzdWIiOiI4emx0bFBHOFdIIn0.G0sSUzj3GBANqj6dU7rSMsr44SARgYwH1ERwKUCaxsM",
 }
 }
@@ -54,6 +51,10 @@ func NewRequest(method, path string, header map[string]string, body io.Reader) (
 	for k, v := range header {
 	for k, v := range header {
 		req.Header.Set(k, v)
 		req.Header.Set(k, v)
 	}
 	}
+	if strings.ToUpper(method) != "GET" && body != nil {
+		req.Header.Set("Content-Type", "application/json")
+
+	}
 	w := httptest.NewRecorder()
 	w := httptest.NewRecorder()
 	app.ServeHTTP(w, req)
 	app.ServeHTTP(w, req)
 	response := new(Response)
 	response := new(Response)
@@ -64,14 +65,14 @@ func NewRequest(method, path string, header map[string]string, body io.Reader) (
 	return response, nil
 	return response, nil
 }
 }
 
 
-func TestGetUserByEmail(t *testing.T) {
+func TestGetUserById(t *testing.T) {
 	response, err := NewRequest("GET",
 	response, err := NewRequest("GET",
-		fmt.Sprintf("/user?email=%s", "5303221@gmail.com"),
-		jsonHeaders,
+		fmt.Sprintf("/user?id=%s", "-1"),
+		headers,
 		nil,
 		nil,
 	)
 	)
 
 
-	t.Log("响应结果")
+	t.Log("response")
 	assert.Nil(t, err)
 	assert.Nil(t, err)
 	assert.Equal(t, 1, response.Code)
 	assert.Equal(t, 1, response.Code)
 }
 }