-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path502.py
205 lines (172 loc) · 6.59 KB
/
502.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#!/usr/bin/env python
from functools import cached_property
from os import environ
from pathlib import Path
from urllib.parse import parse_qs, urlparse
from cdrapi.users import Session
from cdrcgi import Controller
class Control(Controller):
"""Create a 502 (bad gateway) page.
Note that we need to check to see if this really should have been
a 404 error instead of a problem with the server, because for some
reason IIS doesn't handle the failure to find the Python script
specified in the URL correctly.
"""
LOGNAME = "error-502"
def run(self):
"""Take over control of the page."""
opts = dict(subtitle=self.subtitle, session=self.session)
page = self.HTMLPage("CDR Administration", **opts)
page.form.append(
page.B.P(
"If the problem persists, please create a ",
self.jira,
" ticket in the OCECDR project. If the problem is "
"obviously a network or other infrastructure failure, "
"it may be appropriate to also file a ticket with ",
self.service_now,
"."
)
)
if self.fields.getvalue("clean"):
parent = page.header.find("div")
if parent is not None:
nav = parent.find("nav")
if nav is not None:
parent.remove(nav)
page.body.remove(page.footer)
page.add_alert(self.alert, type="error")
page.add_uswds_script()
page.send()
@cached_property
def alert(self):
"""Notification of the problem."""
if not self.missing:
return "A problem occurred while processing your request."
script = self.original_script
return f"🔎 We really looked, but we can't find {script!r}. 👀"
@cached_property
def jira(self):
"""Link for creating a new CDR ticket in JIRA (if we have the URL)."""
args = "trackers", "create-cdr-ticket"
url = self.session.tier.get_control_value(self.session, *args)
if not url:
return "JIRA"
return self.HTMLPage.B.A("JIRA", href=url, target="_blank")
@cached_property
def missing(self):
"""Should this really be a 404 page?"""
if not self.path:
return False
if not self.path.exists():
self.logger.warning("unable to find %s", self.path)
return True
return False
@cached_property
def original_script(self):
"""The script which was invoked when the problem was encountered."""
return self.parsed_url.path if self.parsed_url else None
@cached_property
def original_url(self):
"""The URL for the original request which failed."""
query_string = environ.get("QUERY_STRING")
if not query_string:
self.logger.warning("QUERY_STRING missing")
return None
self.logger.info("QUERY_STRING=%s", query_string)
if ";" not in query_string:
message = "unexpected syntax for QUERY_STRING: %s"
self.logger.warning(message, query_string)
return None
return query_string.split(";", 1)[1]
@cached_property
def parsed_url(self):
"""The parsed URL for the request which failed."""
if not self.original_url:
return None
try:
parsed = urlparse(self.original_url)
self.logger.info("parsed_url=%s", parsed)
return parsed
except Exception:
self.logger.exception("failure parsing %s", self.original_url)
self.alert = "Failure parsing URL for original request."
return None
@cached_property
def path(self):
"""Path object for the location of the CGI script."""
return self.www_root / self.original_script.strip("/")
@cached_property
def script_text(self):
"""The contents of the script file."""
if self.missing:
return None
try:
return self.path.read_text(encoding="utf-8")
except Exception:
self.logger.exception("reading %s", self.path)
self.alert = (
"The web server does not have permission "
f"to read the script {self.original_script}."
)
return None
@cached_property
def script_valid(self):
"""True if the script can be successfully compiled.
Doesn't detect problems with the included libraries.
"""
if self.script_text is None:
return False
if not self.script_text.strip():
self.alert = f"Script {self.original_script} is empty."
return False
try:
compile(self.script_text + "\n", "<string>", "exec")
return True
except Exception:
self.logger.exception("compiling %s", self.original_script)
self.alert = f"Script {self.original_script} has syntax errors."
return False
@cached_property
def service_now(self):
"""Link for creating a Service Now ticket (if we have the URL)."""
label = "NCI at Your Service"
args = "trackers", "create-sn-ticket"
url = self.session.tier.get_control_value(self.session, *args)
if not url:
return label
return self.HTMLPage.B.A(label, href=url, target="_blank")
@cached_property
def session(self):
"""Overridden so we can pull the session from the original URL."""
if self.parsed_url:
query_string = parse_qs(self.parsed_url.query)
self.logger.info("query_string=%s", query_string)
if self.SESSION in query_string:
try:
session = Session(query_string[self.SESSION][0])
self.logger.info("Session=%s", session)
return session
except Exception:
self.logger.exception(query_string[self.SESSION])
return Session("guest")
@cached_property
def subtitle(self):
"""What we want shown at the top of the page."""
if self.missing:
return "Script Not Found"
if self.script_text is None:
return "Permissions Error"
if not self.script_valid:
return "Program Error"
return "Server Error"
@cached_property
def www_root(self):
"""Base directory for the web site's documents."""
return Path(__file__).parent.parent.parent
if __name__ == "__main__":
control = Control()
try:
control.run()
except Exception as e:
control.bail(e)