service/request.go

219 lines
4.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"apigo.cc/go/discover"
"io"
"mime/multipart"
"net"
"net/http"
"net/textproto"
"net/url"
)
// UploadFile 上传文件结构
type UploadFile struct {
fileHeader *multipart.FileHeader
Filename string
Header textproto.MIMEHeader
Size int64
}
// Open 打开上传文件
func (f *UploadFile) Open() (multipart.File, error) {
return f.fileHeader.Open()
}
// Content 获取上传文件内容
func (f *UploadFile) Content() ([]byte, error) {
src, err := f.fileHeader.Open()
if err != nil {
return nil, err
}
defer src.Close()
return io.ReadAll(src)
}
// Header 包装 http.Header 以提供 JS 友好的方法
type Header struct {
H http.Header `js:"-"`
}
func (h *Header) Get(key string) string {
return h.H.Get(key)
}
func (h *Header) Set(key, value string) {
h.H.Set(key, value)
}
func (h *Header) Add(key, value string) {
h.H.Add(key, value)
}
func (h *Header) Del(key string) {
h.H.Del(key)
}
func (h *Header) Values(key string) []string {
return h.H.Values(key)
}
// Request 封装 http.Request
type Request struct {
*http.Request `js:"-"`
contextValues map[string]any `js:"-"`
Id string
}
// Cookie 简化的 JS 友好 Cookie 结构
type Cookie struct {
Name string
Value string
Path string
Domain string
MaxAge int
Secure bool
HttpOnly bool
}
func (r *Request) GetCookie(name string) *Cookie {
c, err := r.Request.Cookie(name)
if err != nil {
return nil
}
return &Cookie{
Name: c.Name,
Value: c.Value,
Path: c.Path,
Domain: c.Domain,
MaxAge: c.MaxAge,
Secure: c.Secure,
HttpOnly: c.HttpOnly,
}
}
func (r *Request) GetCookies() []*Cookie {
res := make([]*Cookie, 0)
for _, c := range r.Request.Cookies() {
res = append(res, &Cookie{
Name: c.Name,
Value: c.Value,
Path: c.Path,
Domain: c.Domain,
MaxAge: c.MaxAge,
Secure: c.Secure,
HttpOnly: c.HttpOnly,
})
}
return res
}
// AddCookie 遮蔽原生的 AddCookie
func (r *Request) AddCookie(c *Cookie) {
if c == nil {
return
}
r.Request.AddCookie(&http.Cookie{
Name: c.Name,
Value: c.Value,
Path: c.Path,
Domain: c.Domain,
MaxAge: c.MaxAge,
Secure: c.Secure,
HttpOnly: c.HttpOnly,
})
}
// CookiesNamed 遮蔽原生的 CookiesNamed
func (r *Request) CookiesNamed(name string) []*Cookie {
res := make([]*Cookie, 0)
for _, c := range r.Request.Cookies() {
if c.Name == name {
res = append(res, &Cookie{
Name: c.Name,
Value: c.Value,
Path: c.Path,
Domain: c.Domain,
MaxAge: c.MaxAge,
Secure: c.Secure,
HttpOnly: c.HttpOnly,
})
}
}
return res
}
func (r *Request) Header() *Header {
return &Header{H: r.Request.Header}
}
// NewRequest 创建 Request 包装
func NewRequest(httpRequest *http.Request) *Request {
return &Request{
Request: httpRequest,
contextValues: make(map[string]any),
}
}
// ResetPath 重写请求路径
func (r *Request) ResetPath(path string) {
r.RequestURI = path
if u, err := url.Parse(path); err == nil {
r.URL = u
}
}
// Set 设置请求上下文变量
func (r *Request) Set(key string, value any) {
r.contextValues[key] = value
}
// Get 获取请求上下文变量
func (r *Request) Get(key string) any {
return r.contextValues[key]
}
// MakeUrl 根据当前请求构建完整 URL
func (r *Request) MakeUrl(path string) string {
scheme := r.Header().Get(discover.HeaderScheme)
if scheme == "" {
scheme = "http"
}
host := r.Header().Get(discover.HeaderHost)
if host == "" {
host = r.Host
}
return scheme + "://" + host + path
}
// DeviceId 获取设备 ID
func (r *Request) DeviceId() string {
return r.Header().Get(discover.HeaderDeviceID)
}
// SessionId 获取会话 ID
func (r *Request) SessionId() string {
return r.Header().Get(discover.HeaderSessionID)
}
// SetUserId 设置用户 ID传递给下游
func (r *Request) SetUserId(userId string) {
r.Header().Set(discover.HeaderUserID, userId)
}
// ClientIp 获取真实 IP
func (r *Request) ClientIp() string {
ip := r.Header().Get(discover.HeaderClientIP)
if ip == "" {
ip = r.Header().Get(discover.HeaderForwardedFor)
}
if ip == "" {
host, _, err := net.SplitHostPort(r.RemoteAddr)
if err == nil {
return host
}
return r.RemoteAddr
}
return ip
}