Skip to content

Commit 20304b0

Browse files
committed
/resources/ handle bytes in item from spider
ScrapyJSONEncoder should not crash if there are bytes in item generated by spider. Also added error handling, we should not hang when there is something unexpected in API, just return to 500 and go on.
1 parent 415961e commit 20304b0

File tree

3 files changed

+18
-6
lines changed

3 files changed

+18
-6
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ testing_scripts*
3333

3434
# sphinx
3535
docs/build/*
36+
.python-version

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ Scrapy>=1.0.0
22
service-identity>=1.0.0
33
demjson==2.2.4
44
six==1.12.0
5+
jmespath==0.10.0
6+
pyasn1==0.4.8

scrapyrt/resources.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,18 @@
1212
from .utils import extract_scrapy_request_args, to_bytes
1313

1414

15+
class AdaptedScrapyJSONEncoder(ScrapyJSONEncoder):
16+
def default(self, o):
17+
if isinstance(o, bytes):
18+
return o.decode('utf8')
19+
else:
20+
return super().default(o)
21+
22+
1523
# XXX super() calls won't work wihout object mixin in Python 2
1624
# maybe this can be removed at some point?
1725
class ServiceResource(resource.Resource, object):
18-
json_encoder = ScrapyJSONEncoder()
26+
json_encoder = AdaptedScrapyJSONEncoder()
1927

2028
def __init__(self, root=None):
2129
resource.Resource.__init__(self)
@@ -69,7 +77,7 @@ def handle_error(self, exception_or_failure, request):
6977
else:
7078
request.setResponseCode(500)
7179
if request.code == 500:
72-
log.err(str(exception_or_failure))
80+
log.err(f'Error when rendering response: "{exception}"')
7381
return self.format_error_response(exception, request)
7482

7583
def format_error_response(self, exception, request):
@@ -78,17 +86,18 @@ def format_error_response(self, exception, request):
7886
# and they fail on str(exception) call.
7987
msg = exception.message if hasattr(exception, 'message') else str(exception)
8088

81-
return {
89+
encoded_error_response = self.json_encoder.encode({
8290
"status": "error",
8391
"message": msg,
8492
"code": request.code
85-
}
93+
}) + "\n"
94+
return encoded_error_response.encode('utf8')
8695

8796
def render_object(self, obj, request):
8897
try:
8998
r = self.json_encoder.encode(obj) + "\n"
90-
except Exception as e:
91-
return self.json_encoder.encode(self.handle_error(e, request)).encode('utf8')
99+
except Exception as exc:
100+
return self.handle_error(exc, request)
92101

93102
request.setHeader('Content-Type', 'application/json')
94103
request.setHeader('Access-Control-Allow-Origin', '*')

0 commit comments

Comments
 (0)