We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Problem with flask_jwt
I'm trying to use the ScoutApp in an flask application using the flask_jwt module, but i recive the below error message when my loggin route are called:

```jsx
[2018-05-30 13:06:20,984] ERROR in __init__: Traceback (most recent call last):

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/flask/app.py", line 1639, in full_dispatch_request
    rv = self.dispatch_request()

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py", line 69, in dispatch_request
    result = view_func(**req.view_args)

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/core/monkey.py", line 213, in __call__
    return self._eop_wrapper_(self.__subject__, *args, **kwargs)

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py", line 119, in tracing_function
    raise e

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py", line 116, in tracing_function
    return original(*args, **kwargs)

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/flask_jwt/__init__.py", line 115, in _default_auth_request_handler
    username = data.get(current_app.config.get('JWT_AUTH_USERNAME_KEY'), None)

AttributeError: 'NoneType' object has no attribute 'get'
 No user info
    Request:   OPTIONS /api/auth
    QueryString: b''
    IP:        127.0.0.1
    Agent:     linux | chrome 66.0.3359.181
    Raw Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
    Payload: b''
    
ERROR:condominio:Traceback (most recent call last):

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/flask/app.py", line 1639, in full_dispatch_request
    rv = self.dispatch_request()

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py", line 69, in dispatch_request
    result = view_func(**req.view_args)

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/core/monkey.py", line 213, in __call__
    return self._eop_wrapper_(self.__subject__, *args, **kwargs)

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py", line 119, in tracing_function
    raise e

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py", line 116, in tracing_function
    return original(*args, **kwargs)

  File "/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/flask_jwt/__init__.py", line 115, in _default_auth_request_handler
    username = data.get(current_app.config.get('JWT_AUTH_USERNAME_KEY'), None)

AttributeError: 'NoneType' object has no attribute 'get'
 No user info
    Request:   OPTIONS /api/auth
    QueryString: b''
    IP:        127.0.0.1
    Agent:     linux | chrome 66.0.3359.181
    Raw Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
    Payload: b''
    
INFO:werkzeug:127.0.0.1 - - [30/May/2018 13:06:23] "OPTIONS /api/auth HTTP/1.1" 500 
```

Debugging the problem, apparently the JWT can't get the request data to do the authentication. For some reason the request lose it the data when ScoutApp are enabled.

The JWT code that breaks:
```python
def _default_auth_request_handler():
    data = request.get_json()
    username = data.get(current_app.config.get('JWT_AUTH_USERNAME_KEY'), None)
    password = data.get(current_app.config.get('JWT_AUTH_PASSWORD_KEY'), None)
    criterion = [username, password, len(data) == 2]

    if not all(criterion):
        raise JWTError('Bad Request', 'Invalid credentials')

    identity = _jwt.authentication_callback(username, password)

    if identity:
        access_token = _jwt.jwt_encode_callback(identity)
        return _jwt.auth_response_callback(access_token, identity)
    else:
        raise JWTError('Bad Request', 'Invalid credentials')
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/scout_apm/flask/__init__.py`
Content:
```
1 from flask import current_app
2 from flask.globals import _request_ctx_stack
3 
4 import scout_apm.core
5 from scout_apm.core.config.config import ScoutConfig
6 from scout_apm.core.tracked_request import TrackedRequest
7 from scout_apm.core.monkey import CallableProxy
8 
9 
10 class ScoutApm(object):
11     def __init__(self, app=None):
12         self.app = app
13         if app is not None:
14             self.init_app(app)
15 
16     def init_app(self, app):
17         app.before_first_request(self.before_first_request)
18         app.before_request(self.process_request)
19         app.after_request(self.process_response)
20 
21         # Monkey-patch the Flask.dispatch_request method
22         app.dispatch_request = self.dispatch_request
23 
24     #############
25     #  Startup  #
26     #############
27 
28     def before_first_request(self):
29         self.extract_flask_settings()
30         scout_apm.core.install()
31 
32     def extract_flask_settings(self):
33         """
34         Copies SCOUT_* settings in the app into Scout's config lookup
35         """
36         configs = {}
37         for name in filter(lambda x: x.startswith('SCOUT_'), current_app.config):
38             value = current_app.config[name]
39             clean_name = name.replace('SCOUT_', '').lower()
40             configs[clean_name] = value
41         ScoutConfig.set(**configs)
42 
43     #############################
44     #  Request Lifecycle hooks  #
45     #############################
46 
47     def dispatch_request(self):
48         """Modified version of Flask.dispatch_request to call process_view."""
49 
50         req = _request_ctx_stack.top.request
51         app = current_app
52 
53         if req.routing_exception is not None:
54             app.raise_routing_exception(req)
55 
56         # The routing rule has some handy attributes to extract how Flask found
57         # this endpoint
58         rule = req.url_rule
59 
60         # Wrap the real view_func
61         view_func = self.wrap_view_func(
62             app,
63             rule,
64             req,
65             app.view_functions[rule.endpoint],
66             req.view_args)
67 
68         return view_func(**req.view_args)
69 
70     def process_request(self):
71         TrackedRequest.instance().start_span(operation='Flask')
72 
73     def wrap_view_func(self, app, rule, req, view_func, view_kwargs):
74         """ This method is called just before the flask view is called.
75         This is done by the dispatch_request method.
76         """
77         operation = view_func.__module__ + '.' + view_func.__name__
78         return self.trace_view_function(
79                         view_func,
80                         ('Controller', {'path': req.path, 'name': operation}))
81 
82     def trace_view_function(self, func, info):
83         try:
84             def tracing_function(original, *args, **kwargs):
85                 entry_type, detail = info
86 
87                 operation = entry_type
88                 if detail['name'] is not None:
89                     operation = operation + '/' + detail['name']
90 
91                 tr = TrackedRequest.instance()
92                 tr.mark_real_request()
93                 span = tr.start_span(operation=operation)
94 
95                 for key in detail:
96                     span.tag(key, detail[key])
97 
98                 # And the custom View stuff
99                 #  request = args[0]
100 
101                 # Extract headers
102                 #  regex = re.compile('^HTTP_')
103                 #  headers = dict((regex.sub('', header), value) for (header, value)
104                 #  in request.META.items() if header.startswith('HTTP_'))
105 
106                 #  span.tag('remote_addr', request.META['REMOTE_ADDR'])
107 
108                 try:
109                     return original(*args, **kwargs)
110                 except Exception as e:
111                     TrackedRequest.instance().tag('error', 'true')
112                     raise e
113                 finally:
114                     TrackedRequest.instance().stop_span()
115 
116             return CallableProxy(func, tracing_function)
117         except Exception as err:
118             # If we can't wrap for any reason, just return the original
119             return func
120 
121     def process_response(self, response):
122         TrackedRequest.instance().stop_span()
123         return response
124 
125
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/scout_apm/flask/__init__.py b/src/scout_apm/flask/__init__.py
--- a/src/scout_apm/flask/__init__.py
+++ b/src/scout_apm/flask/__init__.py
@@ -50,6 +50,10 @@
         req = _request_ctx_stack.top.request
         app = current_app
 
+        # Return flask's default options response. See issue #40
+        if req.method == 'OPTIONS':
+            return app.make_default_options_response()
+
         if req.routing_exception is not None:
             app.raise_routing_exception(req)

{"golden_diff": "diff --git a/src/scout_apm/flask/__init__.py b/src/scout_apm/flask/__init__.py\n--- a/src/scout_apm/flask/__init__.py\n+++ b/src/scout_apm/flask/__init__.py\n@@ -50,6 +50,10 @@\n         req = _request_ctx_stack.top.request\n         app = current_app\n \n+        # Return flask's default options response. See issue #40\n+        if req.method == 'OPTIONS':\n+            return app.make_default_options_response()\n+\n         if req.routing_exception is not None:\n             app.raise_routing_exception(req)\n", "issue": "Problem with flask_jwt\nI'm trying to use the ScoutApp in an flask application using the flask_jwt module, but i recive the below error message when my loggin route are called:\r\n\r\n```jsx\r\n[2018-05-30 13:06:20,984] ERROR in __init__: Traceback (most recent call last):\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/flask/app.py\", line 1639, in full_dispatch_request\r\n    rv = self.dispatch_request()\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py\", line 69, in dispatch_request\r\n    result = view_func(**req.view_args)\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/core/monkey.py\", line 213, in __call__\r\n    return self._eop_wrapper_(self.__subject__, *args, **kwargs)\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py\", line 119, in tracing_function\r\n    raise e\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py\", line 116, in tracing_function\r\n    return original(*args, **kwargs)\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/flask_jwt/__init__.py\", line 115, in _default_auth_request_handler\r\n    username = data.get(current_app.config.get('JWT_AUTH_USERNAME_KEY'), None)\r\n\r\nAttributeError: 'NoneType' object has no attribute 'get'\r\n No user info\r\n    Request:   OPTIONS /api/auth\r\n    QueryString: b''\r\n    IP:        127.0.0.1\r\n    Agent:     linux | chrome 66.0.3359.181\r\n    Raw Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36\r\n    Payload: b''\r\n    \r\nERROR:condominio:Traceback (most recent call last):\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/flask/app.py\", line 1639, in full_dispatch_request\r\n    rv = self.dispatch_request()\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py\", line 69, in dispatch_request\r\n    result = view_func(**req.view_args)\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/core/monkey.py\", line 213, in __call__\r\n    return self._eop_wrapper_(self.__subject__, *args, **kwargs)\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py\", line 119, in tracing_function\r\n    raise e\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/scout_apm/flask/__init__.py\", line 116, in tracing_function\r\n    return original(*args, **kwargs)\r\n\r\n  File \"/home/andreramos/.virtualenvs/back/lib/python3.6/site-packages/flask_jwt/__init__.py\", line 115, in _default_auth_request_handler\r\n    username = data.get(current_app.config.get('JWT_AUTH_USERNAME_KEY'), None)\r\n\r\nAttributeError: 'NoneType' object has no attribute 'get'\r\n No user info\r\n    Request:   OPTIONS /api/auth\r\n    QueryString: b''\r\n    IP:        127.0.0.1\r\n    Agent:     linux | chrome 66.0.3359.181\r\n    Raw Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36\r\n    Payload: b''\r\n    \r\nINFO:werkzeug:127.0.0.1 - - [30/May/2018 13:06:23] \"OPTIONS /api/auth HTTP/1.1\" 500 \r\n```\r\n\r\nDebugging the problem, apparently the JWT can't get the request data to do the authentication. For some reason the request lose it the data when ScoutApp are enabled.\r\n\r\nThe JWT code that breaks:\r\n```python\r\ndef _default_auth_request_handler():\r\n    data = request.get_json()\r\n    username = data.get(current_app.config.get('JWT_AUTH_USERNAME_KEY'), None)\r\n    password = data.get(current_app.config.get('JWT_AUTH_PASSWORD_KEY'), None)\r\n    criterion = [username, password, len(data) == 2]\r\n\r\n    if not all(criterion):\r\n        raise JWTError('Bad Request', 'Invalid credentials')\r\n\r\n    identity = _jwt.authentication_callback(username, password)\r\n\r\n    if identity:\r\n        access_token = _jwt.jwt_encode_callback(identity)\r\n        return _jwt.auth_response_callback(access_token, identity)\r\n    else:\r\n        raise JWTError('Bad Request', 'Invalid credentials')\r\n```\r\n\n", "before_files": [{"content": "from flask import current_app\nfrom flask.globals import _request_ctx_stack\n\nimport scout_apm.core\nfrom scout_apm.core.config.config import ScoutConfig\nfrom scout_apm.core.tracked_request import TrackedRequest\nfrom scout_apm.core.monkey import CallableProxy\n\n\nclass ScoutApm(object):\n    def __init__(self, app=None):\n        self.app = app\n        if app is not None:\n            self.init_app(app)\n\n    def init_app(self, app):\n        app.before_first_request(self.before_first_request)\n        app.before_request(self.process_request)\n        app.after_request(self.process_response)\n\n        # Monkey-patch the Flask.dispatch_request method\n        app.dispatch_request = self.dispatch_request\n\n    #############\n    #  Startup  #\n    #############\n\n    def before_first_request(self):\n        self.extract_flask_settings()\n        scout_apm.core.install()\n\n    def extract_flask_settings(self):\n        \"\"\"\n        Copies SCOUT_* settings in the app into Scout's config lookup\n        \"\"\"\n        configs = {}\n        for name in filter(lambda x: x.startswith('SCOUT_'), current_app.config):\n            value = current_app.config[name]\n            clean_name = name.replace('SCOUT_', '').lower()\n            configs[clean_name] = value\n        ScoutConfig.set(**configs)\n\n    #############################\n    #  Request Lifecycle hooks  #\n    #############################\n\n    def dispatch_request(self):\n        \"\"\"Modified version of Flask.dispatch_request to call process_view.\"\"\"\n\n        req = _request_ctx_stack.top.request\n        app = current_app\n\n        if req.routing_exception is not None:\n            app.raise_routing_exception(req)\n\n        # The routing rule has some handy attributes to extract how Flask found\n        # this endpoint\n        rule = req.url_rule\n\n        # Wrap the real view_func\n        view_func = self.wrap_view_func(\n            app,\n            rule,\n            req,\n            app.view_functions[rule.endpoint],\n            req.view_args)\n\n        return view_func(**req.view_args)\n\n    def process_request(self):\n        TrackedRequest.instance().start_span(operation='Flask')\n\n    def wrap_view_func(self, app, rule, req, view_func, view_kwargs):\n        \"\"\" This method is called just before the flask view is called.\n        This is done by the dispatch_request method.\n        \"\"\"\n        operation = view_func.__module__ + '.' + view_func.__name__\n        return self.trace_view_function(\n                        view_func,\n                        ('Controller', {'path': req.path, 'name': operation}))\n\n    def trace_view_function(self, func, info):\n        try:\n            def tracing_function(original, *args, **kwargs):\n                entry_type, detail = info\n\n                operation = entry_type\n                if detail['name'] is not None:\n                    operation = operation + '/' + detail['name']\n\n                tr = TrackedRequest.instance()\n                tr.mark_real_request()\n                span = tr.start_span(operation=operation)\n\n                for key in detail:\n                    span.tag(key, detail[key])\n\n                # And the custom View stuff\n                #  request = args[0]\n\n                # Extract headers\n                #  regex = re.compile('^HTTP_')\n                #  headers = dict((regex.sub('', header), value) for (header, value)\n                #  in request.META.items() if header.startswith('HTTP_'))\n\n                #  span.tag('remote_addr', request.META['REMOTE_ADDR'])\n\n                try:\n                    return original(*args, **kwargs)\n                except Exception as e:\n                    TrackedRequest.instance().tag('error', 'true')\n                    raise e\n                finally:\n                    TrackedRequest.instance().stop_span()\n\n            return CallableProxy(func, tracing_function)\n        except Exception as err:\n            # If we can't wrap for any reason, just return the original\n            return func\n\n    def process_response(self, response):\n        TrackedRequest.instance().stop_span()\n        return response\n\n", "path": "src/scout_apm/flask/__init__.py"}], "after_files": [{"content": "from flask import current_app\nfrom flask.globals import _request_ctx_stack\n\nimport scout_apm.core\nfrom scout_apm.core.config.config import ScoutConfig\nfrom scout_apm.core.tracked_request import TrackedRequest\nfrom scout_apm.core.monkey import CallableProxy\n\n\nclass ScoutApm(object):\n    def __init__(self, app=None):\n        self.app = app\n        if app is not None:\n            self.init_app(app)\n\n    def init_app(self, app):\n        app.before_first_request(self.before_first_request)\n        app.before_request(self.process_request)\n        app.after_request(self.process_response)\n\n        # Monkey-patch the Flask.dispatch_request method\n        app.dispatch_request = self.dispatch_request\n\n    #############\n    #  Startup  #\n    #############\n\n    def before_first_request(self):\n        self.extract_flask_settings()\n        scout_apm.core.install()\n\n    def extract_flask_settings(self):\n        \"\"\"\n        Copies SCOUT_* settings in the app into Scout's config lookup\n        \"\"\"\n        configs = {}\n        for name in filter(lambda x: x.startswith('SCOUT_'), current_app.config):\n            value = current_app.config[name]\n            clean_name = name.replace('SCOUT_', '').lower()\n            configs[clean_name] = value\n        ScoutConfig.set(**configs)\n\n    #############################\n    #  Request Lifecycle hooks  #\n    #############################\n\n    def dispatch_request(self):\n        \"\"\"Modified version of Flask.dispatch_request to call process_view.\"\"\"\n\n        req = _request_ctx_stack.top.request\n        app = current_app\n\n        # Return flask's default options response. See issue #40\n        if req.method == 'OPTIONS':\n            return app.make_default_options_response()\n\n        if req.routing_exception is not None:\n            app.raise_routing_exception(req)\n\n        # The routing rule has some handy attributes to extract how Flask found\n        # this endpoint\n        rule = req.url_rule\n\n        # Wrap the real view_func\n        view_func = self.wrap_view_func(\n            app,\n            rule,\n            req,\n            app.view_functions[rule.endpoint],\n            req.view_args)\n\n        return view_func(**req.view_args)\n\n    def process_request(self):\n        TrackedRequest.instance().start_span(operation='Flask')\n\n    def wrap_view_func(self, app, rule, req, view_func, view_kwargs):\n        \"\"\" This method is called just before the flask view is called.\n        This is done by the dispatch_request method.\n        \"\"\"\n        operation = view_func.__module__ + '.' + view_func.__name__\n        return self.trace_view_function(\n                        view_func,\n                        ('Controller', {'path': req.path, 'name': operation}))\n\n    def trace_view_function(self, func, info):\n        try:\n            def tracing_function(original, *args, **kwargs):\n                entry_type, detail = info\n\n                operation = entry_type\n                if detail['name'] is not None:\n                    operation = operation + '/' + detail['name']\n\n                tr = TrackedRequest.instance()\n                tr.mark_real_request()\n                span = tr.start_span(operation=operation)\n\n                for key in detail:\n                    span.tag(key, detail[key])\n\n                # And the custom View stuff\n                #  request = args[0]\n\n                # Extract headers\n                #  regex = re.compile('^HTTP_')\n                #  headers = dict((regex.sub('', header), value) for (header, value)\n                #  in request.META.items() if header.startswith('HTTP_'))\n\n                #  span.tag('remote_addr', request.META['REMOTE_ADDR'])\n\n                try:\n                    return original(*args, **kwargs)\n                except Exception as e:\n                    TrackedRequest.instance().tag('error', 'true')\n                    raise e\n                finally:\n                    TrackedRequest.instance().stop_span()\n\n            return CallableProxy(func, tracing_function)\n        except Exception as err:\n            # If we can't wrap for any reason, just return the original\n            return func\n\n    def process_response(self, response):\n        TrackedRequest.instance().stop_span()\n        return response\n\n", "path": "src/scout_apm/flask/__init__.py"}]}