424 lines
9.0 KiB
Markdown
424 lines
9.0 KiB
Markdown
# HTTP Restful工具文档
|
||
|
||
## 概述
|
||
|
||
HTTP Restful工具提供了标准化的HTTP请求和响应处理功能,包含统一的响应结构、分页支持和HTTP状态码与业务状态码的分离。
|
||
|
||
## 功能特性
|
||
|
||
- 标准化的响应结构:`{code, message, timestamp, data}`
|
||
- 分离HTTP状态码和业务状态码
|
||
- 支持分页响应
|
||
- 提供便捷的请求参数解析方法
|
||
- 支持JSON请求体解析
|
||
- 提供常用的HTTP错误响应方法
|
||
|
||
## 响应结构
|
||
|
||
### 标准响应结构
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "success",
|
||
"timestamp": 1704067200,
|
||
"data": {}
|
||
}
|
||
```
|
||
|
||
### 分页响应结构
|
||
|
||
```json
|
||
{
|
||
"code": 0,
|
||
"message": "success",
|
||
"timestamp": 1704067200,
|
||
"data": {
|
||
"list": [],
|
||
"total": 100,
|
||
"page": 1,
|
||
"pageSize": 10
|
||
}
|
||
}
|
||
```
|
||
|
||
## 使用方法
|
||
|
||
### 1. 成功响应
|
||
|
||
```go
|
||
import (
|
||
"net/http"
|
||
"github.com/go-common/http"
|
||
)
|
||
|
||
// 简单成功响应(data为nil)
|
||
http.Success(w, nil)
|
||
|
||
// 带数据的成功响应
|
||
data := map[string]interface{}{
|
||
"id": 1,
|
||
"name": "test",
|
||
}
|
||
http.Success(w, data)
|
||
|
||
// 带消息的成功响应
|
||
http.SuccessWithMessage(w, "操作成功", data)
|
||
```
|
||
|
||
### 2. 错误响应
|
||
|
||
```go
|
||
// 业务错误(HTTP 200,业务code非0)
|
||
http.Error(w, 1001, "用户不存在")
|
||
|
||
// 系统错误(HTTP 500)
|
||
http.SystemError(w, "服务器内部错误")
|
||
|
||
// 请求错误(HTTP 400)
|
||
http.BadRequest(w, "请求参数错误")
|
||
|
||
// 未授权(HTTP 401)
|
||
http.Unauthorized(w, "未登录")
|
||
|
||
// 禁止访问(HTTP 403)
|
||
http.Forbidden(w, "无权限访问")
|
||
|
||
// 未找到(HTTP 404)
|
||
http.NotFound(w, "资源不存在")
|
||
```
|
||
|
||
### 3. 分页响应
|
||
|
||
```go
|
||
// 获取分页参数
|
||
page, pageSize := http.GetPaginationParams(r)
|
||
|
||
// 查询数据(示例)
|
||
list, total := getDataList(page, pageSize)
|
||
|
||
// 返回分页响应
|
||
http.SuccessPage(w, list, total, page, pageSize)
|
||
|
||
// 带消息的分页响应
|
||
http.SuccessPageWithMessage(w, "查询成功", list, total, page, pageSize)
|
||
```
|
||
|
||
### 4. 解析请求
|
||
|
||
#### 解析JSON请求体
|
||
|
||
```go
|
||
type CreateUserRequest struct {
|
||
Name string `json:"name"`
|
||
Email string `json:"email"`
|
||
}
|
||
|
||
var req CreateUserRequest
|
||
err := http.ParseJSON(r, &req)
|
||
if err != nil {
|
||
http.BadRequest(w, "请求参数解析失败")
|
||
return
|
||
}
|
||
```
|
||
|
||
#### 获取查询参数
|
||
|
||
```go
|
||
// 获取字符串参数
|
||
name := http.GetQuery(r, "name", "")
|
||
email := http.GetQuery(r, "email", "default@example.com")
|
||
|
||
// 获取整数参数
|
||
id := http.GetQueryInt(r, "id", 0)
|
||
age := http.GetQueryInt(r, "age", 18)
|
||
|
||
// 获取int64参数
|
||
userId := http.GetQueryInt64(r, "userId", 0)
|
||
|
||
// 获取布尔参数
|
||
isActive := http.GetQueryBool(r, "isActive", false)
|
||
|
||
// 获取浮点数参数
|
||
price := http.GetQueryFloat64(r, "price", 0.0)
|
||
```
|
||
|
||
#### 获取表单参数
|
||
|
||
```go
|
||
// 获取表单字符串
|
||
name := http.GetFormValue(r, "name", "")
|
||
|
||
// 获取表单整数
|
||
age := http.GetFormInt(r, "age", 0)
|
||
|
||
// 获取表单int64
|
||
userId := http.GetFormInt64(r, "userId", 0)
|
||
|
||
// 获取表单布尔值
|
||
isActive := http.GetFormBool(r, "isActive", false)
|
||
```
|
||
|
||
#### 获取请求头
|
||
|
||
```go
|
||
token := http.GetHeader(r, "Authorization", "")
|
||
contentType := http.GetHeader(r, "Content-Type", "application/json")
|
||
```
|
||
|
||
#### 获取分页参数
|
||
|
||
```go
|
||
// 自动解析page和pageSize参数
|
||
// 默认: page=1, pageSize=10
|
||
// 限制: pageSize最大1000
|
||
page, pageSize := http.GetPaginationParams(r)
|
||
|
||
// 计算数据库查询偏移量
|
||
offset := http.GetOffset(page, pageSize)
|
||
```
|
||
|
||
### 5. 自定义响应
|
||
|
||
```go
|
||
// 使用WriteJSON自定义响应
|
||
http.WriteJSON(w, http.StatusOK, 0, "success", data)
|
||
|
||
// 参数说明:
|
||
// - httpCode: HTTP状态码(200, 400, 500等)
|
||
// - code: 业务状态码(0表示成功,非0表示业务错误)
|
||
// - message: 响应消息
|
||
// - data: 响应数据
|
||
```
|
||
|
||
## 完整示例
|
||
|
||
```go
|
||
package main
|
||
|
||
import (
|
||
"net/http"
|
||
"github.com/go-common/http"
|
||
)
|
||
|
||
// 用户列表接口
|
||
func GetUserList(w http.ResponseWriter, r *http.Request) {
|
||
// 获取分页参数
|
||
page, pageSize := http.GetPaginationParams(r)
|
||
|
||
// 获取查询参数
|
||
keyword := http.GetQuery(r, "keyword", "")
|
||
|
||
// 查询数据
|
||
users, total := queryUsers(keyword, page, pageSize)
|
||
|
||
// 返回分页响应
|
||
http.SuccessPage(w, users, total, page, pageSize)
|
||
}
|
||
|
||
// 创建用户接口
|
||
func CreateUser(w http.ResponseWriter, r *http.Request) {
|
||
// 解析请求体
|
||
var req struct {
|
||
Name string `json:"name"`
|
||
Email string `json:"email"`
|
||
}
|
||
|
||
if err := http.ParseJSON(r, &req); err != nil {
|
||
http.BadRequest(w, "请求参数解析失败")
|
||
return
|
||
}
|
||
|
||
// 参数验证
|
||
if req.Name == "" {
|
||
http.Error(w, 1001, "用户名不能为空")
|
||
return
|
||
}
|
||
|
||
// 创建用户
|
||
user, err := createUser(req.Name, req.Email)
|
||
if err != nil {
|
||
http.SystemError(w, "创建用户失败")
|
||
return
|
||
}
|
||
|
||
// 返回成功响应
|
||
http.SuccessWithMessage(w, "创建成功", user)
|
||
}
|
||
|
||
// 获取用户详情接口
|
||
func GetUser(w http.ResponseWriter, r *http.Request) {
|
||
// 获取路径参数(需要配合路由框架使用)
|
||
id := http.GetQueryInt64(r, "id", 0)
|
||
|
||
if id == 0 {
|
||
http.BadRequest(w, "用户ID不能为空")
|
||
return
|
||
}
|
||
|
||
// 查询用户
|
||
user, err := getUserByID(id)
|
||
if err != nil {
|
||
http.SystemError(w, "查询用户失败")
|
||
return
|
||
}
|
||
|
||
if user == nil {
|
||
http.Error(w, 1002, "用户不存在")
|
||
return
|
||
}
|
||
|
||
http.Success(w, user)
|
||
}
|
||
```
|
||
|
||
## API 参考
|
||
|
||
### 响应方法
|
||
|
||
#### Success(w http.ResponseWriter, data interface{})
|
||
|
||
成功响应,HTTP 200,业务code 0。
|
||
|
||
#### SuccessWithMessage(w http.ResponseWriter, message string, data interface{})
|
||
|
||
带消息的成功响应。
|
||
|
||
#### Error(w http.ResponseWriter, code int, message string)
|
||
|
||
业务错误响应,HTTP 200,业务code非0。
|
||
|
||
#### SystemError(w http.ResponseWriter, message string)
|
||
|
||
系统错误响应,HTTP 500,业务code 500。
|
||
|
||
#### BadRequest(w http.ResponseWriter, message string)
|
||
|
||
请求错误响应,HTTP 400。
|
||
|
||
#### Unauthorized(w http.ResponseWriter, message string)
|
||
|
||
未授权响应,HTTP 401。
|
||
|
||
#### Forbidden(w http.ResponseWriter, message string)
|
||
|
||
禁止访问响应,HTTP 403。
|
||
|
||
#### NotFound(w http.ResponseWriter, message string)
|
||
|
||
未找到响应,HTTP 404。
|
||
|
||
#### WriteJSON(w http.ResponseWriter, httpCode, code int, message string, data interface{})
|
||
|
||
写入JSON响应(自定义)。
|
||
|
||
**参数:**
|
||
- `httpCode`: HTTP状态码
|
||
- `code`: 业务状态码
|
||
- `message`: 响应消息
|
||
- `data`: 响应数据
|
||
|
||
#### SuccessPage(w http.ResponseWriter, list interface{}, total int64, page, pageSize int)
|
||
|
||
分页成功响应。
|
||
|
||
#### SuccessPageWithMessage(w http.ResponseWriter, message string, list interface{}, total int64, page, pageSize int)
|
||
|
||
带消息的分页成功响应。
|
||
|
||
### 请求方法
|
||
|
||
#### ParseJSON(r *http.Request, v interface{}) error
|
||
|
||
解析JSON请求体。
|
||
|
||
#### GetQuery(r *http.Request, key, defaultValue string) string
|
||
|
||
获取查询参数(字符串)。
|
||
|
||
#### GetQueryInt(r *http.Request, key string, defaultValue int) int
|
||
|
||
获取查询参数(整数)。
|
||
|
||
#### GetQueryInt64(r *http.Request, key string, defaultValue int64) int64
|
||
|
||
获取查询参数(int64)。
|
||
|
||
#### GetQueryBool(r *http.Request, key string, defaultValue bool) bool
|
||
|
||
获取查询参数(布尔值)。
|
||
|
||
#### GetQueryFloat64(r *http.Request, key string, defaultValue float64) float64
|
||
|
||
获取查询参数(浮点数)。
|
||
|
||
#### GetFormValue(r *http.Request, key, defaultValue string) string
|
||
|
||
获取表单值(字符串)。
|
||
|
||
#### GetFormInt(r *http.Request, key string, defaultValue int) int
|
||
|
||
获取表单值(整数)。
|
||
|
||
#### GetFormInt64(r *http.Request, key string, defaultValue int64) int64
|
||
|
||
获取表单值(int64)。
|
||
|
||
#### GetFormBool(r *http.Request, key string, defaultValue bool) bool
|
||
|
||
获取表单值(布尔值)。
|
||
|
||
#### GetHeader(r *http.Request, key, defaultValue string) string
|
||
|
||
获取请求头。
|
||
|
||
#### GetPaginationParams(r *http.Request) (page, pageSize int)
|
||
|
||
获取分页参数。
|
||
|
||
**返回:** page(页码,最小1),pageSize(每页大小,最小1,最大1000)
|
||
|
||
#### GetOffset(page, pageSize int) int
|
||
|
||
根据页码和每页大小计算偏移量。
|
||
|
||
## 状态码说明
|
||
|
||
### HTTP状态码
|
||
|
||
- `200`: 正常响应(包括业务错误)
|
||
- `400`: 请求参数错误
|
||
- `401`: 未授权
|
||
- `403`: 禁止访问
|
||
- `404`: 资源不存在
|
||
- `500`: 系统内部错误
|
||
|
||
### 业务状态码
|
||
|
||
- `0`: 成功
|
||
- `非0`: 业务错误(具体错误码由业务定义)
|
||
|
||
## 注意事项
|
||
|
||
1. **HTTP状态码与业务状态码分离**:
|
||
- 业务错误(如用户不存在、参数验证失败等)返回HTTP 200,业务code非0
|
||
- 只有系统异常(如数据库连接失败、程序panic等)才返回HTTP 500
|
||
|
||
2. **分页参数限制**:
|
||
- page最小值为1
|
||
- pageSize最小值为1,最大值为1000
|
||
|
||
3. **响应格式统一**:
|
||
- 所有响应都遵循标准结构
|
||
- timestamp为Unix时间戳(秒)
|
||
|
||
4. **错误处理**:
|
||
- 使用Error方法返回业务错误
|
||
- 使用SystemError返回系统错误
|
||
- 使用BadRequest等返回HTTP级别的错误
|
||
|
||
## 示例
|
||
|
||
完整示例请参考 `examples/http_example.go`
|
||
|