def _update_peer_version(self, response): vser = None server_header = response.headers.get("server", None) if server_header is not None: server_name, server_ver = http.parse_user_agent(server_header) if (server_name != FEAT_IDENT or len(server_ver) != 1 or not isinstance(server_ver[0], int)): raise TunnelError("Unsupported server %r" % server_header) vser = server_ver[0] vin = self._tunnel._version vout = vser if vser is not None and vser < vin else vin self._peer_version = vser self._target_version = vout self._headers["user-agent"] = http.compose_user_agent(FEAT_IDENT, vout) return response
def parse_user_agent(self): agent = self.get_received_header("user-agent") if not agent: return "unknown", None return http.parse_user_agent(agent)
def onAllContentReceived(self): vout = self.channel.owner._version ctype = self.get_received_header("content-type") if ctype != "application/json": self._error(http.Status.UNSUPPORTED_MEDIA_TYPE, "Message content type not supported, " "only application/json is.") return agent_header = self.get_received_header("user-agent") if agent_header is None: self._error(http.Status.BAD_REQUEST, "No user agent specified.") return agent_name, agent_ver = http.parse_user_agent(agent_header) if ((agent_name != FEAT_IDENT) or len(agent_ver) != 1 or not isinstance(agent_ver[0], int)): self._error(http.Status.BAD_REQUEST, "User agent not supported.") return vcli = agent_ver[0] if self.method is http.Methods.HEAD: vin = vcli if vcli is not None and vcli < vout else vout server_header = http.compose_user_agent(FEAT_IDENT, vin) self.set_header("server", server_header) self.set_length(0) self.finish() return if self.method is http.Methods.POST: if vcli is not None and vcli > vout: # not safe, better fail self._error(http.Status.UNSUPPORTED_MEDIA_TYPE, "Message version not supported.") return host_header = self.get_received_header("host") if host_header is None: self._error(http.Status.BAD_REQUEST, "Message without host header.") return scheme = self.channel.owner._scheme host, port = http.parse_host(host_header, scheme) uri = http.compose(self.uri, host=host, port=port, scheme=scheme) vin = vcli if vcli is not None else vout unserializer = json.Unserializer(registry=self._registry, source_ver=vin, target_ver=vout) body = "".join(self._buffer) try: data = unserializer.convert(body) except Exception as e: msg = "Error while unserializing tunnel message" error.handle_exception(self, e, msg) self._error(http.Status.BAD_REQUEST, "Invalid message, unserialization failed.") return self.channel.owner._dispatch(uri, data) self.set_response_code(http.Status.OK) server_header = http.compose_user_agent(FEAT_IDENT, vin) self.set_header("server", server_header) self.set_length(0) self.finish() return self.set_response_code(http.Status.NOT_ALLOWED) self.set_header("content-type", "plain/text") self.write("Method not allowed, only POST and HEAD.") self.finish()