Exemplo n.º 1
0
def _test_url(data):
    import requests

    from octoprint import util as util

    class StatusCodeRange(object):
        def __init__(self, start=None, end=None):
            self.start = start
            self.end = end

        def __contains__(self, item):
            if not isinstance(item, int):
                return False
            if self.start and self.end:
                return self.start <= item < self.end
            elif self.start:
                return self.start <= item
            elif self.end:
                return item < self.end
            else:
                return False

        def as_dict(self):
            return {"start": self.start, "end": self.end}

    status_ranges = {
        "informational": StatusCodeRange(start=100, end=200),
        "success": StatusCodeRange(start=200, end=300),
        "redirection": StatusCodeRange(start=300, end=400),
        "client_error": StatusCodeRange(start=400, end=500),
        "server_error": StatusCodeRange(start=500, end=600),
        "normal": StatusCodeRange(end=400),
        "error": StatusCodeRange(start=400, end=600),
        "any": StatusCodeRange(start=100),
        "timeout": StatusCodeRange(start=0, end=1),
    }

    url = data["url"]
    method = data.get("method", "HEAD")
    timeout = 3.0
    valid_ssl = True
    check_status = [status_ranges["normal"]]
    content_type_whitelist = None
    content_type_blacklist = None

    if "timeout" in data:
        try:
            timeout = float(data["timeout"])
        except Exception:
            return make_response(
                "{!r} is not a valid value for timeout (must be int or float)".
                format(data["timeout"]),
                400,
            )

    if "validSsl" in data:
        valid_ssl = data["validSsl"] in valid_boolean_trues

    if "status" in data:
        request_status = data["status"]
        if not isinstance(request_status, list):
            request_status = [request_status]

        check_status = []
        for rs in request_status:
            if isinstance(rs, int):
                check_status.append([rs])
            else:
                if rs in status_ranges:
                    check_status.append(status_ranges[rs])
                else:
                    code = requests.codes[rs]
                    if code is not None:
                        check_status.append([code])

    if "content_type_whitelist" in data:
        if not isinstance(data["content_type_whitelist"], (list, tuple)):
            return make_response(
                "content_type_whitelist must be a list of mime types")
        content_type_whitelist = list(
            map(util.parse_mime_type, data["content_type_whitelist"]))
    if "content_type_blacklist" in data:
        if not isinstance(data["content_type_whitelist"], (list, tuple)):
            return make_response(
                "content_type_blacklist must be a list of mime types")
        content_type_blacklist = list(
            map(util.parse_mime_type, data["content_type_blacklist"]))

    response_result = None
    outcome = True
    status = 0
    try:
        with requests.request(method=method,
                              url=url,
                              timeout=timeout,
                              verify=valid_ssl,
                              stream=True) as response:
            status = response.status_code
            outcome = outcome and any(map(lambda x: status in x, check_status))
            content_type = response.headers.get("content-type")

            response_result = {
                "headers": dict(response.headers),
                "content_type": content_type,
            }

            if not content_type and data.get(
                    "content_type_guess") in valid_boolean_trues:
                content = response.content
                content_type = util.guess_mime_type(bytearray(content))

            if not content_type:
                content_type = "application/octet-stream"

            response_result = {"assumed_content_type": content_type}

            parsed_content_type = util.parse_mime_type(content_type)

            in_whitelist = content_type_whitelist is None or any(
                map(
                    lambda x: util.mime_type_matches(parsed_content_type, x),
                    content_type_whitelist,
                ))
            in_blacklist = content_type_blacklist is not None and any(
                map(
                    lambda x: util.mime_type_matches(parsed_content_type, x),
                    content_type_blacklist,
                ))

            if not in_whitelist or in_blacklist:
                # we don't support this content type
                response.close()
                outcome = False

            elif "response" in data and (
                    data["response"] in valid_boolean_trues
                    or data["response"] in ("json", "bytes")):
                if data["response"] == "json":
                    content = response.json()

                else:
                    import base64

                    content = base64.standard_b64encode(response.content)

                response_result["content"] = content
    except Exception:
        logging.getLogger(__name__).exception(
            "Error while running a test {} request on {}".format(method, url))
        outcome = False

    result = {"url": url, "status": status, "result": outcome}
    if response_result:
        result["response"] = response_result

    return jsonify(**result)
Exemplo n.º 2
0
def _test_url(data):
	import requests

	class StatusCodeRange(object):
		def __init__(self, start=None, end=None):
			self.start = start
			self.end = end

		def __contains__(self, item):
			if not isinstance(item, int):
				return False
			if self.start and self.end:
				return self.start <= item < self.end
			elif self.start:
				return self.start <= item
			elif self.end:
				return item < self.end
			else:
				return False

		def as_dict(self):
			return dict(
				start=self.start,
				end=self.end
			)

	status_ranges = dict(
		informational=StatusCodeRange(start=100, end=200),
		success=StatusCodeRange(start=200, end=300),
		redirection=StatusCodeRange(start=300, end=400),
		client_error=StatusCodeRange(start=400, end=500),
		server_error=StatusCodeRange(start=500, end=600),
		normal=StatusCodeRange(end=400),
		error=StatusCodeRange(start=400, end=600),
		any=StatusCodeRange(start=100),
		timeout=StatusCodeRange(start=0, end=1)
	)

	url = data["url"]
	method = data.get("method", "HEAD")
	timeout = 3.0
	valid_ssl = True
	check_status = [status_ranges["normal"]]
	content_type_whitelist = None
	content_type_blacklist = None

	if "timeout" in data:
		try:
			timeout = float(data["timeout"])
		except:
			return make_response("{!r} is not a valid value for timeout (must be int or float)".format(data["timeout"]),
			                     400)

	if "validSsl" in data:
		valid_ssl = data["validSsl"] in valid_boolean_trues

	if "status" in data:
		request_status = data["status"]
		if not isinstance(request_status, list):
			request_status = [request_status]

		check_status = []
		for rs in request_status:
			if isinstance(rs, int):
				check_status.append([rs])
			else:
				if rs in status_ranges:
					check_status.append(status_ranges[rs])
				else:
					code = requests.codes[rs]
					if code is not None:
						check_status.append([code])

	if "content_type_whitelist" in data:
		if not isinstance(data["content_type_whitelist"], (list, tuple)):
			return make_response("content_type_whitelist must be a list of mime types")
		content_type_whitelist = map(util.parse_mime_type, data["content_type_whitelist"])
	if "content_type_blacklist" in data:
		if not isinstance(data["content_type_whitelist"], (list, tuple)):
			return make_response("content_type_blacklist must be a list of mime types")
		content_type_blacklist = map(util.parse_mime_type, data["content_type_blacklist"])

	response_result = None
	outcome = True
	status = 0
	try:
		with requests.request(method=method, url=url, timeout=timeout, verify=valid_ssl, stream=True) as response:
			status = response.status_code
			outcome = outcome and any(map(lambda x: status in x, check_status))
			content_type = response.headers.get("content-type")

			response_result = dict(headers=dict(response.headers),
			                       content_type=content_type)

			parsed_content_type = util.parse_mime_type(content_type)
			in_whitelist = content_type_whitelist is None or any(
				map(lambda x: util.mime_type_matches(parsed_content_type, x), content_type_whitelist))
			in_blacklist = content_type_blacklist is not None and any(
				map(lambda x: util.mime_type_matches(parsed_content_type, x), content_type_blacklist))

			if not in_whitelist or in_blacklist:
				# we don't support this content type
				response.close()
				outcome = False

			elif "response" in data and (
					data["response"] in valid_boolean_trues or data["response"] in ("json", "bytes")):
				if data["response"] == "json":
					content = response.json()

				else:
					import base64
					content = base64.standard_b64encode(response.content)

				response_result["content"] = content
	except:
		logging.getLogger(__name__).exception("Error while running a test {} request on {}".format(method, url))
		outcome = False

	result = dict(
		url=url,
		status=status,
		result=outcome
	)
	if response_result:
		result["response"] = response_result

	return jsonify(**result)