diff --git a/sources/lib/server/headers-magic.go b/sources/lib/server/headers-magic.go index 157cd02..257a985 100644 --- a/sources/lib/server/headers-magic.go +++ b/sources/lib/server/headers-magic.go @@ -40,9 +40,21 @@ func (_buffer *HttpResponseWriterHeadersBuffer) Include (_name []byte, _value [] } -func (_buffer *HttpResponseWriterHeadersBuffer) WriteTo (_response http.ResponseWriter) () { + + +func (_buffer *HttpResponseWriterHeadersBuffer) WriteToGenericResponse (_response http.ResponseWriter) () { - _headers := HttpResponseWriterHeaderDoMagic (_response) + _headers := _response.Header () + + _buffer.WriteToGenericHeaders (_headers) + + _response.WriteHeader (_buffer.status) +} + + + + +func (_buffer *HttpResponseWriterHeadersBuffer) WriteToGenericHeaders (_headers http.Header) () { for _index := 0; _index < _buffer.headersCount; _index += 1 { @@ -62,21 +74,99 @@ func (_buffer *HttpResponseWriterHeadersBuffer) WriteTo (_response http.Response } _headers["Date"] = nil - - _response.WriteHeader (_buffer.status) } -func HttpResponseWriterHeaderDoMagic (_response http.ResponseWriter) (http.Header) { +func (_buffer *HttpResponseWriterHeadersBuffer) WriteTo (_response http.ResponseWriter) () { - if !_httpResponseWriteHeaderMagic_enabled { - return _response.Header () + if !_httpResponseWriterHeadersMagic_enabled { + _buffer.WriteToGenericResponse (_response) + return } + _responseRaw := *(*[2]uintptr) (unsafe.Pointer (&_response)) + _responseType := _responseRaw[0] + + + _redo : + + _netHttp1Type := atomic.LoadUintptr (&_httpResponseWriterHeadersMagic_netHttp1_type) + if _responseType == _netHttp1Type { + _buffer.WriteToNetHttp1 (_response) + return + } + + _netHttp2Type := atomic.LoadUintptr (&_httpResponseWriterHeadersMagic_netHttp2_type) + if _responseType == _netHttp2Type { + _buffer.WriteToNetHttp2 (_response) + return + } + + _quicHttp3Type := atomic.LoadUintptr (&_httpResponseWriterHeadersMagic_quicHttp3_type) + if _responseType == _quicHttp3Type { + _buffer.WriteToQuicHttp3 (_response) + return + } + + _httpResponseWriterHeadersMagic_detect (_response) + + goto _redo +} + +var _httpResponseWriterHeadersMagic_netHttp1_type uintptr +var _httpResponseWriterHeadersMagic_netHttp2_type uintptr +var _httpResponseWriterHeadersMagic_quicHttp3_type uintptr + + + + +func (_buffer *HttpResponseWriterHeadersBuffer) WriteToNetHttp1 (_response http.ResponseWriter) () { + + _responseRaw := *(*[2]uintptr) (unsafe.Pointer (&_response)) + _responseAddress := unsafe.Pointer (_responseRaw[1]) + + _headers := make (map[string][]string, 16) + + { + _handlerHeaderOffset := atomic.LoadInt32 (&_httpResponseWriterHeadersMagic_netHttp1_handlerHeaderOffset) + _cwHeaderOffset := atomic.LoadInt32 (&_httpResponseWriterHeadersMagic_netHttp1_cwHeaderOffset) + + _handlerHeaderValue := (*http.Header) (unsafe.Add (_responseAddress, _handlerHeaderOffset)) + _cwHeaderValue := (*http.Header) (unsafe.Add (_responseAddress, _cwHeaderOffset)) + + *_handlerHeaderValue = _headers + *_cwHeaderValue = _headers + } + + _buffer.WriteToGenericHeaders (_headers) +} + + + + +func (_buffer *HttpResponseWriterHeadersBuffer) WriteToNetHttp2 (_response http.ResponseWriter) () { + + _buffer.WriteToGenericResponse (_response) +} + + + + +func (_buffer *HttpResponseWriterHeadersBuffer) WriteToQuicHttp3 (_response http.ResponseWriter) () { + + _buffer.WriteToGenericResponse (_response) +} + + + + +func _httpResponseWriterHeadersMagic_detect (_response http.ResponseWriter) { + + // NOTE: Because we don't modify the headers after calling `WriteHeader`, // the following code tricks `net/http` into believing it didn't gave us the headers. // This eliminates the `http.Header.Clone()` call on `WriteHeader`. @@ -87,68 +177,59 @@ func HttpResponseWriterHeaderDoMagic (_response http.ResponseWriter) (http.Heade _responsePackage := _responseType.PkgPath () _responseTypeName := _responseType.Name () - var _header http.Header + _responseRaw := *(*[2]uintptr) (unsafe.Pointer (&_response)) + _responseRawType := _responseRaw[0] switch { case (_responsePackage == "net/http") && (_responseTypeName == "response") : { - _handlerHeaderOffset := atomic.LoadInt32 (&_httpResponseWriteHeaderMagic_netHttp_handlerHeaderOffset) - _cwHeaderOffset := atomic.LoadInt32 (&_httpResponseWriteHeaderMagic_netHttp_cwHeaderOffset) + log.Printf ("[dd] [73f6be95] [magic] detected NetHttp1 (`%s.%s`) with type `%08x`;", _responsePackage, _responseTypeName, _responseRawType) - if (_handlerHeaderOffset == 0) || (_cwHeaderOffset == 0) { - - _handlerHeaderReflect := _responseReflect.FieldByName ("handlerHeader") - _handlerHeaderAddress := unsafe.Pointer (_handlerHeaderReflect.UnsafeAddr ()) - - _cwHeaderReflect := _responseReflect.FieldByName ("cw") .FieldByName ("header") - _cwHeaderAddress := unsafe.Pointer (_cwHeaderReflect.UnsafeAddr ()) - - _handlerHeaderOffset = int32 (int64 (uintptr (_handlerHeaderAddress)) - int64 (uintptr (_responseAddress))) - _cwHeaderOffset = int32 (int64 (uintptr (_cwHeaderAddress)) - int64 (uintptr (_responseAddress))) - - atomic.StoreInt32 (&_httpResponseWriteHeaderMagic_netHttp_handlerHeaderOffset, _handlerHeaderOffset) - atomic.StoreInt32 (&_httpResponseWriteHeaderMagic_netHttp_cwHeaderOffset, _cwHeaderOffset) - } + _handlerHeaderReflect := _responseReflect.FieldByName ("handlerHeader") + _handlerHeaderAddress := unsafe.Pointer (_handlerHeaderReflect.UnsafeAddr ()) - _handlerHeaderValue := (*http.Header) (unsafe.Add (_responseAddress, _handlerHeaderOffset)) - _cwHeaderValue := (*http.Header) (unsafe.Add (_responseAddress, _cwHeaderOffset)) + _cwHeaderReflect := _responseReflect.FieldByName ("cw") .FieldByName ("header") + _cwHeaderAddress := unsafe.Pointer (_cwHeaderReflect.UnsafeAddr ()) - _header = make (map[string][]string, 16) + _handlerHeaderOffset := int32 (int64 (uintptr (_handlerHeaderAddress)) - int64 (uintptr (_responseAddress))) + _cwHeaderOffset := int32 (int64 (uintptr (_cwHeaderAddress)) - int64 (uintptr (_responseAddress))) - *_handlerHeaderValue = _header - *_cwHeaderValue = _header + atomic.StoreInt32 (&_httpResponseWriterHeadersMagic_netHttp1_handlerHeaderOffset, _handlerHeaderOffset) + atomic.StoreInt32 (&_httpResponseWriterHeadersMagic_netHttp1_cwHeaderOffset, _cwHeaderOffset) + + atomic.StoreUintptr (&_httpResponseWriterHeadersMagic_netHttp1_type, _responseRawType) } case (_responsePackage == "net/http") && (_responseTypeName == "http2responseWriter") : { - _header = _response.Header () + log.Printf ("[dd] [cfb457eb] [magic] detected NetHttp2 (`%s.%s`) with type `%08x`;", _responsePackage, _responseTypeName, _responseRawType) + + atomic.StoreUintptr (&_httpResponseWriterHeadersMagic_netHttp2_type, _responseRawType) } case (_responsePackage == "github.com/lucas-clemente/quic-go/http3") && (_responseTypeName == "responseWriter") : { - _header = _response.Header () + log.Printf ("[dd] [90b8f7c6] [magic] detected QuicHttp3 (`%s.%s`) with type `%08x`;", _responsePackage, _responseTypeName, _responseRawType) + + atomic.StoreUintptr (&_httpResponseWriterHeadersMagic_quicHttp3_type, _responseRawType) } default : { log.Printf ("[ee] [64583df9] unsupported HTTP ResponseWriter `%s.%s`!\n", _responsePackage, _responseTypeName) - if _httpResponseWriteHeaderMagic_panic { + if _httpResponseWriterHeadersMagic_panic { panic (fmt.Sprintf ("[09274c17] unsupported HTTP ResponseWriter `%s.%s`!", _responsePackage, _responseTypeName)) } - - _header = _response.Header () } } - - return _header } -var _httpResponseWriteHeaderMagic_enabled = true -var _httpResponseWriteHeaderMagic_panic = true +var _httpResponseWriterHeadersMagic_enabled = true +var _httpResponseWriterHeadersMagic_panic = true -var _httpResponseWriteHeaderMagic_netHttp_handlerHeaderOffset int32 -var _httpResponseWriteHeaderMagic_netHttp_cwHeaderOffset int32 +var _httpResponseWriterHeadersMagic_netHttp1_handlerHeaderOffset int32 +var _httpResponseWriterHeadersMagic_netHttp1_cwHeaderOffset int32