Repository: rollbar/pyrollbar

Issue:
include_request_body not working for Flask
When you pass `include_request_body=False` (which is the default), Rollbar will still send the body.

Discussion:
@moodh: We just ran into the same issue. Looking at the implementation:

```
def _build_werkzeug_request_data(request):
    request_data = {
        'url': request.url,
        'GET': dict(request.args),
        'POST': dict(request.form),
        'user_ip': _extract_user_ip(request),
        'headers': dict(request.headers),
        'method': request.method,
        'files_keys': list(request.files.keys()),
    }

    try:
        if request.json:
            request_data['body'] = request.json
    except Exception:
        pass

    return request_data
```

This doesn't contain the needed setting check. Simply adding it:
```
def _build_werkzeug_request_data(request):
    request_data = {
        'url': request.url,
        'GET': dict(request.args),
        'POST': dict(request.form),
        'user_ip': _extract_user_ip(request),
        'headers': dict(request.headers),
        'method': request.method,
        'files_keys': list(request.files.keys()),
    }

    if SETTINGS['include_request_body']:
        try:
            if request.json:
                request_data['body'] = request.json
        except Exception:
            pass

    return request_data
```

Fixes the issue. We'd appreciate this being updated!@javamo: @moodh This is my temporal fix in case it's helpful for you:
```python
import os
import rollbar
import rollbar.contrib.flask
from flask import request, got_request_exception


@app.before_first_request
def init_rollbar():
    """Initialize Rollbar
    """
    rollbar_environment = os.environ.get('ROLLBAR_ENVIRONMENT')
    include_request_body = os.environ.get('ROLLBAR_INCLUDE_REQUEST_BODY')
    if rollbar_environment in ('production', 'testing', 'demo'):
        rollbar.init(
            os.environ.get('ROLLBAR_ACCESS_TOKEN'),
            rollbar_environment,
            root=os.path.dirname(os.path.realpath(__file__)),
            allow_logging_basic_config=False)

        # Send exceptions from `app` to rollbar, using flask's signal system
        if include_request_body:
            got_request_exception.connect(rollbar.contrib.flask.report_exception, app)
        else:
            got_request_exception.connect(report_exc_without_body, app)


def report_exc_without_body(sender, exception, **extra):
    # TODO: Temporal fix to avoid sending the body
    # https://github.com/rollbar/pyrollbar/issues/344
    rollbar.report_exc_info(request=request, payload_data={
        'request': {'body': None}
    })
```@moodh: Thanks, here's how I removed the data from our end, but I haven't fully tested it yet :)
```
def initialize_rollbar(app):
    def _payload_handler(payload):
        try:
            payload['data']['request']['body'] = {}
        except Exception:
            pass

        return payload

    rollbar.init(...)

    rollbar.events.add_payload_handler(_payload_handler)
```

Solution patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f13a2b3..bc1a0a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,10 @@
 
 The change log is also available on the [GitHub Releases Page](https://github.com/rollbar/pyrollbar/releases).
 
+**1.1.2**
+
+Fixed build missing entrypoints for pyramid and cli in [#471](https://github.com/rollbar/pyrollbar/pull/471)
+
 **1.1.1**
 
 Fixed #465 httpx 0.28.0 not compatible with pyrollbar by @danielmorell in [#466](https://github.com/rollbar/pyrollbar/pull/466)
diff --git a/pyproject.toml b/pyproject.toml
index db92b1b..ec44a06 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -53,3 +53,9 @@ build-backend = "setuptools.build_meta"
 
 [tool.setuptools.dynamic]
 version = {attr = "rollbar.__version__"}
+
+[project.scripts]
+rollbar = "rollbar.cli:main"
+
+[project.entry-points."paste.filter_app_factory"]
+pyramid = "rollbar.contrib.pyramid:create_rollbar_middleware"
diff --git a/rollbar/__init__.py b/rollbar/__init__.py
index 2a3a62d..d4dfea2 100644
--- a/rollbar/__init__.py
+++ b/rollbar/__init__.py
@@ -24,7 +24,7 @@ import requests
 from rollbar.lib import events, filters, dict_merge, transport, defaultJSONEncode
 
 
-__version__ = '1.1.1'
+__version__ = '1.1.2'
 __log_name__ = 'rollbar'
 log = logging.getLogger(__log_name__)
 
@@ -268,6 +268,7 @@ SETTINGS = {
     'environment': 'production',
     'exception_level_filters': [],
     'root': None,  # root path to your code
+    'host': None,  # custom hostname of the current host
     'branch': None,  # git branch name
     'code_version': None,
     # 'blocking', 'thread' (default), 'async', 'agent', 'tornado', 'gae', 'twisted', 'httpx' or 'thread_pool'
@@ -1264,11 +1265,12 @@ def _build_werkzeug_request_data(request):
         'files_keys': list(request.files.keys()),
     }
 
-    try:
-        if request.json:
-            request_data['body'] = request.json
-    except Exception:
-        pass
+    if SETTINGS['include_request_body']:
+        try:
+            if request.json:
+                request_data['body'] = request.json
+        except Exception:
+            pass
 
     return request_data
 
@@ -1296,13 +1298,15 @@ def _build_bottle_request_data(request):
         'GET': dict(request.query)
     }
 
-    if request.json:
-        try:
-            request_data['body'] = request.body.getvalue()
-        except:
-            pass
-    else:
-        request_data['POST'] = dict(request.forms)
+
+    if SETTINGS['include_request_body']:
+        if request.json:
+            try:
+                request_data['body'] = request.body.getvalue()
+            except:
+                pass
+        else:
+            request_data['POST'] = dict(request.forms)
 
     return request_data
 
@@ -1316,13 +1320,14 @@ def _build_sanic_request_data(request):
         'GET': dict(request.args)
     }
 
-    if request.json:
-        try:
-            request_data['body'] = request.json
-        except:
-            pass
-    else:
-        request_data['POST'] = request.form
+    if SETTINGS['include_request_body']:
+        if request.json:
+            try:
+                request_data['body'] = request.json
+            except:
+                pass
+        else:
+            request_data['POST'] = request.form
 
     return request_data
 
@@ -1353,16 +1358,17 @@ def _build_wsgi_request_data(request):
 
     request_data['headers'] = _extract_wsgi_headers(request.items())
 
-    try:
-        length = int(request.get('CONTENT_LENGTH', 0))
-    except ValueError:
-        length = 0
-    input = request.get('wsgi.input')
-    if length and input and hasattr(input, 'seek') and hasattr(input, 'tell'):
-        pos = input.tell()
-        input.seek(0, 0)
-        request_data['body'] = input.read(length)
-        input.seek(pos, 0)
+    if SETTINGS['include_request_body']:
+        try:
+            length = int(request.get('CONTENT_LENGTH', 0))
+        except ValueError:
+            length = 0
+        input = request.get('wsgi.input')
+        if length and input and hasattr(input, 'seek') and hasattr(input, 'tell'):
+            pos = input.tell()
+            input.seek(0, 0)
+            request_data['body'] = input.read(length)
+            input.seek(pos, 0)
 
     return request_data
 
@@ -1447,8 +1453,9 @@ def _build_server_data():
     Returns a dictionary containing information about the server environment.
     """
     # server environment
+    host = SETTINGS.get('host') or socket.gethostname()
     server_data = {
-        'host': socket.gethostname(),
+        'host': host,
         'pid': os.getpid()
     }
 


Test patch:
diff --git a/rollbar/test/flask_tests/test_flask.py b/rollbar/test/flask_tests/test_flask.py
index b97227b..43874bc 100644
--- a/rollbar/test/flask_tests/test_flask.py
+++ b/rollbar/test/flask_tests/test_flask.py
@@ -82,6 +82,7 @@ if ALLOWED_PYTHON_VERSION and FLASK_INSTALLED:
 
         @mock.patch('rollbar.send_payload')
         def test_uncaught(self, send_payload):
+            rollbar.SETTINGS['include_request_body'] = True
             resp = self.client.get('/cause_error?foo=bar',
                 headers={'X-Real-Ip': '1.2.3.4', 'User-Agent': 'Flask Test'})
             self.assertEqual(resp.status_code, 500)
@@ -115,6 +116,7 @@ if ALLOWED_PYTHON_VERSION and FLASK_INSTALLED:
 
         @mock.patch('rollbar.send_payload')
         def test_uncaught_json_request(self, send_payload):
+            rollbar.SETTINGS['include_request_body'] = True
             json_body = {"hello": "world"}
             json_body_str = json.dumps(json_body)
             resp = self.client.post('/cause_error', data=json_body_str,
@@ -178,3 +180,20 @@ if ALLOWED_PYTHON_VERSION and FLASK_INSTALLED:
 
             rollbar.SETTINGS['capture_email'] = True
             rollbar.SETTINGS['capture_username'] = True
+
+        @mock.patch('rollbar.send_payload')
+        def test_uncaught_no_body(self, send_payload):
+            rollbar.SETTINGS['include_request_body'] = False
+
+            resp = self.client.get('/cause_error?foo=bar',
+                headers={'X-Real-Ip': '1.2.3.4', 'User-Agent': 'Flask Test'})
+            self.assertEqual(resp.status_code, 500)
+
+            self.assertEqual(send_payload.called, True)
+            payload = send_payload.call_args[0][0]
+            data = payload['data']
+
+            self.assertIn('request', data)
+            self.assertNotIn('body', data['request'])
+
+            rollbar.SETTINGS['include_request_body'] = True
diff --git a/rollbar/test/test_rollbar.py b/rollbar/test/test_rollbar.py
index 29daf3d..19a5e55 100644
--- a/rollbar/test/test_rollbar.py
+++ b/rollbar/test/test_rollbar.py
@@ -74,18 +74,21 @@ class RollbarTest(BaseTest):
         self.assertIn('argv', server_data)
         self.assertNotIn('branch', server_data)
         self.assertNotIn('root', server_data)
+        self.assertGreater(len(server_data['host']), 2)
 
+        rollbar.SETTINGS['host'] = 'test-host'
         rollbar.SETTINGS['branch'] = 'master'
         rollbar.SETTINGS['root'] = '/home/test/'
 
         server_data = rollbar._build_server_data()
 
-        self.assertIn('host', server_data)
         self.assertIn('argv', server_data)
+        self.assertEqual(server_data['host'], 'test-host')
         self.assertEqual(server_data['branch'], 'master')
         self.assertEqual(server_data['root'], '/home/test/')
 
     def test_wsgi_request_data(self):
+        rollbar.SETTINGS['include_request_body'] = True
         request = {
             'CONTENT_LENGTH': str(len('body body body')),
             'CONTENT_TYPE': '',
@@ -118,6 +121,20 @@ class RollbarTest(BaseTest):
         self.assertDictEqual(data['GET'], {'format': 'json', 'param1': 'value1', 'param2': 'value2'})
         self.assertDictEqual(data['headers'], {'Connection': 'close', 'Host': 'example.com', 'User-Agent': 'Agent'})
 
+    def test_wsgi_request_data_no_body(self):
+        rollbar.SETTINGS['include_request_body'] = False
+        request = {
+            'CONTENT_LENGTH': str(len('body body body')),
+            'REMOTE_ADDR': '127.0.0.1',
+            'SERVER_NAME': 'example.com',
+            'SERVER_PORT': '80',
+            'wsgi.input': StringIO('body body body'),
+            'wsgi.url_scheme': 'http',
+        }
+        data = rollbar._build_wsgi_request_data(request)
+        self.assertNotIn('body', data)
+        rollbar.SETTINGS['include_request_body'] = True
+
     def test_starlette_request_data(self):
         try:
             from starlette.requests import Request