From fa97cace29493b657df3ab3a70ef66c7507260df Mon Sep 17 00:00:00 2001 From: Star Date: Wed, 10 Dec 2025 16:56:37 +0800 Subject: [PATCH] =?UTF-8?q?export=20interface;=20-w=20=E6=97=B6=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E7=9B=91=E5=90=AC=E6=B2=A1=E6=9C=89content-type?= =?UTF-8?q?=E7=9A=84html?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 2 +- service.go | 5 +- service.ts | 446 ++++++++++++++++++++++++++--------------------------- 3 files changed, 227 insertions(+), 226 deletions(-) diff --git a/go.mod b/go.mod index 545cbbb..cb462e5 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module apigo.cc/gojs/service go 1.24.0 require ( - apigo.cc/gojs v0.0.30 + apigo.cc/gojs v0.0.31 apigo.cc/gojs/console v0.0.4 apigo.cc/gojs/file v0.0.7 apigo.cc/gojs/http v0.0.8 diff --git a/service.go b/service.go index 1b53e9a..680e3ee 100644 --- a/service.go +++ b/service.go @@ -290,8 +290,9 @@ func init() { onWatchLock.Unlock() }, "") s.SetOutFilter(func(in map[string]any, request *s.Request, response *s.Response, out any, logger *log.Logger) (newOut any, isOver bool) { - if strings.HasPrefix(response.Header().Get("Content-Type"), "text/html") { - outStr := u.String(out) + contentType := response.Header().Get("Content-Type") + outStr := u.String(out) + if strings.HasPrefix(contentType, "text/html") || (contentType == "" && strings.Contains(outStr, " // SSL证书配置,key为域名,value为cert和key的文件路径 - noLogGets: boolean // 不记录GET请求的日志 - noLogHeaders: string // 不记录请求头中包含的这些字段,多个字段用逗号分隔,默认不记录:Accept,Accept-Encoding,Cache-Control,Pragma,Connection,Upgrade-Insecure-Requests - logInputArrayNum: number // 请求字段中容器类型(数组、Map)在日志打印个数限制 默认为10个,多余的数据将不再日志中记录 - logInputFieldSize: number // 请求字段中单个字段在日志打印长度限制 默认为500个字符,多余的数据将不再日志中记录 - noLogOutputFields: string // 不记录响应字段中包含的这些字段(key名),多个字段用逗号分隔 - logOutputArrayNum: number // 响应字段中容器类型(数组、Map)在日志打印个数限制 默认为3个,多余的数据将不再日志中记录 - logOutputFieldSize: number // 响应字段中单个字段在日志打印长度限制 默认为100个字符,多余的数据将不再日志中记录 - logWebsocketAction: boolean // 记录Websocket中每个Action的请求日志,默认不记录 - compress: boolean // 是否启用压缩,默认不启用 - compressMinSize: number // 小于设定值的应答内容将不进行压缩,默认值:1024 - compressMaxSize: number // 大于设定值的应答内容将不进行压缩,默认值:4096000 - checkDomain: string // 心跳检测时使用域名,,默认使用IP地址,心跳检测使用 HEAD /__CHECK__ 请求,应答 299 表示正常,593 表示异常 - redirectTimeout: number // proxy和discover发起请求时的超时时间,单位ms,默认值:10000 - acceptXRealIpWithoutRequestId: boolean // 是否允许头部没有携带请求ID的X-Real-IP信息,默认不允许(防止伪造客户端IP) - statisticTime: boolean // 是否开启请求时间统计,默认不开启 - statisticTimeInterval: number // 统计时间间隔,单位ms,默认值:10000 - fast: boolean // 是否启用快速模式(为了追求性能牺牲一部分特性),默认不启用 - maxUploadSize: number // 最大上传文件大小(multipart/form-data请求的总空间),单位字节,默认值:104857600 - cpu: number // CPU占用的核数,默认为0,即不做限制 - memory: number // 内存(单位M),默认为0,即不做限制 - cpuMonitor: boolean // 在日志中记录CPU使用情况,默认不开启 - memoryMonitor: boolean // 在日志中记录内存使用情况,默认不开启 - cpuLimitValue: number // CPU超过最高占用值(10-100)超过次数将自动重启(如果CpuMonitor开启的话),默认100 - memoryLimitValue: number // 内存超过最高占用值(10-100)超过次数将自动重启(如果MemoryMonitor开启的话),默认95 - cpuLimitTimes: number // CPU超过最高占用值超过次数(1-100)将报警(如果CpuMonitor开启的话),默认6(即30秒内连续6次) - memoryLimitTimes: number // 内存超过最高占用值超过次数(1-100)将报警(如果MemoryMonitor开启的话),默认6(即30秒内连续6次) - cookieScope: string // 启用Session时Cookie的有效范围,host|domain|topDomain,默认值为host - sessionWithoutCookie: boolean // Session禁用Cookie保持,默认使用Cookie - deviceWithoutCookie: boolean // 设备ID禁用Cookie保持,默认使用Cookie - idServer: string // 用s.UniqueId、s.Id来生成唯一ID(雪花算法)时所需的redis服务器连接,如果不指定将不能实现跨服务的全局唯一 - keepKeyCase: boolean // 是否保持Key的首字母大小写?默认保持,设置为false则自动将首字母转为小写 - indexFiles: string[] // 访问静态文件时的索引文件,默认为 index.html - indexDir: boolean // 访问目录时显示文件列表 - readTimeout: number // 读取请求的超时时间,单位ms - readHeaderTimeout: number // 读取请求头的超时时间,单位ms - writeTimeout: number // 响应写入的超时时间,单位ms - idleTimeout: number // 连接空闲超时时间,单位ms - maxHeaderBytes: number // 请求头的最大字节数 - maxHandlers: number // 每个连接的最大处理程序数量 - maxConcurrentStreams: number // 每个连接的最大并发流数量 - maxDecoderHeaderTableSize: number // 解码器头表的最大大小 - maxEncoderHeaderTableSize: number // 编码器头表的最大大小 - maxReadFrameSize: number // 单个帧的最大读取大小 - maxUploadBufferPerConnection: number // 每个连接的最大上传缓冲区大小 - maxUploadBufferPerStream: number // 每个流的最大上传缓冲区大小 +export interface Config { + // github.com/ssgo/s 的配置参数 + listen: string // 监听端口(|隔开多个监听)(,隔开多个选项)(如果不指定IP则监听在0.0.0.0,如果不指定端口则使用h2c协议监听在随机端口,80端口默认使用http协议,443端口默认使用https协议),例如 80,http|443|443:h2|127.0.0.1:8080,h2c + ssl: Map // SSL证书配置,key为域名,value为cert和key的文件路径 + noLogGets: boolean // 不记录GET请求的日志 + noLogHeaders: string // 不记录请求头中包含的这些字段,多个字段用逗号分隔,默认不记录:Accept,Accept-Encoding,Cache-Control,Pragma,Connection,Upgrade-Insecure-Requests + logInputArrayNum: number // 请求字段中容器类型(数组、Map)在日志打印个数限制 默认为10个,多余的数据将不再日志中记录 + logInputFieldSize: number // 请求字段中单个字段在日志打印长度限制 默认为500个字符,多余的数据将不再日志中记录 + noLogOutputFields: string // 不记录响应字段中包含的这些字段(key名),多个字段用逗号分隔 + logOutputArrayNum: number // 响应字段中容器类型(数组、Map)在日志打印个数限制 默认为3个,多余的数据将不再日志中记录 + logOutputFieldSize: number // 响应字段中单个字段在日志打印长度限制 默认为100个字符,多余的数据将不再日志中记录 + logWebsocketAction: boolean // 记录Websocket中每个Action的请求日志,默认不记录 + compress: boolean // 是否启用压缩,默认不启用 + compressMinSize: number // 小于设定值的应答内容将不进行压缩,默认值:1024 + compressMaxSize: number // 大于设定值的应答内容将不进行压缩,默认值:4096000 + checkDomain: string // 心跳检测时使用域名,,默认使用IP地址,心跳检测使用 HEAD /__CHECK__ 请求,应答 299 表示正常,593 表示异常 + redirectTimeout: number // proxy和discover发起请求时的超时时间,单位ms,默认值:10000 + acceptXRealIpWithoutRequestId: boolean // 是否允许头部没有携带请求ID的X-Real-IP信息,默认不允许(防止伪造客户端IP) + statisticTime: boolean // 是否开启请求时间统计,默认不开启 + statisticTimeInterval: number // 统计时间间隔,单位ms,默认值:10000 + fast: boolean // 是否启用快速模式(为了追求性能牺牲一部分特性),默认不启用 + maxUploadSize: number // 最大上传文件大小(multipart/form-data请求的总空间),单位字节,默认值:104857600 + cpu: number // CPU占用的核数,默认为0,即不做限制 + memory: number // 内存(单位M),默认为0,即不做限制 + cpuMonitor: boolean // 在日志中记录CPU使用情况,默认不开启 + memoryMonitor: boolean // 在日志中记录内存使用情况,默认不开启 + cpuLimitValue: number // CPU超过最高占用值(10-100)超过次数将自动重启(如果CpuMonitor开启的话),默认100 + memoryLimitValue: number // 内存超过最高占用值(10-100)超过次数将自动重启(如果MemoryMonitor开启的话),默认95 + cpuLimitTimes: number // CPU超过最高占用值超过次数(1-100)将报警(如果CpuMonitor开启的话),默认6(即30秒内连续6次) + memoryLimitTimes: number // 内存超过最高占用值超过次数(1-100)将报警(如果MemoryMonitor开启的话),默认6(即30秒内连续6次) + cookieScope: string // 启用Session时Cookie的有效范围,host|domain|topDomain,默认值为host + sessionWithoutCookie: boolean // Session禁用Cookie保持,默认使用Cookie + deviceWithoutCookie: boolean // 设备ID禁用Cookie保持,默认使用Cookie + idServer: string // 用s.UniqueId、s.Id来生成唯一ID(雪花算法)时所需的redis服务器连接,如果不指定将不能实现跨服务的全局唯一 + keepKeyCase: boolean // 是否保持Key的首字母大小写?默认保持,设置为false则自动将首字母转为小写 + indexFiles: string[] // 访问静态文件时的索引文件,默认为 index.html + indexDir: boolean // 访问目录时显示文件列表 + readTimeout: number // 读取请求的超时时间,单位ms + readHeaderTimeout: number // 读取请求头的超时时间,单位ms + writeTimeout: number // 响应写入的超时时间,单位ms + idleTimeout: number // 连接空闲超时时间,单位ms + maxHeaderBytes: number // 请求头的最大字节数 + maxHandlers: number // 每个连接的最大处理程序数量 + maxConcurrentStreams: number // 每个连接的最大并发流数量 + maxDecoderHeaderTableSize: number // 解码器头表的最大大小 + maxEncoderHeaderTableSize: number // 编码器头表的最大大小 + maxReadFrameSize: number // 单个帧的最大读取大小 + maxUploadBufferPerConnection: number // 每个连接的最大上传缓冲区大小 + maxUploadBufferPerStream: number // 每个流的最大上传缓冲区大小 - // 其他配置 - sessionKey: string // HTTP头和Cookie中SessionID的Key,客户端没有传递时服务端自动生成,Header的优先级高于Cookie,默认为 Session, 设置为空时表示不使用 - deviceKey: string // 标识设备ID的Key,客户端没有传递时服务端自动生成,Header的优先级高于Cookie,默认为 Device, 设置为空时表示不使用 - clientKey: string // 标识客户端的Key,默认为 Client,对应的Header头为 ClientName 和 ClientVersion - userIdKey: string // session中userID的Key,用于在日志中记录用户ID信息,默认为 id - sessionProvider: string // 指定一个redis连接(例如:redis://:sskey加密的密码@127.0.0.1:6379/15),默认使用内存存储 - sessionTimeout: number // session过期时间,单位 秒,默认为 3600秒 - authFieldMessage: string | Object // 身份验证失败时的消息,默认为 auth failed,可以设置对象来返回JSON,可以使用模版 {{TARGET_AUTHLEVEL}}、{{USER_AUTHLEVEL}} - verifyFieldMessage: string | Object // 参数验证失败时的消息,默认为 verify failed,可以设置对象来返回JSON,可以使用模版 {{FAILED_FIELDS}} - limitedMessage: string | Object // 访问受限时的消息,默认为 too many requests,可以设置对象来返回JSON,可以使用模版 {{LIMITED_FROM}}、{{LIMITED_VALUE}} - limiterRedis: string // 限流器使用的Redis连接,默认使用内存存储 - limiters: Map // 限流器配置,from 为数据来源,例如:ip、user、device、header.User-Agent、in.phone 等(in表示从请求参数中获取),time为时间间隔,单位ms,times为 时间间隔内允许访问的次数 - hotLoad: number // 热加载配置,单位s,默认值:0,0表示不检测热加载 + // 其他配置 + sessionKey: string // HTTP头和Cookie中SessionID的Key,客户端没有传递时服务端自动生成,Header的优先级高于Cookie,默认为 Session, 设置为空时表示不使用 + deviceKey: string // 标识设备ID的Key,客户端没有传递时服务端自动生成,Header的优先级高于Cookie,默认为 Device, 设置为空时表示不使用 + clientKey: string // 标识客户端的Key,默认为 Client,对应的Header头为 ClientName 和 ClientVersion + userIdKey: string // session中userID的Key,用于在日志中记录用户ID信息,默认为 id + sessionProvider: string // 指定一个redis连接(例如:redis://:sskey加密的密码@127.0.0.1:6379/15),默认使用内存存储 + sessionTimeout: number // session过期时间,单位 秒,默认为 3600秒 + authFieldMessage: string | Object // 身份验证失败时的消息,默认为 auth failed,可以设置对象来返回JSON,可以使用模版 {{TARGET_AUTHLEVEL}}、{{USER_AUTHLEVEL}} + verifyFieldMessage: string | Object // 参数验证失败时的消息,默认为 verify failed,可以设置对象来返回JSON,可以使用模版 {{FAILED_FIELDS}} + limitedMessage: string | Object // 访问受限时的消息,默认为 too many requests,可以设置对象来返回JSON,可以使用模版 {{LIMITED_FROM}}、{{LIMITED_VALUE}} + limiterRedis: string // 限流器使用的Redis连接,默认使用内存存储 + limiters: Map // 限流器配置,from 为数据来源,例如:ip、user、device、header.User-Agent、in.phone 等(in表示从请求参数中获取),time为时间间隔,单位ms,times为 时间间隔内允许访问的次数 + hotLoad: number // 热加载配置,单位s,默认值:0,0表示不检测热加载 - // gateway 的配置参数 - proxy: Map // 代理配置,key为[host][path],value为代理的目标应用或URL - rewrite: Map // 重写请求路径,key为[host][path],value为重写后的路径 - static: Map // 静态文件目录,key为[host][path],value为目录路径 + // gateway 的配置参数 + proxy: Map // 代理配置,key为[host][path],value为代理的目标应用或URL + rewrite: Map // 重写请求路径,key为[host][path],value为重写后的路径 + static: Map // 静态文件目录,key为[host][path],value为目录路径 - // github.com/ssgo/discover 的配置参数 - registry: string // 服务注册中心,请配置一个有效的RedisURL,默认值 redis://:@127.0.0.1:6379/15 - app: string // 设置该值将会自动将服务注册到 discover - weight: number // 节点的权重,默认值 100 - accessTokens: Map // 请求接口时使用指定的Access-Token进行验证,值为Token对应的authLevel(允许访问大于等于指定对应authLevel的接口) - calls: Map // 配置将会调用的服务,格式:[1|2]:[http|https|h2c]:[AccessToken],默认协议为:h2c,如使用h2c协议可只提供 AccessToken - callRetryTimes: number // 调用其他服务时最大重试次数,默认值 10 - ipPrefix: string // discover服务发现时指定使用的IP网段,默认排除 172.17.(Docker) + // github.com/ssgo/discover 的配置参数 + registry: string // 服务注册中心,请配置一个有效的RedisURL,默认值 redis://:@127.0.0.1:6379/15 + app: string // 设置该值将会自动将服务注册到 discover + weight: number // 节点的权重,默认值 100 + accessTokens: Map // 请求接口时使用指定的Access-Token进行验证,值为Token对应的authLevel(允许访问大于等于指定对应authLevel的接口) + calls: Map // 配置将会调用的服务,格式:[1|2]:[http|https|h2c]:[AccessToken],默认协议为:h2c,如使用h2c协议可只提供 AccessToken + callRetryTimes: number // 调用其他服务时最大重试次数,默认值 10 + ipPrefix: string // discover服务发现时指定使用的IP网段,默认排除 172.17.(Docker) } -interface CertSet { - certFile: string - keyFile: string +export interface CertSet { + certFile: string + keyFile: string } -interface PoolConfig { - min: number - max: string - idle: number +export interface PoolConfig { + min: number + max: string + idle: number } -interface LimiterConfig { - from: string - time: number - times: number +export interface LimiterConfig { + from: string + time: number + times: number } -interface RegisterOption { - authLevel: number - host: string - method: string - path: string - memo: string - noBody: boolean - noLog200: boolean - limiters: string[] - verifies: Object - requires: string[] - ext: Object - onMessage: (params: OnMessageParams) => void - onClose: (params: RequestParams) => void +export interface RegisterOption { + authLevel: number + host: string + method: string + path: string + memo: string + noBody: boolean + noLog200: boolean + limiters: string[] + verifies: Object + requires: string[] + ext: Object + onMessage: (params: OnMessageParams) => void + onClose: (params: RequestParams) => void } -interface RequestParams { - args: Object - headers: Object - request: Request - client: WSClient - caller: Caller - session: Session - response: Response - logger: Logger +export interface RequestParams { + args: Object + headers: Object + request: Request + client: WSClient + caller: Caller + session: Session + response: Response + logger: Logger } -interface OnMessageParams { - type: string - data: string | Object - client: WSClient - session: Session - logger: Logger +export interface OnMessageParams { + type: string + data: string | Object + client: WSClient + session: Session + logger: Logger } -interface WSClient { - id: string - read: () => WSMessage - write: (data: any) => void - writeMessage: (type: string, data: any) => void - ping: () => void - close: () => void +export interface WSClient { + id: string + read: () => WSMessage + write: (data: any) => void + writeMessage: (type: string, data: any) => void + ping: () => void + close: () => void } -interface WSMessage { - type: string - data: string | Object +export interface WSMessage { + type: string + data: string | Object } -interface Session { - set: (key: string | Object, value?: any) => void - get: (...keys: string[]) => any | Object - remove: (...keys: string[]) => void - setAuthLevel: (authLevel: number) => void - save: () => void +export interface Session { + set: (key: string | Object, value?: any) => void + get: (...keys: string[]) => any | Object + remove: (...keys: string[]) => void + setAuthLevel: (authLevel: number) => void + save: () => void } -interface Caller { - get(url: string, headers?: Object): Result - head(url: string, headers?: Object): Result - post(url: string, data: any, headers?: Object): Result - put(url: string, data: any, headers?: Object): Result - delete(url: string, data: any, headers?: Object): Result - do(method: string, url: string, data: any, callback?: (data: string) => void, headers?: Object): Result +export interface Caller { + get(url: string, headers?: Object): Result + head(url: string, headers?: Object): Result + post(url: string, data: any, headers?: Object): Result + put(url: string, data: any, headers?: Object): Result + delete(url: string, data: any, headers?: Object): Result + do(method: string, url: string, data: any, callback?: (data: string) => void, headers?: Object): Result } -interface Result { - status: string - statusCode: number - headers: Object - bytes(): Uint8Array - string(): string - object(): Object +export interface Result { + status: string + statusCode: number + headers: Object + bytes(): Uint8Array + string(): string + object(): Object } -interface CookieOption { - path: string - domain: string - expires: any - maxAge: number - secure: boolean - httpOnly: boolean +export interface CookieOption { + path: string + domain: string + expires: any + maxAge: number + secure: boolean + httpOnly: boolean } -interface Request { - id: string - proto: string - scheme: string - host: string - method: string - path: string - remoteAddr: string - realIP: string - referer: string - userAgent: string - url: string - contentLength: number - cookies: Object - headers: Object - args: Object - files: Map - multiFiles: Map - makeURL: (path: string) => string - readAll: () => any - read: (size: number) => any - close: () => void - get: (key: string) => any - set: (key: string, value: any) => void - getHeader: (key: string) => string - setHeader: (key: string, value: string) => void - setUserID: (id: string) => void +export interface Request { + id: string + proto: string + scheme: string + host: string + method: string + path: string + remoteAddr: string + realIP: string + referer: string + userAgent: string + url: string + contentLength: number + cookies: Object + headers: Object + args: Object + files: Map + multiFiles: Map + makeURL: (path: string) => string + readAll: () => any + read: (size: number) => any + close: () => void + get: (key: string) => any + set: (key: string, value: any) => void + getHeader: (key: string) => string + setHeader: (key: string, value: string) => void + setUserID: (id: string) => void } -interface Response { - id: string - setStatus: (code: number) => void - setCookie: (name: string, value: string, option?: CookieOption) => void - setHeader: (name: string, value: string) => void - addHeader: (name: string, value: string) => void - getHeader: (name: string) => string - write: (data: any) => number - flush: () => void - sendFile: (contentType: string, filename: string) => void - downloadFile: (contentType: string, filename: string, data: any) => void - location: (url: string) => void - end: (data: any) => void +export interface Response { + id: string + setStatus: (code: number) => void + setCookie: (name: string, value: string, option?: CookieOption) => void + setHeader: (name: string, value: string) => void + addHeader: (name: string, value: string) => void + getHeader: (name: string) => string + write: (data: any) => number + flush: () => void + sendFile: (contentType: string, filename: string) => void + downloadFile: (contentType: string, filename: string, data: any) => void + location: (url: string) => void + end: (data: any) => void } -interface Logger { - debug: (message: string, info?: Object) => void - info: (message: string, info?: Object) => void - warn: (message: string, info?: Object) => void - error: (message: string, info?: Object) => void +export interface Logger { + debug: (message: string, info?: Object) => void + info: (message: string, info?: Object) => void + warn: (message: string, info?: Object) => void + error: (message: string, info?: Object) => void } -interface UploadFile { - name: string - size: number - data: any +export interface UploadFile { + name: string + size: number + data: any }