From 967174e80fadb011b50c65c38d38c181ebc4146b Mon Sep 17 00:00:00 2001 From: Quinn Damerell Date: Fri, 13 Dec 2024 13:53:14 -0800 Subject: [PATCH] test --- homeway/homeway/WebStream/headerimpl.py | 55 ++++++++++++++++++- .../homeway/WebStream/webstreamhttphelper.py | 11 +++- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/homeway/homeway/WebStream/headerimpl.py b/homeway/homeway/WebStream/headerimpl.py index 8296e16..129ab73 100644 --- a/homeway/homeway/WebStream/headerimpl.py +++ b/homeway/homeway/WebStream/headerimpl.py @@ -4,6 +4,7 @@ from ..streammsgbuilder import StreamMsgBuilder from ..httprequest import HttpRequest +from ..Proto.PathTypes import PathTypes from ..Proto.HttpInitialContext import HttpInitialContext # Indicates the base protocol, not if it's secure or not. @@ -21,7 +22,8 @@ class HeaderHelper: @staticmethod def GatherRequestHeaders(logger:logging.Logger, httpInitialContextOptional:HttpInitialContext, protocol) : - hostAddress = HttpRequest.GetDirectServiceAddress() + # Get the correct host address for this request type. + hostAddress = HeaderHelper._HostHostAddress(logger, httpInitialContextOptional) # Get the count of headers in the message. sendHeaders = {} @@ -117,6 +119,55 @@ def GatherRequestHeaders(logger:logging.Logger, httpInitialContextOptional:HttpI return sendHeaders + # Determine the host address. + # If this is an absolute URL, we need to use the host from the URL. + @staticmethod + def _HostHostAddress(logger:logging.Logger, httpInitialContextOptional:HttpInitialContext): + + # Start with the default host address for this device. + # If we can't get the path type, we use it. + hostAddress = HttpRequest.GetDirectServiceAddress() + if httpInitialContextOptional is None: + return hostAddress + + pathType = httpInitialContextOptional.PathType() + if pathType != PathTypes.Absolute: + return hostAddress + + # If we have an absolute path, we need to parse the host out of it, + # because we don't want to use this device's host name as the host. + try: + # Get the URL + absoluteUrl = StreamMsgBuilder.BytesToString(httpInitialContextOptional.Path()) + + # Find the protocol + protocolEnd = absoluteUrl.find("://") + if protocolEnd == -1: + raise Exception("GatherRequestHeaders failed to find protocol in host address.") + + # Move past the :// + protocolEnd += 3 + + # Find the end, if not found, assume the end of the string. + hostEnd = absoluteUrl.find("/", protocolEnd+3) + if hostEnd == -1: + hostEnd = len(absoluteUrl) + + host = absoluteUrl[protocolEnd:hostEnd] + + # According to the spec, if the port is 80 or 443, it should be omitted. + # Otherwise, if there is a port, then it should be included. + if host.find(":") != -1: + knownPortIndex = host.find(":80") + if knownPortIndex == -1: + knownPortIndex = host.find(":443") + if knownPortIndex != -1: + host = host[:knownPortIndex] + return host + except Exception as e: + Sentry.Exception("GatherRequestHeaders failed to parse absolute path.", e) + + # Called only for websockets to get headers. @staticmethod def GatherWebsocketRequestHeaders(logger:logging.Logger, httpInitialContext) -> dict: @@ -173,7 +224,7 @@ def GetWebSocketSubProtocols(logger:logging.Logger, httpInitialContext) -> list: # # This function must return the location value string again, either corrected or not. @staticmethod - def CorrectLocationResponseHeaderIfNeeded(logger:logging.Logger, requestUri:str, locationValue:str, sendHeaders): + def CorrectLocationResponseHeaderIfNeeded(logger:logging.Logger, requestUri:str, locationValue:str, sendHeaders, httpInitialContext:HttpInitialContext): # The sendHeaders is an dict that was generated by GatherRequestHeaders and were used to send the request. # Make sure the location is http(s) or ws(s), since that's all we deal with right now. diff --git a/homeway/homeway/WebStream/webstreamhttphelper.py b/homeway/homeway/WebStream/webstreamhttphelper.py index 44102c1..d105efa 100644 --- a/homeway/homeway/WebStream/webstreamhttphelper.py +++ b/homeway/homeway/WebStream/webstreamhttphelper.py @@ -267,7 +267,8 @@ def executeHttpRequest(self): # The boundary stream is used for webcam streams, and it's an ideal place to package and send each frame boundaryStr = None # Pull out the content type value, so we can use it to figure out if we want to compress this data or not - contentTypeLower =None + contentTypeLower = None + ogLocationHeaderValue = None headers = hwHttpResult.Headers for name, value in headers.items(): nameLower = name.lower() @@ -292,7 +293,13 @@ def executeHttpRequest(self): elif nameLower == "location": # We have noticed that some proxy servers aren't setup correctly to forward the x-forwarded-for and such headers. # So when the web server responds back with a 301 or 302, the location header might not have the correct hostname, instead an ip like 127.0.0.1. - hwHttpResult.Headers[name] = HeaderHelper.CorrectLocationResponseHeaderIfNeeded(self.Logger, uri, value, sendHeaders) + ogLocationHeaderValue = value + hwHttpResult.Headers[name] = HeaderHelper.CorrectLocationResponseHeaderIfNeeded(self.Logger, uri, value, sendHeaders, httpInitialContext) + + if ogLocationHeaderValue is not None: + # Also set the og location, so the server has it if it needs it. + # This has to be set out of the loop. + hwHttpResult.Headers["x-og-location"] = ogLocationHeaderValue # We also look at the content-type to determine if we should add compression to this request or not. # general rule of thumb is that compression is quite cheap but really helps with text, so we should compress when we