Skip to content

Commit

Permalink
Fix #350 seperate column for errors (#352)
Browse files Browse the repository at this point in the history
* Fix #350 separate column for errors

* Fix test cases
  • Loading branch information
cedric05 authored Jan 13, 2025
1 parent 7d104ed commit ca44c46
Show file tree
Hide file tree
Showing 11 changed files with 200 additions and 50 deletions.
85 changes: 61 additions & 24 deletions dotextensions/server/handlers/basic_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,20 @@ def run(self, command: Command) -> Result:
except DotHttpException as exc:
logger.error(f"dothttp exception happened {exc}", exc_info=True)
result = Result(
id=command.id, result={"error_message": exc.message, "error": True}
id=command.id, result={
"error_message": exc.message, "error": True}
)
except RequestException as exc:
logger.error(f"exception from requests {exc}", exc_info=True)
result = Result(
id=command.id, result={"error_message": str(exc), "error": True}
id=command.id, result={
"error_message": str(exc), "error": True}
)
except Exception as exc:
logger.error(f"unknown error happened {exc}", exc_info=True)
result = Result(
id=command.id, result={"error_message": str(exc), "error": True}
id=command.id, result={
"error_message": str(exc), "error": True}
)
return result

Expand All @@ -71,14 +74,14 @@ def execute(self, command):
req = self.get_curl_comp(config)
result = req.get_curl_output()
result = Result(
id=command.id,
result={
"body": result,
"headers": {
"Content-Type": mimetypes.types_map[".sh"],
},
id=command.id,
result={
"body": result,
"headers": {
"Content-Type": mimetypes.types_map[".sh"],
},
)
},
)
else:
comp = self.get_request_comp(config)
result = self.get_request_result(command, comp)
Expand All @@ -94,7 +97,8 @@ def get_config(self, command):
target = params.get("target", "1")
nocookie = params.get("nocookie", False)
curl = params.get("curl", False)
properties = [f"{i}={j}" for i, j in params.get("properties", {}).items()]
properties = [f"{i}={j}" for i,
j in params.get("properties", {}).items()]
content = params.get("content", None)
contexts = params.get("contexts")
property_file = params.get("property-file", None)
Expand Down Expand Up @@ -123,6 +127,26 @@ def get_config(self, command):

def get_request_result(self, command, comp: RequestCompiler):
comp.load_def()
if comp.property_util.errors:
return Result(
id=command.id,
result={
"errors": [{"var": list(error.kwargs['var']), "message": str(error)} for error in comp.property_util.errors],
"response": {
"body": "",
"output_file": "",
"status": 0,
"method": "ERROR",
"url": "ERROR",
"headers": {
"Content-Type": "text/plain",
},
"error": True,
"error_message": "errors found",
"contentType": "text/plain",
},
},
)
resp = comp.get_response()
if output := comp.httpdef.output:
# body = f"Output stored in {output}"
Expand All @@ -131,7 +155,8 @@ def get_request_result(self, command, comp: RequestCompiler):
except Exception as e:
output = f"Not!. unhandled error happened : {e}"
logger.warning("unable to write because", exc_info=True)
script_result = comp.script_execution.execute_test_script(resp).as_json()
script_result = comp.script_execution.execute_test_script(
resp).as_json()
body = resp.text
response_data = {
"response": {
Expand All @@ -140,6 +165,7 @@ def get_request_result(self, command, comp: RequestCompiler):
**self._get_resp_data(resp),
},
"script_result": script_result,
"errors": [error.kwargs for error in comp.property_util.errors],
}
if resp.history:
response_data["history"] = [
Expand All @@ -153,9 +179,11 @@ def get_request_result(self, command, comp: RequestCompiler):
# redirects can add cookies
comp.httpdef.headers["cookie"] = resp.request.headers["cookie"]
try:
data.update({"http": self.get_http_from_req(comp.httpdef, comp.property_util)})
data.update({"http": self.get_http_from_req(
comp.httpdef, comp.property_util)})
except Exception as e:
logger.error("ran into error regenerating http def from parsed object")
logger.error(
"ran into error regenerating http def from parsed object")
data.update(
{"http": f"ran into error \n Exception: `{e}` message:{e.args}"}
)
Expand All @@ -175,7 +203,8 @@ def get_request_comp(self, config):

@staticmethod
def get_http_from_req(request: HttpDef, property_util: "PropertyProvider"):
http_def = MultidefHttp(import_list=[], allhttps=[request.get_http_from_req()])
http_def = MultidefHttp(import_list=[], allhttps=[
request.get_http_from_req()])
return HttpFileFormatter.format(http_def, property_util=property_util)


Expand All @@ -200,7 +229,8 @@ def load_model(self):
##
# context has varibles defined
# for resolving purpose, including them into content
self.content = self.content + CONTEXT_SEP + CONTEXT_SEP.join(self.args.contexts)
self.content = self.content + CONTEXT_SEP + \
CONTEXT_SEP.join(self.args.contexts)

def select_target(self):
for context in self.args.contexts:
Expand All @@ -219,7 +249,7 @@ def select_target(self):
self.model.import_list = model.import_list
self.load_imports()
self.content += context + "\n\n" + context

except Exception as e:
# contexts, can not always be correct syntax
# in such scenarios, don't complain, try to resolve with
Expand Down Expand Up @@ -277,19 +307,20 @@ def run(self, command: Command) -> Result:
"headers": {
"Content-Type": "text/plain",
},
"output_file":"",
"output_file": "",
"error": True,
"error_message": error_result,
"contentType": "text/plain",
}
result = {
"response": response,
"script_result": {"stdout": "", "error": "", "properties":{}, "tests":[]},
"script_result": {"stdout": "", "error": "", "properties": {}, "tests": []},
"http": "REQUEST_EXECUTION_ERROR",
"filenameExtension": ".txt",
}
result.update(response)
return Result(id=command.id, result=result)
return Result(id=command.id, result=result)


class FormatHttpFileHandler(BaseHandler):
method = "/file/format"
Expand All @@ -301,6 +332,7 @@ def run(self, command: Command) -> Result:
result = Result(id=command.id, result=command.params)
return result


class ResolveBase():

def get_resolved(self, command: Command) -> Result:
Expand All @@ -320,7 +352,7 @@ def get_resolved(self, command: Command) -> Result:
if match.start() <= pos <= match.end():
property_hovered = match.group()[2:-2].split("=")[0].strip()
break

type_dict = TypeFromPos.figure_n_get(model, pos)
if "target" not in type_dict:
command.params["target"] = 1
Expand Down Expand Up @@ -363,12 +395,14 @@ def get_resolved(self, command: Command) -> Result:
return Result(id=command.id, result=type_dict)

# return resolved string instead of model object


class GetHoveredResolvedParamFileHandler(RunHttpFileHandler, ResolveBase):
method = "/file/resolve"

def get_method(self):
return GetHoveredResolvedParamFileHandler.method

def run(self, command):
return self.get_resolved(command)

Expand All @@ -382,6 +416,7 @@ def get_method(self):
def run(self, command):
return self.get_resolved(command)


class GetNameReferencesHandler(BaseHandler):
name = "/file/names"

Expand All @@ -394,7 +429,8 @@ def run(self, command: Command) -> Result:
result = self.execute(command, filename)
except DotHttpException as ex:
result = Result(
id=command.id, result={"error_message": ex.message, "error": True}
id=command.id, result={
"error_message": ex.message, "error": True}
)
except Exception as e:
result = Result(
Expand Down Expand Up @@ -428,7 +464,8 @@ def parse_n_get(self, http_data, filename: str):
for new_model, _content in BaseModelProcessor._get_models_from_import(
model, filename
):
self.get_for_http(new_model.allhttps, imported_names, imported_urls)
self.get_for_http(new_model.allhttps,
imported_names, imported_urls)
return all_names, all_urls, imported_names, imported_urls

def get_for_http(self, allhttps, all_names, all_urls):
Expand Down
13 changes: 13 additions & 0 deletions dothttp/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ def wrapper(cls):
class exc(cls):
def __init__(self, **kwargs):
self.message = message.format(**kwargs)
self.kwargs = kwargs

return exc

Expand All @@ -17,6 +18,18 @@ def __str__(self) -> str:
return self.message


class DothttpMultiExceptions(DotHttpException):
def __init__(self, exceptions):
self.exceptions = exceptions

@property
def message(self):
return "\n".join([str(exception) for exception in self.exceptions])

def __str__(self) -> str:
return "\n".join([str(exception) for exception in self.exceptions])


@exception_wrapper(
"http def with name `{base}` not defined for http with name `{target}`"
)
Expand Down
7 changes: 6 additions & 1 deletion dothttp/parse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ def __init__(self, args: Config):
self.content = ""
self.original_content = self.content = ""
self.property_util = PropertyProvider(self.property_file)
self.errors = []
self.load()

def load(self):
Expand Down Expand Up @@ -277,7 +278,11 @@ def load_content(self):
self.original_content = self.content = f.read()

def get_updated_content(self, content) -> str:
return self.property_util.get_updated_content(content)
try:
return self.property_util.get_updated_content(content)
except DotHttpException as e:
self.errors.append(e)
return content

def get_updated_content_object(self, content) -> str:
return self.property_util.get_updated_content(content, "obj")
Expand Down
6 changes: 5 additions & 1 deletion dothttp/parse/request_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from ..utils.property_util import PropertyProvider, Property

from ..exceptions import DothttpUnSignedCertException
from ..exceptions import DothttpMultiExceptions, DothttpUnSignedCertException
from ..models.parse_models import Http, HttpFileType, MultidefHttp, ScriptType
from ..parse import (
APPLICATION_JSON,
Expand Down Expand Up @@ -480,6 +480,10 @@ def query_to_http(line):
class RequestCompiler(RequestBase):
def run(self):
self.load_def()
if len(self.property_util.errors) > 0:
for error in self.errors:
eprint(error)
raise DothttpMultiExceptions(self.property_util.errors)
resp = self.get_response()
self.print_req_info(resp.request)
for hist_resp in resp.history:
Expand Down
31 changes: 18 additions & 13 deletions dothttp/utils/property_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ def __init__(self, property_file=""):
self.command_line_properties = {}
self.property_file = property_file
self.is_running_system_command_enabled = False
self.errors = []

def enable_system_command(self):
self.is_running_system_command_enabled = True
Expand Down Expand Up @@ -238,19 +239,23 @@ def is_special_keyword(key):
return ret or key.startswith("$expr:")

def get_updated_content(self, content, type="str"):
content_prop_needed, props_needed = self.check_properties_for_content(
content)
for var in props_needed:
if type == "str":
value = self.resolve_property_string(var)
for text_to_replace in content_prop_needed[var].text:
content = content.replace(
"{{" + text_to_replace + "}}", str(value)
)
else:
content = self.resolve_property_object(var)
base_logger.debug(f"using `{content}` for property {var}")
return content
try:
content_prop_needed, props_needed = self.check_properties_for_content(
content)
for var in props_needed:
if type == "str":
value = self.resolve_property_string(var)
for text_to_replace in content_prop_needed[var].text:
content = content.replace(
"{{" + text_to_replace + "}}", str(value)
)
else:
content = self.resolve_property_object(var)
base_logger.debug(f"using `{content}` for property {var}")
return content
except PropertyNotFoundException as e:
self.errors.append(e)
return content

def get_updated_obj_content(self, content):
return self.get_updated_content(content, "obj")
Expand Down
Loading

0 comments on commit ca44c46

Please sign in to comment.