5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-04 07:43:11 +08:00
wails/v3/internal/assetserver/fallback_response_writer.go
Fabio Massaioli d4096868e3
[v3] Fix and optimise assetserver (#4049)
* Fix and optimize content type sniffer

- Minimize copying and buffering
- Ensure it sniffs the full 512-bytes prefix

* Fix assorted warnings

* Cleanup error formatting

- Remove unnecessary formatting calls
- Fix invalid format strings
- Standardise logging calls

* Fix and optimize index fallback method

- Pass through non-404 responses correctly
- Do not buffer original response

* Test content sniffing and index fallback

* Update changelog

* Remove obsolete check

* Add safety checks in sniffer
2025-02-09 00:02:54 +11:00

74 lines
1.6 KiB
Go

package assetserver
import (
"maps"
"net/http"
)
// fallbackResponseWriter wraps a [http.ResponseWriter].
// If the main handler returns status code 404,
// its response is discarded
// and the request is forwarded to the fallback handler.
type fallbackResponseWriter struct {
rw http.ResponseWriter
req *http.Request
fallback http.Handler
header http.Header
headerWritten bool
complete bool
}
// Unwrap returns the wrapped [http.ResponseWriter] for use with [http.ResponseController].
func (fw *fallbackResponseWriter) Unwrap() http.ResponseWriter {
return fw.rw
}
func (fw *fallbackResponseWriter) Header() http.Header {
if fw.header == nil {
// Preserve original header in case we get a 404 response.
fw.header = fw.rw.Header().Clone()
}
return fw.header
}
func (fw *fallbackResponseWriter) Write(chunk []byte) (int, error) {
if fw.complete {
// Fallback triggered, discard further writes.
return len(chunk), nil
}
if !fw.headerWritten {
fw.WriteHeader(http.StatusOK)
}
return fw.rw.Write(chunk)
}
func (fw *fallbackResponseWriter) WriteHeader(statusCode int) {
if fw.headerWritten {
return
}
fw.headerWritten = true
if statusCode == http.StatusNotFound {
// Protect fallback header from external modifications.
if fw.header == nil {
fw.header = fw.rw.Header().Clone()
}
// Invoke fallback handler.
fw.complete = true
fw.fallback.ServeHTTP(fw.rw, fw.req)
return
}
if fw.header != nil {
// Apply headers and forward original map to the main handler.
maps.Copy(fw.rw.Header(), fw.header)
fw.header = fw.rw.Header()
}
fw.rw.WriteHeader(statusCode)
}