debughelpers.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. # -*- coding: utf-8 -*-
  2. """
  3. flask.debughelpers
  4. ~~~~~~~~~~~~~~~~~~
  5. Various helpers to make the development experience better.
  6. :copyright: (c) 2011 by Armin Ronacher.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. from ._compat import implements_to_string
  10. class UnexpectedUnicodeError(AssertionError, UnicodeError):
  11. """Raised in places where we want some better error reporting for
  12. unexpected unicode or binary data.
  13. """
  14. @implements_to_string
  15. class DebugFilesKeyError(KeyError, AssertionError):
  16. """Raised from request.files during debugging. The idea is that it can
  17. provide a better error message than just a generic KeyError/BadRequest.
  18. """
  19. def __init__(self, request, key):
  20. form_matches = request.form.getlist(key)
  21. buf = ['You tried to access the file "%s" in the request.files '
  22. 'dictionary but it does not exist. The mimetype for the request '
  23. 'is "%s" instead of "multipart/form-data" which means that no '
  24. 'file contents were transmitted. To fix this error you should '
  25. 'provide enctype="multipart/form-data" in your form.' %
  26. (key, request.mimetype)]
  27. if form_matches:
  28. buf.append('\n\nThe browser instead transmitted some file names. '
  29. 'This was submitted: %s' % ', '.join('"%s"' % x
  30. for x in form_matches))
  31. self.msg = ''.join(buf)
  32. def __str__(self):
  33. return self.msg
  34. class FormDataRoutingRedirect(AssertionError):
  35. """This exception is raised by Flask in debug mode if it detects a
  36. redirect caused by the routing system when the request method is not
  37. GET, HEAD or OPTIONS. Reasoning: form data will be dropped.
  38. """
  39. def __init__(self, request):
  40. exc = request.routing_exception
  41. buf = ['A request was sent to this URL (%s) but a redirect was '
  42. 'issued automatically by the routing system to "%s".'
  43. % (request.url, exc.new_url)]
  44. # In case just a slash was appended we can be extra helpful
  45. if request.base_url + '/' == exc.new_url.split('?')[0]:
  46. buf.append(' The URL was defined with a trailing slash so '
  47. 'Flask will automatically redirect to the URL '
  48. 'with the trailing slash if it was accessed '
  49. 'without one.')
  50. buf.append(' Make sure to directly send your %s-request to this URL '
  51. 'since we can\'t make browsers or HTTP clients redirect '
  52. 'with form data reliably or without user interaction.' %
  53. request.method)
  54. buf.append('\n\nNote: this exception is only raised in debug mode')
  55. AssertionError.__init__(self, ''.join(buf).encode('utf-8'))
  56. def attach_enctype_error_multidict(request):
  57. """Since Flask 0.8 we're monkeypatching the files object in case a
  58. request is detected that does not use multipart form data but the files
  59. object is accessed.
  60. """
  61. oldcls = request.files.__class__
  62. class newcls(oldcls):
  63. def __getitem__(self, key):
  64. try:
  65. return oldcls.__getitem__(self, key)
  66. except KeyError as e:
  67. if key not in request.form:
  68. raise
  69. raise DebugFilesKeyError(request, key)
  70. newcls.__name__ = oldcls.__name__
  71. newcls.__module__ = oldcls.__module__
  72. request.files.__class__ = newcls