Repository: gofiber/fiber
File: ctx.go (Go)

Code before:
	// Write response body
	c.fasthttp.Response.SetBodyRaw(body)
	return nil
}

var (
	sendFileOnce              sync.Once
	sendFileFS                *fasthttp.FS
	sendFileHandler           fasthttp.RequestHandler
	SendFileWithConfigOnce    sync.Once
	SendFileWithConfigFS      *fasthttp.FS
	SendFileWithConfigHandler fasthttp.RequestHandler
)

// SendFile transfers the file from the given path.
// The file is not compressed by default, enable this by passing a 'true' argument
// Sets the Content-Type response HTTP header field based on the filenames extension.
func (c *Ctx) SendFile(file string, compress ...bool) error {
	// Save the filename, we will need it in the error message if the file isn't found
	filename := file

	// https://github.com/valyala/fasthttp/blob/master/fs.go#L81
	sendFileOnce.Do(func() {
		sendFileFS = &fasthttp.FS{
			Root:                 "/",
			GenerateIndexPages:   false,
			AcceptByteRange:      true,
			Compress:             true,
			CompressedFileSuffix: c.app.config.CompressedFileSuffix,
			CacheDuration:        10 * time.Second,
			IndexNames:           []string{"index.html"},
			PathNotFound: func(ctx *fasthttp.RequestCtx) {
				ctx.Response.SetStatusCode(StatusNotFound)
			},
		}
		sendFileHandler = sendFileFS.NewRequestHandler()
	})

	// Keep original path for mutable params
	c.pathOriginal = utils.CopyString(c.pathOriginal)
	// Disable compression
	if len(compress) == 0 || !compress[0] {
		// https://github.com/valyala/fasthttp/blob/master/fs.go#L46
		c.fasthttp.Request.Header.Del(HeaderAcceptEncoding)
	}
	// https://github.com/valyala/fasthttp/blob/master/fs.go#L85
	if len(file) == 0 || file[0] != '/' {
		hasTrailingSlash := len(file) > 0 && file[len(file)-1] == '/'
		var err error
		if file, err = filepath.Abs(file); err != nil {
			return err

Review comment (refactor):
the code looks very similar to the sendFile method, can we swap the core of both methods into a private and control both with it

or at least that the SendFile method uses SendFileWithConfig 

```go
func (c *Ctx) SendFile(file string, compress ...bool) error {
     return c.SendFileWithConfig(file, SendFile{Compress: compress})
}
```


would be good if we could remove as many duplicate variables and keep the code small






Code after:
	// Write response body
	c.fasthttp.Response.SetBodyRaw(body)
	return nil
}

var (
	sendFileOnce    sync.Once
	sendFileFS      *fasthttp.FS
	sendFileHandler fasthttp.RequestHandler
)

// SendFile transfers the file from the given path.
// The file is not compressed by default, enable this by passing a 'true' argument
// Sets the Content-Type response HTTP header field based on the filenames extension.
func (c *Ctx) SendFile(file string, compress ...bool) error {
	if len(compress) > 0 {
		return c.SendFileWithConfig(file, SendFile{Compress: compress[0]})
	}

	return c.SendFileWithConfig(file)
}

// SendFileWithConfig transfers the file from the given path.
// Some config fields are overwritten. You can change them by config parameter.
// Sets the Content-Type response HTTP header field based on the filenames extension.
func (c *Ctx) SendFileWithConfig(file string, config ...SendFile) error {
	// Save the filename, we will need it in the error message if the file isn't found
	filename := file

	// https://github.com/valyala/fasthttp/blob/master/fs.go#L81
	sendFileOnce.Do(func() {
		sendFileFS = &fasthttp.FS{
			Root:                 "/",
			GenerateIndexPages:   false,
			AcceptByteRange:      true,
			Compress:             true,
			CompressedFileSuffix: c.app.config.CompressedFileSuffix,
			CacheDuration:        10 * time.Second,
			IndexNames:           []string{"index.html"},
			PathNotFound: func(ctx *fasthttp.RequestCtx) {
				ctx.Response.SetStatusCode(StatusNotFound)
			},
		}
		sendFileHandler = sendFileFS.NewRequestHandler()
	})

	// Keep original path for mutable params
	c.pathOriginal = utils.CopyString(c.pathOriginal)
	// Disable compression
	// Set config if provided
	var cacheControlValue string