def response(self, response): log_debug(3) # pkilambi:if redirectException caught returns path(<str>) if isinstance(response, str): method, params = self._get_method_params() if method == "getPackage": return self.redirect(self.req, response) # GET requests resulting in a Fault receive special treatment # since we have to stick the error message in the HTTP header, # and to return an Apache error code if isinstance(response, xmlrpclib.Fault): log_debug(4, "Return FAULT", response.faultCode, response.faultString) retcode = apache.HTTP_NOT_FOUND if abs(response.faultCode) in (33, 34, 35, 37, 39, 41): retcode = apache.HTTP_UNAUTHORIZED self.req.headers_out["X-RHN-Fault-Code"] = str(response.faultCode) faultString = string.strip(base64.encodestring(response.faultString)) # Split the faultString into multiple lines for line in string.split(faultString, "\n"): self.req.headers_out.add("X-RHN-Fault-String", string.strip(line)) # And then send all the other things for k, v in rhnFlags.get("outputTransportOptions").items(): setHeaderValue(self.req.headers_out, k, v) return retcode # Otherwise we're pretty much fine with the standard response # handler # Copy the fields from the transport options, if necessary for k, v in rhnFlags.get("outputTransportOptions").items(): setHeaderValue(self.req.headers_out, k, v) # and jump into the base handler return apacheRequest.response(self, response)
def _handleServerResponse(self, status): """ This method can be overridden by subclasses who want to handle server responses in their own way. By default, we will wrap all the headers up and send them back to the client with an error status. This method should return apache.OK if everything went according to plan. """ if (status != apache.HTTP_OK) and (status != apache.HTTP_PARTIAL_CONTENT): # Non 200 response; have to treat it differently log_debug(2, "Forwarding status %s" % status) # Copy the incoming headers to err_headers_out headers = self.responseContext.getHeaders() if headers is not None: for k in headers.keys(): rhnLib.setHeaderValue(self.req.err_headers_out, k, self._get_header(k)) else: log_error('WARNING? - no incoming headers found!') # And that's that return status if (status == apache.HTTP_PARTIAL_CONTENT): return apache.HTTP_PARTIAL_CONTENT else: # apache.HTTP_OK becomes apache.OK. return apache.OK
def _response_fault_get(req, response): req.err_headers_out["X-RHN-Fault-Code"] = str(response.faultCode) faultString = base64.encodestring(response.faultString).strip() # Split the faultString into multiple lines for line in faultString.split('\n'): req.err_headers_out.add("X-RHN-Fault-String", line.strip()) # And then send all the other things for k, v in rhnFlags.get('outputTransportOptions').items(): setHeaderValue(req.err_headers_out, k, v) return apache.HTTP_NOT_FOUND
def _response_fault_get(req, response): req.headers_out["X-RHN-Fault-Code"] = str(response.faultCode) faultString = base64.encodestring(response.faultString).strip() # Split the faultString into multiple lines for line in faultString.split('\n'): req.headers_out.add("X-RHN-Fault-String", line.strip()) # And then send all the other things for k, v in rhnFlags.get('outputTransportOptions').items(): setHeaderValue(req.headers_out, k, v) return apache.HTTP_NOT_FOUND
def response(self, response): log_debug(3) # pkilambi:if redirectException caught returns path(<str>) if isinstance(response, str): method, params = self._get_method_params() if method == "getPackage": return self.redirect(self.req, response) # GET requests resulting in a Fault receive special treatment # since we have to stick the error message in the HTTP header, # and to return an Apache error code if isinstance(response, xmlrpclib.Fault): log_debug(4, "Return FAULT", response.faultCode, response.faultString) retcode = apache.HTTP_NOT_FOUND if abs(response.faultCode) in (33, 34, 35, 37, 39, 41): retcode = apache.HTTP_UNAUTHORIZED self.req.headers_out["X-RHN-Fault-Code"] = \ str(response.faultCode) faultString = string.strip(base64.encodestring( response.faultString)) # Split the faultString into multiple lines for line in string.split(faultString, '\n'): self.req.headers_out.add("X-RHN-Fault-String", string.strip(line)) # And then send all the other things for k, v in rhnFlags.get('outputTransportOptions').items(): setHeaderValue(self.req.headers_out, k, v) return retcode # Otherwise we're pretty much fine with the standard response # handler # Copy the fields from the transport options, if necessary for k, v in rhnFlags.get('outputTransportOptions').items(): setHeaderValue(self.req.headers_out, k, v) # and jump into the base handler return apacheRequest.response(self, response)
def _forwardHTTPHeaders(self, fromResponse, toRequest): """ This routine will transfer the header contents of an HTTP response to the output headers of an HTTP request for reply to the original requesting client. This function does NOT call the request's send_http_header routine; that is the responsibility of the caller. """ if fromResponse is None or toRequest is None: return # Iterate over each header in the response and place it in the request # output area. for k in fromResponse.msg.keys(): # Get the value v = self._get_header(k, fromResponse.msg) # Set the field in the response rhnLib.setHeaderValue(toRequest.headers_out, k, v)
def _forwardHTTPHeaders(self, fromResponse, toRequest): """ This routine will transfer the header contents of an HTTP response to the output headers of an HTTP request for reply to the original requesting client. This function does NOT call the request's send_http_header routine; that is the responsibility of the caller. """ if fromResponse is None or toRequest is None: return # Iterate over each header in the response and place it in the request # output area. for k in fromResponse.msg.keys(): # Get the value v = self._get_header(k, fromResponse.msg) if (k == 'transfer-encoding') and ('chunked' in v): log_debug(5, "Filtering header", k, v) continue # Set the field in the response rhnLib.setHeaderValue(toRequest.headers_out, k, v)
return apache.HTTP_INTERNAL_SERVER_ERROR except: # Uncaught exception; signal the error Traceback("apacheHandler.response", self.req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR # we're about done here, patch up the headers output.process(response) # Copy the rest of the fields for k, v in output.headers.items(): if string.lower(k) == 'content-type': # Content-type self.req.content_type = v else: setHeaderValue(self.req.headers_out, k, v) if 5 <= CFG.DEBUG < 10: log_debug(5, "The response: %s[...SNIP (for sanity) SNIP...]%s" % (response[:100], response[-100:])) elif CFG.DEBUG >= 10: # if you absolutely must have that whole response in the log file log_debug(10, "The response: %s" % response) # send the headers self.req.send_http_header() try: # XXX: in case data is really large maybe we should split # it in smaller chunks instead of blasting everything at # once. Not yet a problem... self.req.write(output.data) except IOError:
severity="notification") return apache.HTTP_INTERNAL_SERVER_ERROR except Exception: # pylint: disable=E0012, W0703 # Uncaught exception; signal the error Traceback("apacheHandler.response", req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR # we're about done here, patch up the headers output.process(response) # Copy the rest of the fields for k, v in output.headers.items(): if k.lower() == 'content-type': # Content-type req.content_type = v else: setHeaderValue(req.headers_out, k, v) if CFG.DEBUG == 4: # I wrap this in an "if" so we don't parse a large file for no reason. log_debug( 4, "The response: %s[...SNIP (for sanity) SNIP...]%s" % (response[:100], response[-100:])) elif CFG.DEBUG >= 5: # if you absolutely must have that whole response in the log file log_debug(5, "The response: %s" % response) # send the headers req.send_http_header() try: # XXX: in case data is really large maybe we should split # it in smaller chunks instead of blasting everything at
def response(self, response): # Send the xml-rpc response back log_debug(3, type(response)) needs_xmlrpc_encoding = not rhnFlags.test("XMLRPC-Encoded-Response") compress_response = rhnFlags.test("compress_response") # Init an output object; we'll use it for sending data in various # formats if isinstance(response, transports.File): if not hasattr(response.file_obj, 'fileno') and compress_response: # This is a StringIO that has to be compressed, so read it in # memory; mark that we don't have to do any xmlrpc encoding response = response.file_obj.read() needs_xmlrpc_encoding = 0 else: # Just treat is as a file return self.response_file(response) output = transports.Output() # First, use the same encoding/transfer that the client used output.set_transport_flags( transfer=transports.lookupTransfer(self.input.transfer), encoding=transports.lookupEncoding(self.input.encoding)) if isinstance(response, xmlrpclib.Fault): log_debug(4, "Return FAULT", response.faultCode, response.faultString) # No compression for faults because we'd like them to pop # up in clear text on the other side just in case output.set_transport_flags(output.TRANSFER_NONE, output.ENCODE_NONE) elif compress_response: # check if we have to compress this result log_debug(4, "Compression on for client version", self.client) if self.client > 0: output.set_transport_flags(output.TRANSFER_BINARY, output.ENCODE_ZLIB) else: # original clients had the binary transport support broken output.set_transport_flags(output.TRANSFER_BASE64, output.ENCODE_ZLIB) # We simply add the transport options to the output headers output.headers.update(rhnFlags.get('outputTransportOptions').dict()) if needs_xmlrpc_encoding: # Normalize the response response = self.normalize(response) try: response = xmlrpclib.dumps(response, methodresponse=1) except TypeError: e = sys.exc_info()[1] log_debug(4, "Error \"%s\" encoding response = %s" % (e, response)) Traceback("apacheHandler.response", self.req, extra="Error \"%s\" encoding response = %s" % (e, response), severity="notification") return apache.HTTP_INTERNAL_SERVER_ERROR except: # Uncaught exception; signal the error Traceback("apacheHandler.response", self.req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR # we're about done here, patch up the headers output.process(response) # Copy the rest of the fields for k, v in output.headers.items(): if string.lower(k) == 'content-type': # Content-type self.req.content_type = v else: setHeaderValue(self.req.headers_out, k, v) if 5 <= CFG.DEBUG < 10: log_debug(5, "The response: %s[...SNIP (for sanity) SNIP...]%s" % (response[:100], response[-100:])) elif CFG.DEBUG >= 10: # if you absolutely must have that whole response in the log file log_debug(10, "The response: %s" % response) # send the headers self.req.send_http_header() try: # XXX: in case data is really large maybe we should split # it in smaller chunks instead of blasting everything at # once. Not yet a problem... self.req.write(output.data) except IOError: # send_http_header is already sent, so it doesn't make a lot of # sense to return a non-200 error; but there is no better solution return apache.HTTP_BAD_REQUEST del output return apache.OK
def _handleServerResponse(self, status): """ Here, we'll override the default behavior for handling server responses so that we can adequately handle 302's. We will follow redirects unless it is redirect to (re)login page. In which case we change protocol to https and return redirect to user. """ # In case of a 302, redirect the original request to the location # specified in the response. if status == apache.HTTP_MOVED_TEMPORARILY or \ status == apache.HTTP_MOVED_PERMANENTLY: log_debug(1, "Received redirect response: ", status) # if we redirected to ssl version of login page, send redirect directly to user headers = self.responseContext.getHeaders() if headers is not None: for headerKey in headers.keys(): if headerKey == 'location': location = self._get_header(headerKey) relogin = re.compile( r'https?://.*(/rhn/(Re)?Login.do\?.*)') m = relogin.match(location[0]) if m: # pull server name out of "t:o:k:e:n:hostname1,t:o:k:e:n:hostname2,..." proxy_auth = self.req.headers_in[ 'X-RHN-Proxy-Auth'] last_auth = proxy_auth.split(',')[-1] server_name = last_auth.split(':')[-1] log_debug( 1, "Redirecting to SSL version of login page") rhnLib.setHeaderValue( self.req.headers_out, 'Location', "https://%s%s" % (server_name, m.group(1))) return apache.HTTP_MOVED_PERMANENTLY redirectStatus = self.__redirectToNextLocation() # At this point, we've either: # # (a) successfully redirected to the 3rd party # (b) been told to redirect somewhere else from the 3rd party # (c) run out of retry attempts # # We'll keep redirecting until we've received HTTP_OK or an error. while redirectStatus == apache.HTTP_MOVED_PERMANENTLY or \ redirectStatus == apache.HTTP_MOVED_TEMPORARILY: # We've been told to redirect again. We'll pass a special # argument to ensure that if we end up back at the server, we # won't be redirected again. log_debug(1, "Redirected again! Code=", redirectStatus) redirectStatus = self.__redirectToNextLocation(True) if (redirectStatus != apache.HTTP_OK) and ( redirectStatus != apache.HTTP_PARTIAL_CONTENT): # We must have run out of retry attempts. Fail over to Hosted # to perform the request. log_debug(1, "Redirection failed; retries exhausted. " \ "Failing over. Code=", \ redirectStatus) redirectStatus = self.__redirectFailover() return SharedHandler._handleServerResponse(self, redirectStatus) else: # Otherwise, revert to default behavior. return SharedHandler._handleServerResponse(self, status)
return apache.HTTP_INTERNAL_SERVER_ERROR except Exception: # pylint: disable=E0012, W0703 # Uncaught exception; signal the error Traceback("apacheHandler.response", req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR # we're about done here, patch up the headers output.process(response) # Copy the rest of the fields for k, v in output.headers.items(): if k.lower() == 'content-type': # Content-type req.content_type = v else: setHeaderValue(req.headers_out, k, v) if CFG.DEBUG == 4: # I wrap this in an "if" so we don't parse a large file for no reason. log_debug(4, "The response: %s[...SNIP (for sanity) SNIP...]%s" % (response[:100], response[-100:])) elif CFG.DEBUG >= 5: # if you absolutely must have that whole response in the log file log_debug(5, "The response: %s" % response) # send the headers req.send_http_header() try: # XXX: in case data is really large maybe we should split # it in smaller chunks instead of blasting everything at # once. Not yet a problem...
except: # Uncaught exception; signal the error Traceback("apacheHandler.response", self.req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR # we're about done here, patch up the headers output.process(response) # Copy the rest of the fields for k, v in output.headers.items(): if string.lower(k) == 'content-type': # Content-type self.req.content_type = v else: setHeaderValue(self.req.headers_out, k, v) if 5 <= CFG.DEBUG < 10: log_debug( 5, "The response: %s[...SNIP (for sanity) SNIP...]%s" % (response[:100], response[-100:])) elif CFG.DEBUG >= 10: # if you absolutely must have that whole response in the log file log_debug(10, "The response: %s" % response) # send the headers self.req.send_http_header() try: # XXX: in case data is really large maybe we should split # it in smaller chunks instead of blasting everything at # once. Not yet a problem...
def response(self, req, response): """ send the response (common code) """ # Send the xml-rpc response back log_debug(5, "Response type", type(response)) needs_xmlrpc_encoding = rhnFlags.test("NeedEncoding") compress_response = rhnFlags.test("compress_response") # Init an output object; we'll use it for sending data in various # formats if isinstance(response, rpclib.transports.File): if not hasattr(response.file_obj, 'fileno') and compress_response: # This is a StringIO that has to be compressed, so read it in # memory; mark that we don't have to do any xmlrpc encoding response = response.file_obj.read() needs_xmlrpc_encoding = 0 else: # Just treat is as a file return self.response_file(req, response) is_fault = 0 if isinstance(response, rhnFault): if req.method == 'GET': return self._response_fault_get(req, response.getxml()) # Need to encode the response as xmlrpc response = response.getxml() is_fault = 1 # No compression compress_response = 0 # This is an xmlrpc Fault, so we have to encode it needs_xmlrpc_encoding = 1 output = rpclib.transports.Output() if not is_fault: # First, use the same encoding/transfer that the client used output.set_transport_flags( transfer=rpclib.transports.lookupTransfer(self.input.transfer), encoding=rpclib.transports.lookupEncoding(self.input.encoding)) if compress_response: # check if we have to compress this result log_debug(4, "Compression on for client version", self.clientVersion) if self.clientVersion > 0: output.set_transport_flags(output.TRANSFER_BINARY, output.ENCODE_ZLIB) else: # original clients had the binary transport support broken output.set_transport_flags(output.TRANSFER_BASE64, output.ENCODE_ZLIB) # We simply add the transport options to the output headers output.headers.update(rhnFlags.get('outputTransportOptions').dict()) if needs_xmlrpc_encoding: # Normalize the response response = self.normalize(response) try: response = rpclib.xmlrpclib.dumps(response, methodresponse=1) except TypeError as e: log_debug(-1, "Error \"%s\" encoding response = %s" % (e, response)) Traceback("apacheHandler.response", req, extra="Error \"%s\" encoding response = %s" % (e, response), severity="notification") return apache.HTTP_INTERNAL_SERVER_ERROR except Exception: # pylint: disable=E0012, W0703 # Uncaught exception; signal the error Traceback("apacheHandler.response", req, severity="unhandled") return apache.HTTP_INTERNAL_SERVER_ERROR # we're about done here, patch up the headers output.process(response) # Copy the rest of the fields for k, v in list(output.headers.items()): if k.lower() == 'content-type': # Content-type req.content_type = v else: setHeaderValue(req.headers_out, k, v) if CFG.DEBUG == 4: # I wrap this in an "if" so we don't parse a large file for no reason. log_debug(4, "The response: %s[...SNIP (for sanity) SNIP...]%s" % (response[:100], response[-100:])) elif CFG.DEBUG >= 5: # if you absolutely must have that whole response in the log file log_debug(5, "The response: %s" % response) # send the headers req.send_http_header() try: # XXX: in case data is really large maybe we should split # it in smaller chunks instead of blasting everything at # once. Not yet a problem... req.write(output.data) except IOError: # send_http_header is already sent, so it doesn't make a lot of # sense to return a non-200 error; but there is no better solution return apache.HTTP_BAD_REQUEST del output return apache.OK
def _handleServerResponse(self, status): """ Here, we'll override the default behavior for handling server responses so that we can adequately handle 302's. We will follow redirects unless it is redirect to (re)login page. In which case we change protocol to https and return redirect to user. """ # In case of a 302, redirect the original request to the location # specified in the response. if status == apache.HTTP_MOVED_TEMPORARILY or \ status == apache.HTTP_MOVED_PERMANENTLY: log_debug(1, "Received redirect response: ", status) # if we redirected to ssl version of login page, send redirect directly to user headers = self.responseContext.getHeaders() if headers is not None: for headerKey in headers.keys(): if headerKey == 'location': location = self._get_header(headerKey) relogin = re.compile(r'https?://.*(/rhn/(Re)?Login.do\?.*)') m = relogin.match(location[0]) if m: # pull server name out of "t:o:k:e:n:hostname1,t:o:k:e:n:hostname2,..." proxy_auth = self.req.headers_in['X-RHN-Proxy-Auth'] last_auth = proxy_auth.split(',')[-1] server_name = last_auth.split(':')[-1] log_debug(1, "Redirecting to SSL version of login page") rhnLib.setHeaderValue(self.req.headers_out, 'Location', "https://%s%s" % (server_name, m.group(1))) return apache.HTTP_MOVED_PERMANENTLY redirectStatus = self.__redirectToNextLocation() # At this point, we've either: # # (a) successfully redirected to the 3rd party # (b) been told to redirect somewhere else from the 3rd party # (c) run out of retry attempts # # We'll keep redirecting until we've received HTTP_OK or an error. while redirectStatus == apache.HTTP_MOVED_PERMANENTLY or \ redirectStatus == apache.HTTP_MOVED_TEMPORARILY: # We've been told to redirect again. We'll pass a special # argument to ensure that if we end up back at the server, we # won't be redirected again. log_debug(1, "Redirected again! Code=", redirectStatus) redirectStatus = self.__redirectToNextLocation(True) if (redirectStatus != apache.HTTP_OK) and (redirectStatus != apache.HTTP_PARTIAL_CONTENT): # We must have run out of retry attempts. Fail over to Hosted # to perform the request. log_debug(1, "Redirection failed; retries exhausted. " "Failing over. Code=", redirectStatus) redirectStatus = self.__redirectFailover() return SharedHandler._handleServerResponse(self, redirectStatus) else: # Otherwise, revert to default behavior. return SharedHandler._handleServerResponse(self, status)