编辑
2024-11-01
后端
00
请注意,本文编写于 190 天前,最后修改于 190 天前,其中某些信息可能已经过时。

目录

主要配置项

今天上午又开了一上午会,没办法,竞争对手太给力,无聊看看fiber,最近一直在玩fiber,minty也是基于fiber,也提了一些issue,社区还算活跃

今天看几个基础结构吧

首先还是看app文件,很多核心结构都在里面

go
// Version 表示当前 fiber 包的版本 const Version = "2.52.5" // Handler 定义了一个用于处理 HTTP 请求的函数类型。 type Handler = func(*Ctx) error // 路由的Handler和中间件都是一个Handler // Map 是 map[string]interface{} 的快捷方式,适用于 JSON 返回值,类似于gin.H type Map map[string]interface{} // Storage 接口用于与不同的数据库/键值存储提供者进行通信 type Storage interface { // Get 获取给定键的值。 // 如果键不存在,则返回 `nil, nil` Get(key string) ([]byte, error) // Set 存储给定键的值,并附带一个过期时间,0 表示不过期。 // 空键或空值将被忽略,不会返回错误。 Set(key string, val []byte, exp time.Duration) error // Delete 删除给定键的值。 // 如果存储中不包含该键,则不会返回错误。 Delete(key string) error // Reset 重置存储并删除所有键。 Reset() error // Close 关闭存储,并停止任何正在运行的垃圾收集器和打开的连接。 Close() error }

接下来是ErrorHandler,它类似于全局异常捕获,允许你统一处理未处理的异常

go
// ErrorHandler 定义了一个函数,该函数将处理堆栈中任何处理程序返回的所有错误 // // cfg := fiber.Config{} // cfg.ErrorHandler = func(c *Ctx, err error) error { // code := StatusInternalServerError // var e *fiber.Error // if errors.As(err, &e) { // code = e.Code // } // c.Set(HeaderContentType, MIMETextPlainCharsetUTF8) // return c.Status(code).SendString(err.Error()) // } // app := fiber.New(cfg) type ErrorHandler = func(*Ctx, error) error // Error 表示在处理请求时发生的错误。 type Error struct { Code int `json:"code"` Message string `json:"message"` }

下面是一个示例

go
package main import ( "errors" "fmt" "github.com/gofiber/fiber/v2" "net/http" ) // 自定义错误类型 type CustomError struct { Code int Message string } // 实现 Error 接口 func (e *CustomError) Error() string { return e.Message } func main() { // 创建 Fiber 应用 app := fiber.New(fiber.Config{ // 配置 ErrorHandler ErrorHandler: func(c *fiber.Ctx, err error) error { // 获取 HTTP 状态码,默认为 500 code := fiber.StatusInternalServerError // 检查是否是自定义错误类型 var e *CustomError if errors.As(err, &e) { code = e.Code } // 设置响应头 c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8) // 返回错误信息 return c.Status(code).SendString(err.Error()) }, }) // 定义一个路由,故意抛出一个错误 app.Get("/error", func(c *fiber.Ctx) error { // 抛出一个自定义错误 return &CustomError{ Code: http.StatusBadRequest, Message: "这是一个自定义错误", } }) // 定义另一个路由,故意抛出一个未处理的错误 app.Get("/panic", func(c *fiber.Ctx) error { // 抛出一个未处理的错误 return fmt.Errorf("这是一个未处理的错误") }) // 启动应用 err := app.Listen(":3000") if err != nil { fmt.Println("启动服务器失败:", err) } }

接下来是App结构

go
// App denotes the Fiber application. type App struct { mutex sync.Mutex // Route stack divided by HTTP methods stack [][]*Route // Route stack divided by HTTP methods and route prefixes treeStack []map[string][]*Route // contains the information if the route stack has been changed to build the optimized tree routesRefreshed bool // Amount of registered routes routesCount uint32 // Amount of registered handlers handlersCount uint32 // Ctx pool pool sync.Pool // Fasthttp server server *fasthttp.Server // App config config Config // Converts string to a byte slice getBytes func(s string) (b []byte) // Converts byte slice to a string getString func(b []byte) string // Hooks hooks *Hooks // Latest route & group latestRoute *Route // TLS handler tlsHandler *TLSHandler // Mount fields mountFields *mountFields // Indicates if the value was explicitly configured configured Config }

接下来从New函数看下去,主要还是一个初始化配置和申请内存的过程

go
// New 创建一个新的 Fiber 命名实例。 // // app := fiber.New() // // 你可以通过传递一个 Config 结构体来传递可选的配置选项: // // app := fiber.New(fiber.Config{ // Prefork: true, // ServerHeader: "Fiber", // }) func New(config ...Config) *App { // 创建一个新的应用 app := &App{ // 创建 Ctx 池 pool: sync.Pool{ New: func() interface{} { return new(Ctx) }, }, // 创建配置 config: Config{}, getBytes: utils.UnsafeBytes, getString: utils.UnsafeString, latestRoute: &Route{}, } // 定义钩子 app.hooks = newHooks(app) // 定义挂载字段 app.mountFields = newMountFields(app) // 如果提供了配置,则覆盖默认配置 if len(config) > 0 { app.config = config[0] } // 在设置默认值之前初始化配置 app.configured = app.config if app.config.ETag { if !IsChild() { log.Warn("Config.ETag 自 v2.0.6 起已弃用,请使用 'middleware/etag'。") } } // 覆盖默认值 if app.config.BodyLimit == 0 { app.config.BodyLimit = DefaultBodyLimit } if app.config.Concurrency <= 0 { app.config.Concurrency = DefaultConcurrency } if app.config.ReadBufferSize <= 0 { app.config.ReadBufferSize = DefaultReadBufferSize } if app.config.WriteBufferSize <= 0 { app.config.WriteBufferSize = DefaultWriteBufferSize } if app.config.CompressedFileSuffix == "" { app.config.CompressedFileSuffix = DefaultCompressedFileSuffix } if app.config.Immutable { app.getBytes, app.getString = getBytesImmutable, getStringImmutable } if app.config.ErrorHandler == nil { app.config.ErrorHandler = DefaultErrorHandler } if app.config.JSONEncoder == nil { app.config.JSONEncoder = json.Marshal } if app.config.JSONDecoder == nil { app.config.JSONDecoder = json.Unmarshal } if app.config.XMLEncoder == nil { app.config.XMLEncoder = xml.Marshal } if app.config.Network == "" { app.config.Network = NetworkTCP4 } if len(app.config.RequestMethods) == 0 { app.config.RequestMethods = DefaultMethods } app.config.trustedProxiesMap = make(map[string]struct{}, len(app.config.TrustedProxies)) for _, ipAddress := range app.config.TrustedProxies { app.handleTrustedProxy(ipAddress) } // 创建路由堆栈 app.stack = make([][]*Route, len(app.config.RequestMethods)) app.treeStack = make([]map[string][]*Route, len(app.config.RequestMethods)) // 覆盖颜色 app.config.ColorScheme = defaultColors(app.config.ColorScheme) // 初始化应用 app.init() // 返回应用 return app }

大概过一眼fiber.Config有哪些配置项,不用记,有个印象就好

go
// Config is a struct holding the server settings. type Config struct { // When set to true, this will spawn multiple Go processes listening on the same port. // // Default: false Prefork bool `json:"prefork"` // Enables the "Server: value" HTTP header. // // Default: "" ServerHeader string `json:"server_header"` // When set to true, the router treats "/foo" and "/foo/" as different. // By default this is disabled and both "/foo" and "/foo/" will execute the same handler. // // Default: false StrictRouting bool `json:"strict_routing"` // When set to true, enables case sensitive routing. // E.g. "/FoO" and "/foo" are treated as different routes. // By default this is disabled and both "/FoO" and "/foo" will execute the same handler. // // Default: false CaseSensitive bool `json:"case_sensitive"` // When set to true, this relinquishes the 0-allocation promise in certain // cases in order to access the handler values (e.g. request bodies) in an // immutable fashion so that these values are available even if you return // from handler. // // Default: false Immutable bool `json:"immutable"` // When set to true, converts all encoded characters in the route back // before setting the path for the context, so that the routing, // the returning of the current url from the context `ctx.Path()` // and the parameters `ctx.Params(%key%)` with decoded characters will work // // Default: false UnescapePath bool `json:"unescape_path"` // Enable or disable ETag header generation, since both weak and strong etags are generated // using the same hashing method (CRC-32). Weak ETags are the default when enabled. // // Default: false ETag bool `json:"etag"` // Max body size that the server accepts. // -1 will decline any body size // // Default: 4 * 1024 * 1024 BodyLimit int `json:"body_limit"` // Maximum number of concurrent connections. // // Default: 256 * 1024 Concurrency int `json:"concurrency"` // Views is the interface that wraps the Render function. // // Default: nil Views Views `json:"-"` // Views Layout is the global layout for all template render until override on Render function. // // Default: "" ViewsLayout string `json:"views_layout"` // PassLocalsToViews Enables passing of the locals set on a fiber.Ctx to the template engine // // Default: false PassLocalsToViews bool `json:"pass_locals_to_views"` // The amount of time allowed to read the full request including body. // It is reset after the request handler has returned. // The connection's read deadline is reset when the connection opens. // // Default: unlimited ReadTimeout time.Duration `json:"read_timeout"` // The maximum duration before timing out writes of the response. // It is reset after the request handler has returned. // // Default: unlimited WriteTimeout time.Duration `json:"write_timeout"` // The maximum amount of time to wait for the next request when keep-alive is enabled. // If IdleTimeout is zero, the value of ReadTimeout is used. // // Default: unlimited IdleTimeout time.Duration `json:"idle_timeout"` // Per-connection buffer size for requests' reading. // This also limits the maximum header size. // Increase this buffer if your clients send multi-KB RequestURIs // and/or multi-KB headers (for example, BIG cookies). // // Default: 4096 ReadBufferSize int `json:"read_buffer_size"` // Per-connection buffer size for responses' writing. // // Default: 4096 WriteBufferSize int `json:"write_buffer_size"` // CompressedFileSuffix adds suffix to the original file name and // tries saving the resulting compressed file under the new file name. // // Default: ".fiber.gz" CompressedFileSuffix string `json:"compressed_file_suffix"` // ProxyHeader will enable c.IP() to return the value of the given header key // By default c.IP() will return the Remote IP from the TCP connection // This property can be useful if you are behind a load balancer: X-Forwarded-* // NOTE: headers are easily spoofed and the detected IP addresses are unreliable. // // Default: "" ProxyHeader string `json:"proxy_header"` // GETOnly rejects all non-GET requests if set to true. // This option is useful as anti-DoS protection for servers // accepting only GET requests. The request size is limited // by ReadBufferSize if GETOnly is set. // // Default: false GETOnly bool `json:"get_only"` // ErrorHandler is executed when an error is returned from fiber.Handler. // // Default: DefaultErrorHandler ErrorHandler ErrorHandler `json:"-"` // When set to true, disables keep-alive connections. // The server will close incoming connections after sending the first response to client. // // Default: false DisableKeepalive bool `json:"disable_keepalive"` // When set to true, causes the default date header to be excluded from the response. // // Default: false DisableDefaultDate bool `json:"disable_default_date"` // When set to true, causes the default Content-Type header to be excluded from the response. // // Default: false DisableDefaultContentType bool `json:"disable_default_content_type"` // When set to true, disables header normalization. // By default all header names are normalized: conteNT-tYPE -> Content-Type. // // Default: false DisableHeaderNormalizing bool `json:"disable_header_normalizing"` // When set to true, it will not print out the «Fiber» ASCII art and listening address. // // Default: false DisableStartupMessage bool `json:"disable_startup_message"` // This function allows to setup app name for the app // // Default: nil AppName string `json:"app_name"` // StreamRequestBody enables request body streaming, // and calls the handler sooner when given body is // larger then the current limit. StreamRequestBody bool // Will not pre parse Multipart Form data if set to true. // // This option is useful for servers that desire to treat // multipart form data as a binary blob, or choose when to parse the data. // // Server pre parses multipart form data by default. DisablePreParseMultipartForm bool // Aggressively reduces memory usage at the cost of higher CPU usage // if set to true. // // Try enabling this option only if the server consumes too much memory // serving mostly idle keep-alive connections. This may reduce memory // usage by more than 50%. // // Default: false ReduceMemoryUsage bool `json:"reduce_memory_usage"` // FEATURE: v2.3.x // The router executes the same handler by default if StrictRouting or CaseSensitive is disabled. // Enabling RedirectFixedPath will change this behavior into a client redirect to the original route path. // Using the status code 301 for GET requests and 308 for all other request methods. // // Default: false // RedirectFixedPath bool // When set by an external client of Fiber it will use the provided implementation of a // JSONMarshal // // Allowing for flexibility in using another json library for encoding // Default: json.Marshal JSONEncoder utils.JSONMarshal `json:"-"` // When set by an external client of Fiber it will use the provided implementation of a // JSONUnmarshal // // Allowing for flexibility in using another json library for decoding // Default: json.Unmarshal JSONDecoder utils.JSONUnmarshal `json:"-"` // XMLEncoder set by an external client of Fiber it will use the provided implementation of a // XMLMarshal // // Allowing for flexibility in using another XML library for encoding // Default: xml.Marshal XMLEncoder utils.XMLMarshal `json:"-"` // Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only) // WARNING: When prefork is set to true, only "tcp4" and "tcp6" can be chose. // // Default: NetworkTCP4 Network string // If you find yourself behind some sort of proxy, like a load balancer, // then certain header information may be sent to you using special X-Forwarded-* headers or the Forwarded header. // For example, the Host HTTP header is usually used to return the requested host. // But when you’re behind a proxy, the actual host may be stored in an X-Forwarded-Host header. // // If you are behind a proxy, you should enable TrustedProxyCheck to prevent header spoofing. // If you enable EnableTrustedProxyCheck and leave TrustedProxies empty Fiber will skip // all headers that could be spoofed. // If request ip in TrustedProxies whitelist then: // 1. c.Protocol() get value from X-Forwarded-Proto, X-Forwarded-Protocol, X-Forwarded-Ssl or X-Url-Scheme header // 2. c.IP() get value from ProxyHeader header. // 3. c.Hostname() get value from X-Forwarded-Host header // But if request ip NOT in Trusted Proxies whitelist then: // 1. c.Protocol() WON't get value from X-Forwarded-Proto, X-Forwarded-Protocol, X-Forwarded-Ssl or X-Url-Scheme header, // will return https in case when tls connection is handled by the app, of http otherwise // 2. c.IP() WON'T get value from ProxyHeader header, will return RemoteIP() from fasthttp context // 3. c.Hostname() WON'T get value from X-Forwarded-Host header, fasthttp.Request.URI().Host() // will be used to get the hostname. // // Default: false EnableTrustedProxyCheck bool `json:"enable_trusted_proxy_check"` // Read EnableTrustedProxyCheck doc. // // Default: []string TrustedProxies []string `json:"trusted_proxies"` trustedProxiesMap map[string]struct{} trustedProxyRanges []*net.IPNet // If set to true, c.IP() and c.IPs() will validate IP addresses before returning them. // Also, c.IP() will return only the first valid IP rather than just the raw header // WARNING: this has a performance cost associated with it. // // Default: false EnableIPValidation bool `json:"enable_ip_validation"` // If set to true, will print all routes with their method, path and handler. // Default: false EnablePrintRoutes bool `json:"enable_print_routes"` // You can define custom color scheme. They'll be used for startup message, route list and some middlewares. // // Optional. Default: DefaultColors ColorScheme Colors `json:"color_scheme"` // RequestMethods provides customizibility for HTTP methods. You can add/remove methods as you wish. // // Optional. Default: DefaultMethods RequestMethods []string // EnableSplittingOnParsers splits the query/body/header parameters by comma when it's true. // For example, you can use it to parse multiple values from a query parameter like this: // /api?foo=bar,baz == foo[]=bar&foo[]=baz // // Optional. Default: false EnableSplittingOnParsers bool `json:"enable_splitting_on_parsers"` }

主要配置项

  1. Prefork:

    • 类型: bool
    • 描述: 当设置为 true 时,将创建多个 Go 进程监听同一端口。
    • 默认值: false
  2. ServerHeader:

    • 类型: string
    • 描述: 启用 "Server: value" HTTP 头。
    • 默认值: ""
  3. StrictRouting:

    • 类型: bool
    • 描述: 当设置为 true 时,路由器将 /foo/foo/ 视为不同。
    • 默认值: false
  4. CaseSensitive:

    • 类型: bool
    • 描述: 当设置为 true 时,启用区分大小写的路由。
    • 默认值: false
  5. Immutable:

    • 类型: bool
    • 描述: 当设置为 true 时,以不可变的方式访问处理程序中的值。
    • 默认值: false
  6. UnescapePath:

    • 类型: bool
    • 描述: 当设置为 true 时,将所有编码字符转换回原始字符。
    • 默认值: false
  7. ETag:

    • 类型: bool
    • 描述: 启用 ETag 头生成。
    • 默认值: false
  8. BodyLimit:

    • 类型: int
    • 描述: 服务器接受的最大请求体大小。
    • 默认值: 4 * 1024 * 1024
  9. Concurrency:

    • 类型: int
    • 描述: 最大并发连接数。
    • 默认值: 256 * 1024
  10. Views:

    • 类型: Views
    • 描述: 视图接口,用于包装 Render 函数。
    • 默认值: nil
  11. ViewsLayout:

    • 类型: string
    • 描述: 全局布局,用于所有模板渲染。
    • 默认值: ""
  12. PassLocalsToViews:

    • 类型: bool
    • 描述: 启用将本地变量传递给视图模板。
    • 默认值: false
  13. ReadTimeout:

    • 类型: time.Duration
    • 描述: 读取完整请求(包括请求体)的最大时间。
    • 默认值: 无限制
  14. WriteTimeout:

    • 类型: time.Duration
    • 描述: 写入响应的最大时间。
    • 默认值: 无限制
  15. IdleTimeout:

    • 类型: time.Duration
    • 描述: 保持连接的最大空闲时间。
    • 默认值: 无限制
  16. ReadBufferSize:

    • 类型: int
    • 描述: 每个连接的读取缓冲区大小。
    • 默认值: 4096
  17. WriteBufferSize:

    • 类型: int
    • 描述: 每个连接的写入缓冲区大小。
    • 默认值: 4096
  18. CompressedFileSuffix:

    • 类型: string
    • 描述: 压缩文件的后缀。
    • 默认值: ".fiber.gz"
  19. ProxyHeader:

    • 类型: string
    • 描述: 启用代理头,使 c.IP() 返回代理头的值。
    • 默认值: ""
  20. GETOnly:

    • 类型: bool
    • 描述: 拒绝所有非 GET 请求。
    • 默认值: false
  21. ErrorHandler:

    • 类型: ErrorHandler
    • 描述: 处理从 fiber.Handler 返回的错误。
    • 默认值: DefaultErrorHandler
  22. DisableKeepalive:

    • 类型: bool
    • 描述: 禁用保持连接。
    • 默认值: false
  23. DisableDefaultDate:

    • 类型: bool
    • 描述: 禁用默认日期头。
    • 默认值: false
  24. DisableDefaultContentType:

    • 类型: bool
    • 描述: 禁用默认内容类型头。
    • 默认值: false
  25. DisableHeaderNormalizing:

    • 类型: bool
    • 描述: 禁用头规范化。
    • 默认值: false
  26. DisableStartupMessage:

    • 类型: bool
    • 描述: 禁用启动消息。
    • 默认值: false
  27. AppName:

    • 类型: string
    • 描述: 应用名称。
    • 默认值: nil
  28. StreamRequestBody:

    • 类型: bool
    • 描述: 启用请求体流式处理。
    • 默认值: false
  29. DisablePreParseMultipartForm:

    • 类型: bool
    • 描述: 禁用预解析多部分表单数据。
    • 默认值: false
  30. ReduceMemoryUsage:

    • 类型: bool
    • 描述: 启用内存使用优化。
    • 默认值: false
  31. JSONEncoder:

    • 类型: utils.JSONMarshal
    • 描述: 自定义 JSON 编码器。
    • 默认值: json.Marshal
  32. JSONDecoder:

    • 类型: utils.JSONUnmarshal
    • 描述: 自定义 JSON 解码器。
    • 默认值: json.Unmarshal
  33. XMLEncoder:

    • 类型: utils.XMLMarshal
    • 描述: 自定义 XML 编码器。
    • 默认值: xml.Marshal
  34. Network:

    • 类型: string
    • 描述: 已知网络类型,如 "tcp", "tcp4", "tcp6"。
    • 默认值: NetworkTCP4
  35. EnableTrustedProxyCheck:

    • 类型: bool
    • 描述: 启用受信任代理检查。
    • 默认值: false
  36. TrustedProxies:

    • 类型: []string
    • 描述: 受信任的代理列表。
    • 默认值: []string
  37. EnableIPValidation:

    • 类型: bool
    • 描述: 启用 IP 地址验证。
    • 默认值: false
  38. EnablePrintRoutes:

    • 类型: bool
    • 描述: 启用打印所有路由。
    • 默认值: false
  39. ColorScheme:

    • 类型: Colors
    • 描述: 自定义颜色方案。
    • 默认值: DefaultColors
  40. RequestMethods:

    • 类型: []string
    • 描述: 自定义 HTTP 方法。
    • 默认值: DefaultMethods
  41. EnableSplittingOnParsers:

    • 类型: bool
    • 描述: 启用查询/主体/头参数的逗号分割。
    • 默认值: false

接下来是一些常量

go
// 默认配置值 const ( DefaultBodyLimit = 4 * 1024 * 1024 // 默认请求体大小限制 DefaultConcurrency = 256 * 1024 // 默认并发连接数 DefaultReadBufferSize = 4096 // 默认读取缓冲区大小 DefaultWriteBufferSize = 4096 // 默认写入缓冲区大小 DefaultCompressedFileSuffix = ".fiber.gz" // 默认压缩文件后缀 ) // 默认启用的 HTTP 方法 var DefaultMethods = []string{ MethodGet, // GET 方法 MethodHead, // HEAD 方法 MethodPost, // POST 方法 MethodPut, // PUT 方法 MethodDelete, // DELETE 方法 MethodConnect, // CONNECT 方法 MethodOptions, // OPTIONS 方法 MethodTrace, // TRACE 方法 MethodPatch, // PATCH 方法 }

默认的ErrorHnadler,他会处理所有Error

go
// DefaultErrorHandler that process return errors from handlers func DefaultErrorHandler(c *Ctx, err error) error { code := StatusInternalServerError var e *Error if errors.As(err, &e) { code = e.Code } c.Set(HeaderContentType, MIMETextPlainCharsetUTF8) return c.Status(code).SendString(err.Error()) }

本文作者:yowayimono

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!