Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
The Tor Project
Network Health
Metrics
Exonerator
Commits
a8bb4bab
Commit
a8bb4bab
authored
Nov 22, 2017
by
iwakeh
Browse files
Add minimal-invasive catch-all clauses for all servlets.
This should be a temporary measure to investigate task-24534.
parent
cb5700d5
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/main/java/org/torproject/metrics/exonerator/ExoneraTorServlet.java
View file @
a8bb4bab
...
...
@@ -66,156 +66,164 @@ public class ExoneraTorServlet extends HttpServlet {
/* Step 1: Parse the request. */
/* Parse ip parameter. */
String
ipParameter
=
request
.
getParameter
(
"ip"
);
String
relayIp
=
parseIpParameter
(
ipParameter
);
final
boolean
relayIpHasError
=
relayIp
==
null
;
/* Parse timestamp parameter. */
String
timestampParameter
=
request
.
getParameter
(
"timestamp"
);
String
timestampStr
=
parseTimestampParameter
(
timestampParameter
);
final
boolean
timestampHasError
=
timestampStr
==
null
;
/* Parse lang parameter. */
String
langParameter
=
request
.
getParameter
(
"lang"
);
String
langStr
=
"en"
;
if
(
null
!=
langParameter
&&
this
.
availableLanguages
.
contains
(
langParameter
))
{
langStr
=
langParameter
;
}
try
{
/* Parse ip parameter. */
String
ipParameter
=
request
.
getParameter
(
"ip"
);
String
relayIp
=
parseIpParameter
(
ipParameter
);
final
boolean
relayIpHasError
=
relayIp
==
null
;
/* Parse timestamp parameter. */
String
timestampParameter
=
request
.
getParameter
(
"timestamp"
);
String
timestampStr
=
parseTimestampParameter
(
timestampParameter
);
final
boolean
timestampHasError
=
timestampStr
==
null
;
/* Parse lang parameter. */
String
langParameter
=
request
.
getParameter
(
"lang"
);
String
langStr
=
"en"
;
if
(
null
!=
langParameter
&&
this
.
availableLanguages
.
contains
(
langParameter
))
{
langStr
=
langParameter
;
}
/* Step 2: Query the backend server. */
boolean
successfullyConnectedToBackend
=
false
;
String
firstDate
=
null
;
String
lastDate
=
null
;
boolean
noRelevantConsensuses
=
true
;
List
<
String
[]>
statusEntries
=
new
ArrayList
<>();
List
<
String
>
addressesInSameNetwork
=
null
;
/* Only query, if we received valid user input. */
if
(
null
!=
relayIp
&&
!
relayIp
.
isEmpty
()
&&
null
!=
timestampStr
&&
!
timestampStr
.
isEmpty
())
{
QueryResponse
queryResponse
=
this
.
queryBackend
(
relayIp
,
timestampStr
);
if
(
null
!=
queryResponse
)
{
successfullyConnectedToBackend
=
true
;
firstDate
=
queryResponse
.
firstDateInDatabase
;
lastDate
=
queryResponse
.
lastDateInDatabase
;
if
(
null
!=
queryResponse
.
relevantStatuses
&&
queryResponse
.
relevantStatuses
)
{
noRelevantConsensuses
=
false
;
}
if
(
null
!=
queryResponse
.
matches
)
{
for
(
QueryResponse
.
Match
match
:
queryResponse
.
matches
)
{
StringBuilder
sb
=
new
StringBuilder
();
int
writtenAddresses
=
0
;
for
(
String
address
:
match
.
addresses
)
{
sb
.
append
((
writtenAddresses
++
>
0
?
", "
:
""
)
+
address
);
/* Step 2: Query the backend server. */
boolean
successfullyConnectedToBackend
=
false
;
String
firstDate
=
null
;
String
lastDate
=
null
;
boolean
noRelevantConsensuses
=
true
;
List
<
String
[]>
statusEntries
=
new
ArrayList
<>();
List
<
String
>
addressesInSameNetwork
=
null
;
/* Only query, if we received valid user input. */
if
(
null
!=
relayIp
&&
!
relayIp
.
isEmpty
()
&&
null
!=
timestampStr
&&
!
timestampStr
.
isEmpty
())
{
QueryResponse
queryResponse
=
this
.
queryBackend
(
relayIp
,
timestampStr
);
if
(
null
!=
queryResponse
)
{
successfullyConnectedToBackend
=
true
;
firstDate
=
queryResponse
.
firstDateInDatabase
;
lastDate
=
queryResponse
.
lastDateInDatabase
;
if
(
null
!=
queryResponse
.
relevantStatuses
&&
queryResponse
.
relevantStatuses
)
{
noRelevantConsensuses
=
false
;
}
if
(
null
!=
queryResponse
.
matches
)
{
for
(
QueryResponse
.
Match
match
:
queryResponse
.
matches
)
{
StringBuilder
sb
=
new
StringBuilder
();
int
writtenAddresses
=
0
;
for
(
String
address
:
match
.
addresses
)
{
sb
.
append
((
writtenAddresses
++
>
0
?
", "
:
""
)
+
address
);
}
String
[]
statusEntry
=
new
String
[]{
match
.
timestamp
,
sb
.
toString
(),
match
.
fingerprint
,
match
.
nickname
,
null
==
match
.
exit
?
"U"
:
(
match
.
exit
?
"Y"
:
"N"
)};
statusEntries
.
add
(
statusEntry
);
}
String
[]
statusEntry
=
new
String
[]{
match
.
timestamp
,
sb
.
toString
(),
match
.
fingerprint
,
match
.
nickname
,
null
==
match
.
exit
?
"U"
:
(
match
.
exit
?
"Y"
:
"N"
)};
statusEntries
.
add
(
statusEntry
);
}
}
if
(
null
!=
queryResponse
.
nearbyAddresses
)
{
addressesInSameNetwork
=
Arrays
.
asList
(
queryResponse
.
nearbyAddresses
);
if
(
null
!=
queryResponse
.
nearbyAddresses
)
{
addressesInSameNetwork
=
Arrays
.
asList
(
queryResponse
.
nearbyAddresses
);
}
}
}
}
/* Step 3: Write the response. */
/* Set content type, or the page doesn't render in Chrome. */
response
.
setContentType
(
"text/html"
);
response
.
setCharacterEncoding
(
"utf-8"
);
/* Find the right resource bundle for the user's requested language. */
ResourceBundle
rb
=
ResourceBundle
.
getBundle
(
"ExoneraTor"
,
Locale
.
forLanguageTag
(
langStr
));
/* Start writing response. */
StringWriter
so
=
new
StringWriter
();
PrintWriter
out
=
new
PrintWriter
(
so
);
this
.
writeHeader
(
out
,
rb
,
langStr
);
/* Write form. */
boolean
timestampOutOfRange
=
null
!=
timestampStr
&&
(
null
!=
firstDate
&&
timestampStr
.
compareTo
(
firstDate
)
<
0
||
(
null
!=
lastDate
&&
timestampStr
.
compareTo
(
lastDate
)
>
0
));
this
.
writeForm
(
out
,
rb
,
relayIp
,
relayIpHasError
||
(
""
.
equals
(
relayIp
)
&&
!
""
.
equals
(
timestampStr
)),
timestampStr
,
!
relayIpHasError
&&
!(
""
.
equals
(
relayIp
)
&&
!
""
.
equals
(
timestampStr
))
&&
(
timestampHasError
||
timestampOutOfRange
||
(!
""
.
equals
(
relayIp
)
&&
""
.
equals
(
timestampStr
))),
langStr
);
/* If both parameters are empty, don't print any summary and exit.
* This is the start page. */
if
(
""
.
equals
(
relayIp
)
&&
""
.
equals
(
timestampStr
))
{
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
/* If only one parameter is empty and the other is not, print summary with
* warning message and exit. */
}
else
if
(
""
.
equals
(
relayIp
))
{
this
.
writeSummaryNoIp
(
out
,
rb
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
}
else
if
(
""
.
equals
(
timestampStr
))
{
this
.
writeSummaryNoTimestamp
(
out
,
rb
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
/* If there's an issue with parsing either of the parameters, print summary
* with error message and exit. */
}
else
if
(
relayIpHasError
)
{
this
.
writeSummaryInvalidIp
(
out
,
rb
,
ipParameter
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
}
else
if
(
timestampHasError
)
{
this
.
writeSummaryInvalidTimestamp
(
out
,
rb
,
timestampParameter
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
/* If we were unable to connect to the database, write an error message. */
}
else
if
(!
successfullyConnectedToBackend
)
{
this
.
writeSummaryUnableToConnectToBackend
(
out
,
rb
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
/* Similarly, if we found the database to be empty, write an error message,
* too. */
}
else
if
(
null
==
firstDate
||
null
==
lastDate
)
{
this
.
writeSummaryNoData
(
out
,
rb
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
/* If the requested date is out of range, tell the user. */
}
else
if
(
timestampOutOfRange
)
{
this
.
writeSummaryTimestampOutsideRange
(
out
,
rb
,
timestampStr
,
firstDate
,
lastDate
);
this
.
writeFooter
(
out
,
rb
,
relayIp
,
timestampStr
);
}
else
if
(
noRelevantConsensuses
)
{
this
.
writeSummaryNoDataForThisInterval
(
out
,
rb
);
this
.
writeFooter
(
out
,
rb
,
relayIp
,
timestampStr
);
/* Print out result. */
}
else
{
if
(!
statusEntries
.
isEmpty
())
{
this
.
writeSummaryPositive
(
out
,
rb
,
relayIp
,
timestampStr
);
this
.
writeTechnicalDetails
(
out
,
rb
,
relayIp
,
timestampStr
,
statusEntries
);
}
else
if
(
addressesInSameNetwork
!=
null
&&
!
addressesInSameNetwork
.
isEmpty
())
{
this
.
writeSummaryAddressesInSameNetwork
(
out
,
rb
,
relayIp
,
timestampStr
,
langStr
,
addressesInSameNetwork
);
/* Step 3: Write the response. */
/* Set content type, or the page doesn't render in Chrome. */
response
.
setContentType
(
"text/html"
);
response
.
setCharacterEncoding
(
"utf-8"
);
/* Find the right resource bundle for the user's requested language. */
ResourceBundle
rb
=
ResourceBundle
.
getBundle
(
"ExoneraTor"
,
Locale
.
forLanguageTag
(
langStr
));
/* Start writing response. */
StringWriter
so
=
new
StringWriter
();
PrintWriter
out
=
new
PrintWriter
(
so
);
this
.
writeHeader
(
out
,
rb
,
langStr
);
/* Write form. */
boolean
timestampOutOfRange
=
null
!=
timestampStr
&&
(
null
!=
firstDate
&&
timestampStr
.
compareTo
(
firstDate
)
<
0
||
(
null
!=
lastDate
&&
timestampStr
.
compareTo
(
lastDate
)
>
0
));
this
.
writeForm
(
out
,
rb
,
relayIp
,
relayIpHasError
||
(
""
.
equals
(
relayIp
)
&&
!
""
.
equals
(
timestampStr
)),
timestampStr
,
!
relayIpHasError
&&
!(
""
.
equals
(
relayIp
)
&&
!
""
.
equals
(
timestampStr
))
&&
(
timestampHasError
||
timestampOutOfRange
||
(!
""
.
equals
(
relayIp
)
&&
""
.
equals
(
timestampStr
))),
langStr
);
/* If both parameters are empty, don't print any summary and exit.
* This is the start page. */
if
(
""
.
equals
(
relayIp
)
&&
""
.
equals
(
timestampStr
))
{
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
/* If only one parameter is empty and the other is not, print summary
* with warning message and exit. */
}
else
if
(
""
.
equals
(
relayIp
))
{
this
.
writeSummaryNoIp
(
out
,
rb
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
}
else
if
(
""
.
equals
(
timestampStr
))
{
this
.
writeSummaryNoTimestamp
(
out
,
rb
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
/* If there's an issue with parsing either of the parameters, print
* summary with error message and exit. */
}
else
if
(
relayIpHasError
)
{
this
.
writeSummaryInvalidIp
(
out
,
rb
,
ipParameter
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
}
else
if
(
timestampHasError
)
{
this
.
writeSummaryInvalidTimestamp
(
out
,
rb
,
timestampParameter
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
/* If we were unable to connect to the database,
* write an error message. */
}
else
if
(!
successfullyConnectedToBackend
)
{
this
.
writeSummaryUnableToConnectToBackend
(
out
,
rb
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
/* Similarly, if we found the database to be empty,
* write an error message, too. */
}
else
if
(
null
==
firstDate
||
null
==
lastDate
)
{
this
.
writeSummaryNoData
(
out
,
rb
);
this
.
writeFooter
(
out
,
rb
,
null
,
null
);
/* If the requested date is out of range, tell the user. */
}
else
if
(
timestampOutOfRange
)
{
this
.
writeSummaryTimestampOutsideRange
(
out
,
rb
,
timestampStr
,
firstDate
,
lastDate
);
this
.
writeFooter
(
out
,
rb
,
relayIp
,
timestampStr
);
}
else
if
(
noRelevantConsensuses
)
{
this
.
writeSummaryNoDataForThisInterval
(
out
,
rb
);
this
.
writeFooter
(
out
,
rb
,
relayIp
,
timestampStr
);
/* Print out result. */
}
else
{
this
.
writeSummaryNegative
(
out
,
rb
,
relayIp
,
timestampStr
);
if
(!
statusEntries
.
isEmpty
())
{
this
.
writeSummaryPositive
(
out
,
rb
,
relayIp
,
timestampStr
);
this
.
writeTechnicalDetails
(
out
,
rb
,
relayIp
,
timestampStr
,
statusEntries
);
}
else
if
(
addressesInSameNetwork
!=
null
&&
!
addressesInSameNetwork
.
isEmpty
())
{
this
.
writeSummaryAddressesInSameNetwork
(
out
,
rb
,
relayIp
,
timestampStr
,
langStr
,
addressesInSameNetwork
);
}
else
{
this
.
writeSummaryNegative
(
out
,
rb
,
relayIp
,
timestampStr
);
}
this
.
writePermanentLink
(
out
,
rb
,
relayIp
,
timestampStr
,
langStr
);
this
.
writeFooter
(
out
,
rb
,
relayIp
,
timestampStr
);
}
this
.
writePermanentLink
(
out
,
rb
,
relayIp
,
timestampStr
,
langStr
);
this
.
writeFooter
(
out
,
rb
,
relayIp
,
timestampStr
);
}
/* Forward to the JSP that adds header and footer. */
request
.
setAttribute
(
"lang"
,
langStr
);
request
.
setAttribute
(
"body"
,
so
.
toString
());
request
.
getRequestDispatcher
(
"WEB-INF/index.jsp"
).
forward
(
request
,
response
);
/* Forward to the JSP that adds header and footer. */
request
.
setAttribute
(
"lang"
,
langStr
);
request
.
setAttribute
(
"body"
,
so
.
toString
());
request
.
getRequestDispatcher
(
"WEB-INF/index.jsp"
).
forward
(
request
,
response
);
}
catch
(
Throwable
th
)
{
logger
.
error
(
"Some problem in doGet. Returning error."
,
th
);
response
.
sendError
(
HttpServletResponse
.
SC_INTERNAL_SERVER_ERROR
,
"General error."
);
}
}
/* Helper methods for handling the request. */
...
...
@@ -310,6 +318,8 @@ public class ExoneraTorServlet extends HttpServlet {
/* No result from backend, so that we don't have a query response to
* process further. */
logger
.
error
(
"Backend query failed."
,
e
);
}
catch
(
Throwable
th
)
{
logger
.
error
(
"Backend query failed with general error."
,
th
);
}
return
null
;
}
...
...
src/main/java/org/torproject/metrics/exonerator/QueryServlet.java
View file @
a8bb4bab
...
...
@@ -62,45 +62,50 @@ public class QueryServlet extends HttpServlet {
public
void
doGet
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
,
ServletException
{
try
{
/* Parse ip parameter. */
String
ipParameter
=
request
.
getParameter
(
"ip"
);
if
(
null
==
ipParameter
)
{
response
.
sendError
(
HttpServletResponse
.
SC_BAD_REQUEST
,
"Missing ip parameter."
);
return
;
}
String
relayIp
=
this
.
parseIpParameter
(
ipParameter
);
if
(
null
==
relayIp
)
{
response
.
sendError
(
HttpServletResponse
.
SC_BAD_REQUEST
,
"Invalid ip parameter."
);
return
;
}
/* Parse ip parameter. */
String
ipParameter
=
request
.
getParameter
(
"ip"
);
if
(
null
==
ipParameter
)
{
response
.
sendError
(
HttpServletResponse
.
SC_BAD_REQUEST
,
"Missing ip parameter."
);
return
;
}
String
relayIp
=
this
.
parseIpParameter
(
ipParameter
);
if
(
null
==
relayIp
)
{
response
.
sendError
(
HttpServletResponse
.
SC_BAD_REQUEST
,
"Invalid ip parameter."
);
return
;
}
/* Parse timestamp parameter. */
String
timestampParameter
=
request
.
getParameter
(
"timestamp"
);
if
(
null
==
timestampParameter
)
{
response
.
sendError
(
HttpServletResponse
.
SC_BAD_REQUEST
,
"Missing timestamp parameter."
);
return
;
}
Long
timestamp
=
this
.
parseTimestampParameter
(
timestampParameter
);
if
(
null
==
timestamp
)
{
response
.
sendError
(
HttpServletResponse
.
SC_BAD_REQUEST
,
"Invalid timestamp parameter."
);
return
;
}
/* Parse timestamp parameter. */
String
timestampParameter
=
request
.
getParameter
(
"timestamp"
);
if
(
null
==
timestampParameter
)
{
response
.
sendError
(
HttpServletResponse
.
SC_BAD_REQUEST
,
"Missing timestamp parameter."
);
return
;
}
Long
timestamp
=
this
.
parseTimestampParameter
(
timestampParameter
);
if
(
null
==
timestamp
)
{
response
.
sendError
(
HttpServletResponse
.
SC_BAD_REQUEST
,
"Invalid timestamp parameter."
);
return
;
}
/* Query the database. */
QueryResponse
queryResponse
=
this
.
queryDatabase
(
relayIp
,
timestamp
);
if
(
null
==
queryResponse
)
{
/* Query the database. */
QueryResponse
queryResponse
=
this
.
queryDatabase
(
relayIp
,
timestamp
);
if
(
null
==
queryResponse
)
{
response
.
sendError
(
HttpServletResponse
.
SC_INTERNAL_SERVER_ERROR
,
"Database error."
);
}
else
{
/* Write the response. */
response
.
setContentType
(
"application/json"
);
response
.
setCharacterEncoding
(
"utf-8"
);
response
.
getWriter
().
write
(
QueryResponse
.
toJson
(
queryResponse
));
}
}
catch
(
Throwable
th
)
{
logger
.
error
(
"Some problem in doGet. Returning error."
,
th
);
response
.
sendError
(
HttpServletResponse
.
SC_INTERNAL_SERVER_ERROR
,
"Database error."
);
}
else
{
/* Write the response. */
response
.
setContentType
(
"application/json"
);
response
.
setCharacterEncoding
(
"utf-8"
);
response
.
getWriter
().
write
(
QueryResponse
.
toJson
(
queryResponse
));
"General backend error."
);
}
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment