3052: Useless 404 payload for unhandled URLs

yuzisee
david
david
Aug. 20, 2013
What version are you running?
1.7.11


What steps will reproduce the problem?
>>> import rbtools.api.client
>>> r = rbtools.api.client.RBClient('http://my-reviewboard', username='my_username', password='my_password') 
>>> r.get_root().get_user(username='quit()')


What is the expected output?

{u'stat': u'fail', u'err': {u'msg': u'Object does not exist', u'code': 100}}
'{"stat": "fail", "err": {"msg": "Object does not exist", "code": 100}}'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.7/site-packages/rbtools/api/resource.py", line 441, in <lambda>
    self._get_template_request(url, **kwargs)))
  File "/Library/Python/2.7/site-packages/rbtools/api/decorators.py", line 24, in request_method
    *args, **kwargs)
  File "/Library/Python/2.7/site-packages/rbtools/api/transport/sync.py", line 54, in execute_request_method
    return self._execute_request(request)
  File "/Library/Python/2.7/site-packages/rbtools/api/transport/sync.py", line 63, in _execute_request
    rsp = self.server.make_request(request)
  File "/Library/Python/2.7/site-packages/rbtools/api/request.py", line 414, in make_request
    self.process_error(e.code, e.read())
  File "/Library/Python/2.7/site-packages/rbtools/api/request.py", line 387, in process_error
    rsp['err']['msg'])
rbtools.api.errors.APIError: Object does not exist (HTTP 404, API Error 100)


What do you see instead?

'\n<!DOCTYPE html>\n<html lang="en">\n<head>\n  <meta http-equiv="content-type" content="text/html; charset=utf-8">\n  <title>Page not found at /api/users/quit()/</title>\n  <meta name="robots" content="NONE,NOARCHIVE">\n  <style type="text/css">\n    html * { padding:0; margin:0; }\n    body * { padding:10px 20px; }\n    body * * { padding:0; }\n    body { font:small sans-serif; background:#eee; }\n    body>div { border-bottom:1px solid #ddd; }\n    h1 { font-weight:normal; margin-bottom:.4em; }\n    h1 span { font-size:60%; color:#666; font-weight:normal; }\n    table { border:none; border-collapse: collapse; width:100%; }\n    td, th { vertical-align:top; padding:2px 3px; }\n    th { width:12em; text-align:right; color:#666; padding-right:.5em; }\n    #info { background:#f6f6f6; }\n    #info ol { margin: 0.5em 4em; }\n    #info ol li { font-family: monospace; }\n    #summary { background: #ffc; }\n    #explanation { background:#eee; border-bottom: 0px none; }\n  </style>\n</head>\n<body>\n  <div id="summary">\n    <h1>Page not found <span>(404)</span></h1>\n    <table class="meta">\n      <tr>\n        <th>Request Method:</th>\n        <td>GET</td>\n      </tr>\n      <tr>\n        <th>Request URL:</th>\n      <td>http://purpleslam-reviewboard.apple.com/api/users/quit()/</td>\n      </tr>\n    </table>\n  </div>\n  <div id="info">\n    \n      <p>\n      Using the URLconf defined in <code>djblets.util.rooturl</code>,\n      Django tried these URL patterns, in this order:\n      </p>\n      <ol>\n        \n          <li>\n            \n                ^\n                \n            \n                ^admin/extensions/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^admin/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^static\\/(?P&lt;path&gt;.*)$\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^media\\/(?P&lt;path&gt;.*)$\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^js-tests/$\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^account/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^s/(?P&lt;local_site_name&gt;[A-Za-z0-9\\-_.]+)/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^$\n                [name=\'root\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^$\n                [name=\'root-resource\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^default-reviewers/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^extensions/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^hosting-service-accounts/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^repositories/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^groups/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^review-requests/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^search/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^info/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^session/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^users/\n                \n            \n                ^$\n                [name=\'users-resource\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^users/\n                \n            \n                ^(?P&lt;username&gt;[A-Za-z0-9@\\._-]+)/$\n                [name=\'user-resource\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^users/\n                \n            \n                ^(?P&lt;username&gt;[A-Za-z0-9@\\._-]+)/watched/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^api/\n                \n            \n                ^$\n                [name=\'root-resource\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^r/\n                \n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^dashboard/$\n                [name=\'dashboard\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^support/$\n                [name=\'support\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^users/$\n                [name=\'all-users\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^users/(?P&lt;username&gt;[A-Za-z0-9@_\\-\\.]+)/$\n                [name=\'user\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^users/(?P&lt;username&gt;[A-Za-z0-9@_\\-\\.]+)/infobox/$\n                [name=\'user-infobox\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^groups/$\n                [name=\'all-groups\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^groups/(?P&lt;name&gt;[A-Za-z0-9_-]+)/$\n                [name=\'group\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^groups/(?P&lt;name&gt;[A-Za-z0-9_-]+)/members/$\n                [name=\'group_members\']\n            \n          </li>\n        \n          <li>\n            \n                ^\n                \n            \n                ^account/logout/$\n                [name=\'logout\']\n            \n          </li>\n        \n      </ol>\n      <p>The current URL, <code>api/users/quit()/</code>, didn\'t match any of these.</p>\n    \n  </div>\n\n  <div id="explanation">\n    <p>\n      You\'re seeing this error because you have <code>DEBUG = True</code> in\n      your Django settings file. Change that to <code>False</code>, and Django\n      will display a standard 404 page.\n    </p>\n  </div>\n</body>\n</html>\n'
Traceback (most recent call last):
  ...
    rb_client.get_root().get_user(username=u)
  File "/Library/Python/2.7/site-packages/rbtools/api/resource.py", line 441, in <lambda>
    self._get_template_request(url, **kwargs)))
  File "/Library/Python/2.7/site-packages/rbtools/api/decorators.py", line 24, in request_method
    *args, **kwargs)
  File "/Library/Python/2.7/site-packages/rbtools/api/transport/sync.py", line 54, in execute_request_method
    return self._execute_request(request)
  File "/Library/Python/2.7/site-packages/rbtools/api/transport/sync.py", line 63, in _execute_request
    rsp = self.server.make_request(request)
  File "/Library/Python/2.7/site-packages/rbtools/api/request.py", line 414, in make_request
    self.process_error(e.code, e.read())
  File "/Library/Python/2.7/site-packages/rbtools/api/request.py", line 390, in process_error
    raise APIError(http_status, None, None, data)
rbtools.api.errors.APIError: HTTP 404


It looks like Django has actually shut down.

Subsequent attempts to query reviewboard at all will look like:

Traceback (most recent call last):
...
    outgoing_review_query = rb_client.get_root().get_review_requests(status='pending', from_user=from_user)
  File "/Library/Python/2.7/site-packages/rbtools/api/client.py", line 16, in get_root
    return self._transport.get_root(*args, **kwargs)
  File "/Library/Python/2.7/site-packages/rbtools/api/transport/sync.py", line 35, in get_root
    return self._execute_request(HttpRequest(self.server.url))
  File "/Library/Python/2.7/site-packages/rbtools/api/transport/sync.py", line 63, in _execute_request
    rsp = self.server.make_request(request)
  File "/Library/Python/2.7/site-packages/rbtools/api/request.py", line 416, in make_request
    raise ServerInterfaceError("%s" % e.reason)
rbtools.api.errors.ServerInterfaceError: [Errno 60] Operation timed out


What operating system are you using? What browser?

ReviewBoard is running on Ubuntu. I am running RBTools from a Mac running OSX.

Please provide any additional information below.
chipx86
#1 chipx86
Thanks for reporting this.

I'm not able to reproduce it. I set up an environment with 1.7.11 and tried the repro case you provided. I haven't been able to cause this.

Looking at your log output, the 404 result you provided shows a result from Django. The Django 404 happens because the URLs registered don't allow parens, so we never get to a point where we reach any API handler for "quit()" that can throw an API version of a 404, instead throwing only a standard Django 404.

So all that looks correct. Well, "correct." We should probably have some generic thing on /api/* that throws a 404 if nothing else matches.

Now, you end up with an Operation Timed Out. That's very strange. What happens when connecting from a web browser?

Also, what version of RBTools are you using? 

Does that query for get_review_requests work before doing the get_user('quit()') ?
  • +NeedInfo
chipx86
#2 chipx86
  • +Component-API
  • +Useless 404 payload for unhandled URLs
david
#3 david
  • +david
david
#4 david
Pushed the API fix to djblets master (252601c). Thanks!
  • -NeedInfo
    +Fixed