Skip to content

Commit

Permalink
Implementation of requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
ftsalamp authored and danielballan committed May 11, 2018
1 parent 9e38fed commit 3f92aee
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 52 deletions.
61 changes: 29 additions & 32 deletions web_monitoring/diffing_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
from docopt import docopt
import hashlib
import inspect
import json
import re
import sys
import tornado.gen
import tornado.httpclient
import tornado.ioloop
Expand All @@ -16,8 +18,6 @@
)
import web_monitoring.html_diff_render
import web_monitoring.links_diff
import json
import sys

# Map tokens in the REST API to functions in modules.
# The modules do not have to be part of the web_monitoring package.
Expand Down Expand Up @@ -69,7 +69,7 @@ def get(self, differ):
try:
func = self.differs[differ]
except KeyError:
self.send_error(404, reason="Diffing method not found.")
self.send_error(404, reason = f'Unknown diffing method: `{differ}`. You can get a list of supported differs from the `/` endpoint.')
return

# If params repeat, take last one. Decode bytes into unicode strings.
Expand All @@ -80,36 +80,16 @@ def get(self, differ):
b = query_params.pop('b')
except KeyError:
self.send_error(
400, reason="Malformed request. A URL parameter is missing.")
400, reason = 'Malformed request. You must provide a URL as the value for both `a` and `b` query parameters.')
return
# Fetch server response for URLs a and b.
res_a, res_b = yield [client.fetch(a, raise_error=False), client.fetch(b, raise_error=False)]

#Check if the HTTP requests were successfull and handle exeptions
if res_a.error is not None:
try:
res_a.rethrow()
except (ValueError, IOError):
if res_a.code == 599:
self.send_error(
400, reason=str(res_a.error))
else:
self.send_error(
res_a.code, reason=str(res_a.error))
return

if res_b.error is not None:
try:
res_b.rethrow()
except (ValueError, IOError):
if res_b.code == 599:
self.send_error(
400, reason=str(res_b.error))
else:
self.send_error(
res_b.code, reason=str(res_b.error))
return

try:
self.check_response_for_error(res_a)
self.check_response_for_error(res_b)
except tornado.httpclient.HTTPError:
return

# Validate response bytes against hash, if provided.
for query_param, res in zip(('a_hash', 'b_hash'), (res_a, res_b)):
Expand All @@ -122,7 +102,7 @@ def get(self, differ):
actual_hash = hashlib.sha256(res.body).hexdigest()
if actual_hash != expected_hash:
self.send_error(
500, reason="Fetched content does not match hash.")
500, reason = 'Fetched content does not match hash.')
return

# TODO Add caching of fetched URIs.
Expand All @@ -134,11 +114,11 @@ def get(self, differ):
except KeyError:
exceptionMessage = str(sys.exc_info()[1])
exceptionMessage = exceptionMessage[1:-1]
self.send_error(400, reason="Malformed request. "+exceptionMessage)
self.send_error(400, reason = 'Malformed request. {}'.format(exceptionMessage))
return
except UndecodableContentError:
exceptionMessage = str(sys.exc_info()[1])
self.send_error(422, reason=exceptionMessage)
self.send_error(422, reason = exceptionMessage)
return
res['version'] = web_monitoring.__version__
# Echo the client's request unless the differ func has specified
Expand Down Expand Up @@ -166,6 +146,23 @@ def write_error(self, status_code, **kwargs):
self.set_status(response['code'])
self.finish(response)

def check_response_for_error(self, response):
#Check if the HTTP requests were successfull and handle exeptions
if response.error is not None:
try:
response.rethrow()
except (ValueError, IOError):
#Response code == 599 means that no HTTP response was received.
#In this case the error code should become 400 indicating that the error was
#raised because of a bad request parameter.
if response.code == 599:
self.send_error(
400, reason = str(response.error))
else:
self.send_error(
response.code, reason = str(response.error))
raise tornado.httpclient.HTTPError(0)


def _extract_encoding(headers, content):
encoding = None
Expand Down
49 changes: 29 additions & 20 deletions web_monitoring/tests/test_diffing_server_exc_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,47 +9,56 @@ def get_app(self):
app.listen(str(self.get_http_port()))
return

def testInvalidURLaFormat(self):
response = self.fetch('http://localhost:'+str(self.get_http_port())+'/html_token?format=json&include=all&a=example.org&b=https://example.org', method='GET')
def test_invalid_url_a_format(self):
port = self.get_http_port()
response = self.fetch(f'http://localhost:{port}/html_token?format=json&include=all&a=example.org&b=https://example.org')
self.assertEqual(response.code, 400)

def testInvalidURLbFormat(self):
response = self.fetch('http://localhost:'+str(self.get_http_port())+'/html_token?format=json&include=all&a=https://example.org&b=example.org', method='GET')
def test_invalid_url_b_format(self):
port = self.get_http_port()
response = self.fetch(f'http://localhost:{port}/html_token?format=json&include=all&a=https://example.org&b=example.org')
self.assertEqual(response.code, 400)

def testInvalidDiffingMethod(self):
response = self.fetch('http://localhost:'+str(self.get_http_port())+'/non_existing?format=json&include=all&a=example.org&b=https://example.org', method='GET')
def test_invalid_diffing_method(self):
port = self.get_http_port()
response = self.fetch(f'http://localhost:{port}/non_existing?format=json&include=all&a=example.org&b=https://example.org')
self.assertEqual(response.code, 404)

def testMissingURLa(self):
response = self.fetch('http://localhost:'+str(self.get_http_port())+'/html_token?format=json&include=all&b=https://example.org', method='GET')
def test_missing_url_a(self):
port = self.get_http_port()
response = self.fetch(f'http://localhost:{port}/html_token?format=json&include=all&b=https://example.org')
self.assertEqual(response.code, 400)

def testMissingURLb(self):
response = self.fetch('http://localhost:'+str(self.get_http_port())+'/html_token?format=json&include=all&a=https://example.org', method='GET')
def test_missing_url_b(self):
port = self.get_http_port()
response = self.fetch(f'http://localhost:{port}/html_token?format=json&include=all&a=https://example.org')
self.assertEqual(response.code, 400)

def testNotReachableURLa(self):
response = self.fetch('http://localhost:'+str(self.get_http_port())+'/html_token?format=json&include=all&a=https://eeexample.org&b=https://example.org', method='GET')
def test_not_reachable_url_a(self):
port = self.get_http_port()
response = self.fetch(f'http://localhost:{port}/html_token?format=json&include=all&a=https://eeexample.org&b=https://example.org')
self.assertEqual(response.code, 400)

def testNotReachableURLb(self):
response = self.fetch('http://localhost:'+str(self.get_http_port())+'/html_token?format=json&include=all&a=https://example.org&b=https://eeexample.org', method='GET')
def test_not_reachable_url_b(self):
port = self.get_http_port()
response = self.fetch(f'http://localhost:{port}/html_token?format=json&include=all&a=https://example.org&b=https://eeexample.org')
self.assertEqual(response.code, 400)

def testMissingParamsCallerFunc(self):
def test_missing_params_caller_func(self):
response = self.fetch('http://example.org/')
with self.assertRaises(KeyError):
df.caller(mockDiffingMethod, response, response)

def testUndecodableContent(self):
def test_undecodable_content(self):
response = self.fetch('https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt')
with self.assertRaises(UndecodableContentError):
df._decode_body(response,'a',False)

def testFetchUndecodableContent(self):
response = self.fetch('http://localhost:'+str(self.get_http_port())+'/html_token?format=json&include=all&a=https://example.org&b=https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt')
def test_fetch_undecodable_content(self):
port = self.get_http_port()
response = self.fetch(f'http://localhost:{port}/html_token?format=json&include=all&a=https://example.org&b=https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt')
self.assertEqual(response.code, 422)

def mockDiffingMethod(c_body):
return
def mock_diffing_method(c_body):
return

0 comments on commit 3f92aee

Please sign in to comment.