Example #1
0
	def __init__(self, host, port):
		self.host = host
		self.port = port

		self.notify_received_event = Event(self)
		self.connected_event = Event(self)
		self.disconnected_event = Event(self)
		self.active = False

		self.connector = None
		self.timeout_connect = 5
Example #2
0
	def __init__(self, parent):
		self.reset()
		self.head_limit = 8192
		self.content_limit = 50 * 1024 * 1024
		self.package = HttpPackage()

		self.response_dict = {
			200: "OK",
			400: "Bad Request",
			401: "Unauthorized",
			403: "Forbidden",
			404: "Not Found"
		}

		self.package_received_event = Event(parent)
		self.error_report_event = Event(parent)
Example #3
0
    def __init__(self, parent):
        self.reset()
        self.head_limit = 8192
        self.content_limit = 50 * 1024 * 1024
        self.package = HttpPackage()

        self.response_dict = {
            200: "OK",
            400: "Bad Request",
            401: "Unauthorized",
            403: "Forbidden",
            404: "Not Found"
        }

        self.package_received_event = Event(parent)
        self.error_report_event = Event(parent)
Example #4
0
class HttpHandler(object):
	def __init__(self, parent):
		self.reset()
		self.head_limit = 8192
		self.content_limit = 50 * 1024 * 1024
		self.package = HttpPackage()

		self.response_dict = {
			200: "OK",
			400: "Bad Request",
			401: "Unauthorized",
			403: "Forbidden",
			404: "Not Found"
		}

		self.package_received_event = Event(parent)
		self.error_report_event = Event(parent)

	def reset(self):
		self.buf = ""
		self.content_length = 0
		self.content_recv_size = 0
		self.content_l = []		# 接收content的缓存
		self.is_chunked = False
		self.chunksize = -1
		self.chunkdata_l = []

	def handle_data(self, s):
		self.buf = "".join([self.buf, s])

		p = 0
		while True:
			if self.is_chunked:
				p = self.handle_chunked()
				if p == -1:
					break

			if not self.content_length:
				p = self.handle_head()
				if p == -1:
					break

			if self.content_length:
				p = self.handle_content()
				if p == -1:
					break

	def handle_head(self):
#		print "- handle_head()"
		p = self.buf.find("\r\n\r\n")
		if p != -1:
#			print "headlen:", p + 4
			head_s = self.buf[:p]
			self.buf = self.buf[p + 4:]

			if len(head_s) > self.head_limit:
				self.error_report_event.dispatch("HTTP_HEAD_TOO_LONG (%d/%d)" %
					(len(head_s), self.head_limit))

			self.package = self.parse_http_head(head_s)
			self.is_chunked = self.package.head.get("Transfer-Encoding", "") == "chunked"
			if not self.is_chunked:
				# 处理常规(含有Content-Length的)包
				try:
					self.content_length = int(self.package.head.get("Content-Length", 0))
				except:
					self.content_length = 0
#				print "content-length:", self.content_length
				if not self.content_length:
					self.package_received_event.dispatch(self.package)
					self.package = HttpPackage()
				else:
					if self.content_length > self.content_limit:
						self.error_report_event.dispatch("HTTP_CONTENT_TOO_LONG (%d/%d)" %
							(self.content_length, self.content_limit))
		else:
			if len(self.buf) > self.head_limit:
				self.error_report_event.dispatch("HTTP_HEAD_TOO_LONG (%d/%d)" %
					(len(self.buf), self.head_limit))

		return p

	def handle_content(self):
#		print "- handle_content()"
		p = -1
		# 为避免大数据拷贝,使用一个数组作为缓存存放每次收到的数据。
		if self.buf:
			self.content_recv_size += len(self.buf)
			self.content_l.append(self.buf)
			self.buf = ""
		if self.content_recv_size >= self.content_length:
			# HTTP内容已收全
			p = 0
			# 从缓存中还原数据
			self.buf = "".join(self.content_l)
			self.content_l = []
			self.content_recv_size = 0

			self.package.content = self.buf[:self.content_length]
			self.buf = self.buf[self.content_length:]
			self.content_length = 0
#			print "package ready, reset of buf:", len(self.buf)
			self.package_received_event.dispatch(self.package)
			self.package = HttpPackage()
		return p

	def handle_chunked(self):
		p = 0
		while p != -1:
			if self.chunksize == -1:
				p = self.handle_chunked_size()
			else:
				p = self.handle_chunked_content()
		return p

	def handle_chunked_size(self):
		p = self.buf.find("\r\n")
		if p != -1:
			try:
				self.chunksize = int(self.buf[:p], 16)
			except:
				self.chunksize = -1
				p = -1	# 错误的chunksize,终止chunk接收。
			print "chunked size:", self.chunksize
			if self.chunksize >= 0:
				self.buf = self.buf[p + 2:]
		return p

	def handle_chunked_content(self):
		p = -1
		if len(self.buf) >= self.chunksize + 2:
			p = 0
			# CHUNK内容已收全
			self.chunkdata_l.append(self.buf[:self.chunksize])
			self.buf = self.buf[self.chunksize + 2:]
			if self.chunksize == 0:
				# HTTP内容已收全
				self.package.content = "".join(self.chunkdata_l)
				print
				self.chunkdata_l = []
				self.package_received_event.dispatch(self.package)
				self.package = HttpPackage()
				p = self.buf.find("\r\n\r\n")
			self.chunksize = -1
		return p

	def parse_http_head(self, head_s):
		package = HttpPackage()
		request_line = ""
		lines = head_s.split("\r\n")
		for i, line in enumerate(lines):
			if i == 0:
				request_line = line
			else:
				p = line.find(":")
				if p != -1:
					name = line[:p]
					value = line[p + 1:].strip()
					package.head[name] = value

		if request_line:
			# 检查是否请求头
			m = re.search("(GET|POST|SUBSCRIBE|NOTIFY) +?([^ ]+)", request_line, re.I | re.M)
			if m:
				package.method, path = m.groups()
				if "?" in path:
					# aaa?xxx=yyy
					axy = path.split("?")[:2]
					package.path, package.param_raw = axy
					# aaa?xxx=yyy&mmm=nnn
					xy = package.param_raw
					xymn = xy.split("&")
					for entry in xymn:
						if "=" in entry:
							name, value = entry.split("=")[:2]
							package.param[name] = value
				else:
					package.path = path
			else:
				# 检查是否应答头
				m = re.search("HTTP/(\\d+\\.\\d+)\\s+(\\d+)\\s+?(\\w+)?", request_line, re.I | re.M)
				if m:
					package.response_version, package.response_code, package.response_msg = m.groups()
		return package

	def make_request(self, method, path, param=[], heads=[], content=""):
		request = ""
		if param:
			request = "?"
			for name, value in param:
				request = "".join([request, name, "=", value, "&"])
			else:
				request = request[:-1]

		package_s = "%s %s%s HTTP/1.1\r\n" % (method, path, request)

		head_lines = []
		content_type = ""
		for name, value in heads:
			head_lines.append("".join([name, ": ", value]))
			if name.lower() == "content-type":
				content_type = value
		if not content_type:
			head_lines.append("Content-Type: text/plain")
		head_lines.append("Content-Length: %d\r\n\r\n" % len(content))

		package_s += "\r\n".join(head_lines)
		if content:
			package_s += content

		return package_s

	def make_response(self, response_code, heads=[], content=""):
		response_msg = self.response_dict.get(response_code, "Unknown")
		package_s = "HTTP/1.1 %d %s\r\n" % (response_code, response_msg)

		head_lines = []
		content_type = ""
		for name, value in heads:
			head_lines.append("".join([name, ": ", value]))
			if name.lower() == "content-type":
				content_type = value
		if not content_type:
			head_lines.append("Content-Type: text/plain")
		head_lines.append("Content-Length: %d\r\n\r\n" % len(content))

		package_s += "\r\n".join(head_lines)
		if content:
			package_s += content

		return package_s
Example #5
0
class HttpHandler(object):
    def __init__(self, parent):
        self.reset()
        self.head_limit = 8192
        self.content_limit = 50 * 1024 * 1024
        self.package = HttpPackage()

        self.response_dict = {
            200: "OK",
            400: "Bad Request",
            401: "Unauthorized",
            403: "Forbidden",
            404: "Not Found"
        }

        self.package_received_event = Event(parent)
        self.error_report_event = Event(parent)

    def reset(self):
        self.buf = ""
        self.content_length = 0
        self.content_recv_size = 0
        self.content_l = []  # 接收content的缓存
        self.is_chunked = False
        self.chunksize = -1
        self.chunkdata_l = []

    def handle_data(self, s):
        self.buf = "".join([self.buf, s])

        p = 0
        while True:
            if self.is_chunked:
                p = self.handle_chunked()
                if p == -1:
                    break

            if not self.content_length:
                p = self.handle_head()
                if p == -1:
                    break

            if self.content_length:
                p = self.handle_content()
                if p == -1:
                    break

    def handle_head(self):
        #		print "- handle_head()"
        p = self.buf.find("\r\n\r\n")
        if p != -1:
            #			print "headlen:", p + 4
            head_s = self.buf[:p]
            self.buf = self.buf[p + 4:]

            if len(head_s) > self.head_limit:
                self.error_report_event.dispatch(
                    "HTTP_HEAD_TOO_LONG (%d/%d)" %
                    (len(head_s), self.head_limit))

            self.package = self.parse_http_head(head_s)
            self.is_chunked = self.package.head.get("Transfer-Encoding",
                                                    "") == "chunked"
            if not self.is_chunked:
                # 处理常规(含有Content-Length的)包
                try:
                    self.content_length = int(
                        self.package.head.get("Content-Length", 0))
                except:
                    self.content_length = 0
#				print "content-length:", self.content_length
                if not self.content_length:
                    self.package_received_event.dispatch(self.package)
                    self.package = HttpPackage()
                else:
                    if self.content_length > self.content_limit:
                        self.error_report_event.dispatch(
                            "HTTP_CONTENT_TOO_LONG (%d/%d)" %
                            (self.content_length, self.content_limit))
        else:
            if len(self.buf) > self.head_limit:
                self.error_report_event.dispatch(
                    "HTTP_HEAD_TOO_LONG (%d/%d)" %
                    (len(self.buf), self.head_limit))

        return p

    def handle_content(self):
        #		print "- handle_content()"
        p = -1
        # 为避免大数据拷贝,使用一个数组作为缓存存放每次收到的数据。
        if self.buf:
            self.content_recv_size += len(self.buf)
            self.content_l.append(self.buf)
            self.buf = ""
        if self.content_recv_size >= self.content_length:
            # HTTP内容已收全
            p = 0
            # 从缓存中还原数据
            self.buf = "".join(self.content_l)
            self.content_l = []
            self.content_recv_size = 0

            self.package.content = self.buf[:self.content_length]
            self.buf = self.buf[self.content_length:]
            self.content_length = 0
            #			print "package ready, reset of buf:", len(self.buf)
            self.package_received_event.dispatch(self.package)
            self.package = HttpPackage()
        return p

    def handle_chunked(self):
        p = 0
        while p != -1:
            if self.chunksize == -1:
                p = self.handle_chunked_size()
            else:
                p = self.handle_chunked_content()
        return p

    def handle_chunked_size(self):
        p = self.buf.find("\r\n")
        if p != -1:
            try:
                self.chunksize = int(self.buf[:p], 16)
            except:
                self.chunksize = -1
                p = -1  # 错误的chunksize,终止chunk接收。
            print "chunked size:", self.chunksize
            if self.chunksize >= 0:
                self.buf = self.buf[p + 2:]
        return p

    def handle_chunked_content(self):
        p = -1
        if len(self.buf) >= self.chunksize + 2:
            p = 0
            # CHUNK内容已收全
            self.chunkdata_l.append(self.buf[:self.chunksize])
            self.buf = self.buf[self.chunksize + 2:]
            if self.chunksize == 0:
                # HTTP内容已收全
                self.package.content = "".join(self.chunkdata_l)
                print
                self.chunkdata_l = []
                self.package_received_event.dispatch(self.package)
                self.package = HttpPackage()
                p = self.buf.find("\r\n\r\n")
            self.chunksize = -1
        return p

    def parse_http_head(self, head_s):
        package = HttpPackage()
        request_line = ""
        lines = head_s.split("\r\n")
        for i, line in enumerate(lines):
            if i == 0:
                request_line = line
            else:
                p = line.find(":")
                if p != -1:
                    name = line[:p]
                    value = line[p + 1:].strip()
                    package.head[name] = value

        if request_line:
            # 检查是否请求头
            m = re.search("(GET|POST|SUBSCRIBE|NOTIFY) +?([^ ]+)",
                          request_line, re.I | re.M)
            if m:
                package.method, path = m.groups()
                if "?" in path:
                    # aaa?xxx=yyy
                    axy = path.split("?")[:2]
                    package.path, package.param_raw = axy
                    # aaa?xxx=yyy&mmm=nnn
                    xy = package.param_raw
                    xymn = xy.split("&")
                    for entry in xymn:
                        if "=" in entry:
                            name, value = entry.split("=")[:2]
                            package.param[name] = value
                else:
                    package.path = path
            else:
                # 检查是否应答头
                m = re.search("HTTP/(\\d+\\.\\d+)\\s+(\\d+)\\s+?(\\w+)?",
                              request_line, re.I | re.M)
                if m:
                    package.response_version, package.response_code, package.response_msg = m.groups(
                    )
        return package

    def make_request(self, method, path, param=[], heads=[], content=""):
        request = ""
        if param:
            request = "?"
            for name, value in param:
                request = "".join([request, name, "=", value, "&"])
            else:
                request = request[:-1]

        package_s = "%s %s%s HTTP/1.1\r\n" % (method, path, request)

        head_lines = []
        content_type = ""
        for name, value in heads:
            head_lines.append("".join([name, ": ", value]))
            if name.lower() == "content-type":
                content_type = value
        if not content_type:
            head_lines.append("Content-Type: text/plain")
        head_lines.append("Content-Length: %d\r\n\r\n" % len(content))

        package_s += "\r\n".join(head_lines)
        if content:
            package_s += content

        return package_s

    def make_response(self, response_code, heads=[], content=""):
        response_msg = self.response_dict.get(response_code, "Unknown")
        package_s = "HTTP/1.1 %d %s\r\n" % (response_code, response_msg)

        head_lines = []
        content_type = ""
        for name, value in heads:
            head_lines.append("".join([name, ": ", value]))
            if name.lower() == "content-type":
                content_type = value
        if not content_type:
            head_lines.append("Content-Type: text/plain")
        head_lines.append("Content-Length: %d\r\n\r\n" % len(content))

        package_s += "\r\n".join(head_lines)
        if content:
            package_s += content

        return package_s