We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
endpoint in error-page-embed.js does not respect system.url-prefix
## Important Details

How are you running Sentry?

* [x ] On-Premise docker [9.1.1]
## Description

using raven-js with angular works as expected to capture exceptions.
when reporting errors we get the wrong endpoint from the sentry instance

javascript snippet:
```js
Raven
  .config(`https://${environment.sentryKey}@MY_INSTANCE/PROJECT_NUMBER`,
    {
      environment: environment.production ? 'prod' : 'dev',
      release: versions.version
    }
  )
  .install();

export class RavenErrorHandler implements ErrorHandler {
  handleError(error: any): void {
    const err = error.originalError || error;
    console.error(err);
    Raven.captureException(err);
    if (true) {
      // fetches error-page-embed.js from sentry instance with wrong endpoint (docker endpoint)
      Raven.showReportDialog();
    }
  }
}
```

this end point is set here: https://github.com/getsentry/sentry/blob/master/src/sentry/web/frontend/error_page_embed.py
```python
# using request.build_absolute_uri() instead of the value of system.url-prefix 'endpoint':  
 
mark_safe('*/' + json.dumps(request.build_absolute_uri()) + ';/*'),
```

## Steps to Reproduce

web:9000 is the hostname of the docker container
![screenshot3](https://user-images.githubusercontent.com/1331762/61046390-4c9d7c00-a3dd-11e9-9554-0ab5b09c72d2.png)

### What you expected to happen

system.url-prefix in config.yaml: error-page-embed.js should be respected


cc/ @max-wittig


--- 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/sentry/web/frontend/error_page_embed.py`
Content:
```
1 from __future__ import absolute_import
2 
3 import six
4 
5 from django import forms
6 from django.db import IntegrityError, transaction
7 from django.http import HttpResponse
8 from django.views.generic import View
9 from django.template.loader import render_to_string
10 from django.utils import timezone
11 from django.utils.safestring import mark_safe
12 from django.utils.translation import ugettext_lazy as _
13 from django.views.decorators.csrf import csrf_exempt
14 
15 from sentry import eventstore
16 from sentry.models import Event, ProjectKey, ProjectOption, UserReport
17 from sentry.web.helpers import render_to_response
18 from sentry.signals import user_feedback_received
19 from sentry.utils import json
20 from sentry.utils.http import is_valid_origin, origin_from_request
21 from sentry.utils.validators import normalize_event_id
22 
23 GENERIC_ERROR = _("An unknown error occurred while submitting your report. Please try again.")
24 FORM_ERROR = _("Some fields were invalid. Please correct the errors and try again.")
25 SENT_MESSAGE = _("Your feedback has been sent. Thank you!")
26 
27 DEFAULT_TITLE = _("It looks like we're having issues.")
28 DEFAULT_SUBTITLE = _("Our team has been notified.")
29 DEFAULT_SUBTITLE2 = _("If you'd like to help, tell us what happened below.")
30 
31 DEFAULT_NAME_LABEL = _("Name")
32 DEFAULT_EMAIL_LABEL = _("Email")
33 DEFAULT_COMMENTS_LABEL = _("What happened?")
34 
35 DEFAULT_CLOSE_LABEL = _("Close")
36 DEFAULT_SUBMIT_LABEL = _("Submit Crash Report")
37 
38 DEFAULT_OPTIONS = {
39     "title": DEFAULT_TITLE,
40     "subtitle": DEFAULT_SUBTITLE,
41     "subtitle2": DEFAULT_SUBTITLE2,
42     "labelName": DEFAULT_NAME_LABEL,
43     "labelEmail": DEFAULT_EMAIL_LABEL,
44     "labelComments": DEFAULT_COMMENTS_LABEL,
45     "labelClose": DEFAULT_CLOSE_LABEL,
46     "labelSubmit": DEFAULT_SUBMIT_LABEL,
47     "errorGeneric": GENERIC_ERROR,
48     "errorFormEntry": FORM_ERROR,
49     "successMessage": SENT_MESSAGE,
50 }
51 
52 
53 class UserReportForm(forms.ModelForm):
54     name = forms.CharField(
55         max_length=128, widget=forms.TextInput(attrs={"placeholder": _("Jane Doe")})
56     )
57     email = forms.EmailField(
58         max_length=75,
59         widget=forms.TextInput(attrs={"placeholder": _("jane@example.com"), "type": "email"}),
60     )
61     comments = forms.CharField(
62         widget=forms.Textarea(attrs={"placeholder": _("I clicked on 'X' and then hit 'Confirm'")})
63     )
64 
65     class Meta:
66         model = UserReport
67         fields = ("name", "email", "comments")
68 
69 
70 class ErrorPageEmbedView(View):
71     def _get_project_key(self, request):
72         try:
73             dsn = request.GET["dsn"]
74         except KeyError:
75             return
76 
77         try:
78             key = ProjectKey.from_dsn(dsn)
79         except ProjectKey.DoesNotExist:
80             return
81 
82         return key
83 
84     def _get_origin(self, request):
85         return origin_from_request(request)
86 
87     def _smart_response(self, request, context=None, status=200):
88         json_context = json.dumps(context or {})
89         accept = request.META.get("HTTP_ACCEPT") or ""
90         if "text/javascript" in accept:
91             content_type = "text/javascript"
92             content = ""
93         else:
94             content_type = "application/json"
95             content = json_context
96         response = HttpResponse(content, status=status, content_type=content_type)
97         response["Access-Control-Allow-Origin"] = request.META.get("HTTP_ORIGIN", "")
98         response["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS"
99         response["Access-Control-Max-Age"] = "1000"
100         response["Access-Control-Allow-Headers"] = "Content-Type, Authorization, X-Requested-With"
101         response["Vary"] = "Accept"
102         if content == "" and context:
103             response["X-Sentry-Context"] = json_context
104         return response
105 
106     @csrf_exempt
107     def dispatch(self, request):
108         try:
109             event_id = request.GET["eventId"]
110         except KeyError:
111             return self._smart_response(
112                 request, {"eventId": "Missing or invalid parameter."}, status=400
113             )
114 
115         normalized_event_id = normalize_event_id(event_id)
116         if normalized_event_id:
117             event_id = normalized_event_id
118         elif event_id:
119             return self._smart_response(
120                 request, {"eventId": "Missing or invalid parameter."}, status=400
121             )
122 
123         key = self._get_project_key(request)
124         if not key:
125             return self._smart_response(
126                 request, {"dsn": "Missing or invalid parameter."}, status=404
127             )
128 
129         origin = self._get_origin(request)
130         if not is_valid_origin(origin, key.project):
131             return self._smart_response(request, status=403)
132 
133         if request.method == "OPTIONS":
134             return self._smart_response(request)
135 
136         # customization options
137         options = DEFAULT_OPTIONS.copy()
138         for name in six.iterkeys(options):
139             if name in request.GET:
140                 options[name] = six.text_type(request.GET[name])
141 
142         # TODO(dcramer): since we cant use a csrf cookie we should at the very
143         # least sign the request / add some kind of nonce
144         initial = {"name": request.GET.get("name"), "email": request.GET.get("email")}
145 
146         form = UserReportForm(request.POST if request.method == "POST" else None, initial=initial)
147         if form.is_valid():
148             # TODO(dcramer): move this to post to the internal API
149             report = form.save(commit=False)
150             report.project = key.project
151             report.event_id = event_id
152 
153             event = eventstore.get_event_by_id(report.project.id, report.event_id)
154 
155             if event is not None:
156                 Event.objects.bind_nodes([event])
157                 report.environment = event.get_environment()
158                 report.group = event.group
159 
160             try:
161                 with transaction.atomic():
162                     report.save()
163             except IntegrityError:
164                 # There was a duplicate, so just overwrite the existing
165                 # row with the new one. The only way this ever happens is
166                 # if someone is messing around with the API, or doing
167                 # something wrong with the SDK, but this behavior is
168                 # more reasonable than just hard erroring and is more
169                 # expected.
170                 UserReport.objects.filter(project=report.project, event_id=report.event_id).update(
171                     name=report.name,
172                     email=report.email,
173                     comments=report.comments,
174                     date_added=timezone.now(),
175                 )
176 
177             else:
178                 if report.group:
179                     report.notify()
180 
181             user_feedback_received.send(project=report.project, group=report.group, sender=self)
182 
183             return self._smart_response(request)
184         elif request.method == "POST":
185             return self._smart_response(request, {"errors": dict(form.errors)}, status=400)
186 
187         show_branding = (
188             ProjectOption.objects.get_value(
189                 project=key.project, key="feedback:branding", default="1"
190             )
191             == "1"
192         )
193 
194         template = render_to_string(
195             "sentry/error-page-embed.html",
196             {
197                 "form": form,
198                 "show_branding": show_branding,
199                 "title": options["title"],
200                 "subtitle": options["subtitle"],
201                 "subtitle2": options["subtitle2"],
202                 "name_label": options["labelName"],
203                 "email_label": options["labelEmail"],
204                 "comments_label": options["labelComments"],
205                 "submit_label": options["labelSubmit"],
206                 "close_label": options["labelClose"],
207             },
208         )
209 
210         context = {
211             "endpoint": mark_safe("*/" + json.dumps(request.build_absolute_uri()) + ";/*"),
212             "template": mark_safe("*/" + json.dumps(template) + ";/*"),
213             "strings": json.dumps_htmlsafe(
214                 {
215                     "generic_error": six.text_type(options["errorGeneric"]),
216                     "form_error": six.text_type(options["errorFormEntry"]),
217                     "sent_message": six.text_type(options["successMessage"]),
218                 }
219             ),
220         }
221 
222         return render_to_response(
223             "sentry/error-page-embed.js", context, request, content_type="text/javascript"
224         )
225
```
--- 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/sentry/web/frontend/error_page_embed.py b/src/sentry/web/frontend/error_page_embed.py
--- a/src/sentry/web/frontend/error_page_embed.py
+++ b/src/sentry/web/frontend/error_page_embed.py
@@ -17,7 +17,7 @@
 from sentry.web.helpers import render_to_response
 from sentry.signals import user_feedback_received
 from sentry.utils import json
-from sentry.utils.http import is_valid_origin, origin_from_request
+from sentry.utils.http import absolute_uri, is_valid_origin, origin_from_request
 from sentry.utils.validators import normalize_event_id
 
 GENERIC_ERROR = _("An unknown error occurred while submitting your report. Please try again.")
@@ -208,7 +208,9 @@
         )
 
         context = {
-            "endpoint": mark_safe("*/" + json.dumps(request.build_absolute_uri()) + ";/*"),
+            "endpoint": mark_safe(
+                "*/" + json.dumps(absolute_uri(request.get_full_path())) + ";/*"
+            ),
             "template": mark_safe("*/" + json.dumps(template) + ";/*"),
             "strings": json.dumps_htmlsafe(
                 {

{"golden_diff": "diff --git a/src/sentry/web/frontend/error_page_embed.py b/src/sentry/web/frontend/error_page_embed.py\n--- a/src/sentry/web/frontend/error_page_embed.py\n+++ b/src/sentry/web/frontend/error_page_embed.py\n@@ -17,7 +17,7 @@\n from sentry.web.helpers import render_to_response\n from sentry.signals import user_feedback_received\n from sentry.utils import json\n-from sentry.utils.http import is_valid_origin, origin_from_request\n+from sentry.utils.http import absolute_uri, is_valid_origin, origin_from_request\n from sentry.utils.validators import normalize_event_id\n \n GENERIC_ERROR = _(\"An unknown error occurred while submitting your report. Please try again.\")\n@@ -208,7 +208,9 @@\n         )\n \n         context = {\n-            \"endpoint\": mark_safe(\"*/\" + json.dumps(request.build_absolute_uri()) + \";/*\"),\n+            \"endpoint\": mark_safe(\n+                \"*/\" + json.dumps(absolute_uri(request.get_full_path())) + \";/*\"\n+            ),\n             \"template\": mark_safe(\"*/\" + json.dumps(template) + \";/*\"),\n             \"strings\": json.dumps_htmlsafe(\n                 {\n", "issue": "endpoint in error-page-embed.js does not respect system.url-prefix\n## Important Details\r\n\r\nHow are you running Sentry?\r\n\r\n* [x ] On-Premise docker [9.1.1]\r\n## Description\r\n\r\nusing raven-js with angular works as expected to capture exceptions.\r\nwhen reporting errors we get the wrong endpoint from the sentry instance\r\n\r\njavascript snippet:\r\n```js\r\nRaven\r\n  .config(`https://${environment.sentryKey}@MY_INSTANCE/PROJECT_NUMBER`,\r\n    {\r\n      environment: environment.production ? 'prod' : 'dev',\r\n      release: versions.version\r\n    }\r\n  )\r\n  .install();\r\n\r\nexport class RavenErrorHandler implements ErrorHandler {\r\n  handleError(error: any): void {\r\n    const err = error.originalError || error;\r\n    console.error(err);\r\n    Raven.captureException(err);\r\n    if (true) {\r\n      // fetches error-page-embed.js from sentry instance with wrong endpoint (docker endpoint)\r\n      Raven.showReportDialog();\r\n    }\r\n  }\r\n}\r\n```\r\n\r\nthis end point is set here: https://github.com/getsentry/sentry/blob/master/src/sentry/web/frontend/error_page_embed.py\r\n```python\r\n# using request.build_absolute_uri() instead of the value of system.url-prefix 'endpoint':  \r\n \r\nmark_safe('*/' + json.dumps(request.build_absolute_uri()) + ';/*'),\r\n```\r\n\r\n## Steps to Reproduce\r\n\r\nweb:9000 is the hostname of the docker container\r\n![screenshot3](https://user-images.githubusercontent.com/1331762/61046390-4c9d7c00-a3dd-11e9-9554-0ab5b09c72d2.png)\r\n\r\n### What you expected to happen\r\n\r\nsystem.url-prefix in config.yaml: error-page-embed.js should be respected\r\n\r\n\r\ncc/ @max-wittig\r\n\n", "before_files": [{"content": "from __future__ import absolute_import\n\nimport six\n\nfrom django import forms\nfrom django.db import IntegrityError, transaction\nfrom django.http import HttpResponse\nfrom django.views.generic import View\nfrom django.template.loader import render_to_string\nfrom django.utils import timezone\nfrom django.utils.safestring import mark_safe\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.views.decorators.csrf import csrf_exempt\n\nfrom sentry import eventstore\nfrom sentry.models import Event, ProjectKey, ProjectOption, UserReport\nfrom sentry.web.helpers import render_to_response\nfrom sentry.signals import user_feedback_received\nfrom sentry.utils import json\nfrom sentry.utils.http import is_valid_origin, origin_from_request\nfrom sentry.utils.validators import normalize_event_id\n\nGENERIC_ERROR = _(\"An unknown error occurred while submitting your report. Please try again.\")\nFORM_ERROR = _(\"Some fields were invalid. Please correct the errors and try again.\")\nSENT_MESSAGE = _(\"Your feedback has been sent. Thank you!\")\n\nDEFAULT_TITLE = _(\"It looks like we're having issues.\")\nDEFAULT_SUBTITLE = _(\"Our team has been notified.\")\nDEFAULT_SUBTITLE2 = _(\"If you'd like to help, tell us what happened below.\")\n\nDEFAULT_NAME_LABEL = _(\"Name\")\nDEFAULT_EMAIL_LABEL = _(\"Email\")\nDEFAULT_COMMENTS_LABEL = _(\"What happened?\")\n\nDEFAULT_CLOSE_LABEL = _(\"Close\")\nDEFAULT_SUBMIT_LABEL = _(\"Submit Crash Report\")\n\nDEFAULT_OPTIONS = {\n    \"title\": DEFAULT_TITLE,\n    \"subtitle\": DEFAULT_SUBTITLE,\n    \"subtitle2\": DEFAULT_SUBTITLE2,\n    \"labelName\": DEFAULT_NAME_LABEL,\n    \"labelEmail\": DEFAULT_EMAIL_LABEL,\n    \"labelComments\": DEFAULT_COMMENTS_LABEL,\n    \"labelClose\": DEFAULT_CLOSE_LABEL,\n    \"labelSubmit\": DEFAULT_SUBMIT_LABEL,\n    \"errorGeneric\": GENERIC_ERROR,\n    \"errorFormEntry\": FORM_ERROR,\n    \"successMessage\": SENT_MESSAGE,\n}\n\n\nclass UserReportForm(forms.ModelForm):\n    name = forms.CharField(\n        max_length=128, widget=forms.TextInput(attrs={\"placeholder\": _(\"Jane Doe\")})\n    )\n    email = forms.EmailField(\n        max_length=75,\n        widget=forms.TextInput(attrs={\"placeholder\": _(\"jane@example.com\"), \"type\": \"email\"}),\n    )\n    comments = forms.CharField(\n        widget=forms.Textarea(attrs={\"placeholder\": _(\"I clicked on 'X' and then hit 'Confirm'\")})\n    )\n\n    class Meta:\n        model = UserReport\n        fields = (\"name\", \"email\", \"comments\")\n\n\nclass ErrorPageEmbedView(View):\n    def _get_project_key(self, request):\n        try:\n            dsn = request.GET[\"dsn\"]\n        except KeyError:\n            return\n\n        try:\n            key = ProjectKey.from_dsn(dsn)\n        except ProjectKey.DoesNotExist:\n            return\n\n        return key\n\n    def _get_origin(self, request):\n        return origin_from_request(request)\n\n    def _smart_response(self, request, context=None, status=200):\n        json_context = json.dumps(context or {})\n        accept = request.META.get(\"HTTP_ACCEPT\") or \"\"\n        if \"text/javascript\" in accept:\n            content_type = \"text/javascript\"\n            content = \"\"\n        else:\n            content_type = \"application/json\"\n            content = json_context\n        response = HttpResponse(content, status=status, content_type=content_type)\n        response[\"Access-Control-Allow-Origin\"] = request.META.get(\"HTTP_ORIGIN\", \"\")\n        response[\"Access-Control-Allow-Methods\"] = \"GET, POST, OPTIONS\"\n        response[\"Access-Control-Max-Age\"] = \"1000\"\n        response[\"Access-Control-Allow-Headers\"] = \"Content-Type, Authorization, X-Requested-With\"\n        response[\"Vary\"] = \"Accept\"\n        if content == \"\" and context:\n            response[\"X-Sentry-Context\"] = json_context\n        return response\n\n    @csrf_exempt\n    def dispatch(self, request):\n        try:\n            event_id = request.GET[\"eventId\"]\n        except KeyError:\n            return self._smart_response(\n                request, {\"eventId\": \"Missing or invalid parameter.\"}, status=400\n            )\n\n        normalized_event_id = normalize_event_id(event_id)\n        if normalized_event_id:\n            event_id = normalized_event_id\n        elif event_id:\n            return self._smart_response(\n                request, {\"eventId\": \"Missing or invalid parameter.\"}, status=400\n            )\n\n        key = self._get_project_key(request)\n        if not key:\n            return self._smart_response(\n                request, {\"dsn\": \"Missing or invalid parameter.\"}, status=404\n            )\n\n        origin = self._get_origin(request)\n        if not is_valid_origin(origin, key.project):\n            return self._smart_response(request, status=403)\n\n        if request.method == \"OPTIONS\":\n            return self._smart_response(request)\n\n        # customization options\n        options = DEFAULT_OPTIONS.copy()\n        for name in six.iterkeys(options):\n            if name in request.GET:\n                options[name] = six.text_type(request.GET[name])\n\n        # TODO(dcramer): since we cant use a csrf cookie we should at the very\n        # least sign the request / add some kind of nonce\n        initial = {\"name\": request.GET.get(\"name\"), \"email\": request.GET.get(\"email\")}\n\n        form = UserReportForm(request.POST if request.method == \"POST\" else None, initial=initial)\n        if form.is_valid():\n            # TODO(dcramer): move this to post to the internal API\n            report = form.save(commit=False)\n            report.project = key.project\n            report.event_id = event_id\n\n            event = eventstore.get_event_by_id(report.project.id, report.event_id)\n\n            if event is not None:\n                Event.objects.bind_nodes([event])\n                report.environment = event.get_environment()\n                report.group = event.group\n\n            try:\n                with transaction.atomic():\n                    report.save()\n            except IntegrityError:\n                # There was a duplicate, so just overwrite the existing\n                # row with the new one. The only way this ever happens is\n                # if someone is messing around with the API, or doing\n                # something wrong with the SDK, but this behavior is\n                # more reasonable than just hard erroring and is more\n                # expected.\n                UserReport.objects.filter(project=report.project, event_id=report.event_id).update(\n                    name=report.name,\n                    email=report.email,\n                    comments=report.comments,\n                    date_added=timezone.now(),\n                )\n\n            else:\n                if report.group:\n                    report.notify()\n\n            user_feedback_received.send(project=report.project, group=report.group, sender=self)\n\n            return self._smart_response(request)\n        elif request.method == \"POST\":\n            return self._smart_response(request, {\"errors\": dict(form.errors)}, status=400)\n\n        show_branding = (\n            ProjectOption.objects.get_value(\n                project=key.project, key=\"feedback:branding\", default=\"1\"\n            )\n            == \"1\"\n        )\n\n        template = render_to_string(\n            \"sentry/error-page-embed.html\",\n            {\n                \"form\": form,\n                \"show_branding\": show_branding,\n                \"title\": options[\"title\"],\n                \"subtitle\": options[\"subtitle\"],\n                \"subtitle2\": options[\"subtitle2\"],\n                \"name_label\": options[\"labelName\"],\n                \"email_label\": options[\"labelEmail\"],\n                \"comments_label\": options[\"labelComments\"],\n                \"submit_label\": options[\"labelSubmit\"],\n                \"close_label\": options[\"labelClose\"],\n            },\n        )\n\n        context = {\n            \"endpoint\": mark_safe(\"*/\" + json.dumps(request.build_absolute_uri()) + \";/*\"),\n            \"template\": mark_safe(\"*/\" + json.dumps(template) + \";/*\"),\n            \"strings\": json.dumps_htmlsafe(\n                {\n                    \"generic_error\": six.text_type(options[\"errorGeneric\"]),\n                    \"form_error\": six.text_type(options[\"errorFormEntry\"]),\n                    \"sent_message\": six.text_type(options[\"successMessage\"]),\n                }\n            ),\n        }\n\n        return render_to_response(\n            \"sentry/error-page-embed.js\", context, request, content_type=\"text/javascript\"\n        )\n", "path": "src/sentry/web/frontend/error_page_embed.py"}], "after_files": [{"content": "from __future__ import absolute_import\n\nimport six\n\nfrom django import forms\nfrom django.db import IntegrityError, transaction\nfrom django.http import HttpResponse\nfrom django.views.generic import View\nfrom django.template.loader import render_to_string\nfrom django.utils import timezone\nfrom django.utils.safestring import mark_safe\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.views.decorators.csrf import csrf_exempt\n\nfrom sentry import eventstore\nfrom sentry.models import Event, ProjectKey, ProjectOption, UserReport\nfrom sentry.web.helpers import render_to_response\nfrom sentry.signals import user_feedback_received\nfrom sentry.utils import json\nfrom sentry.utils.http import absolute_uri, is_valid_origin, origin_from_request\nfrom sentry.utils.validators import normalize_event_id\n\nGENERIC_ERROR = _(\"An unknown error occurred while submitting your report. Please try again.\")\nFORM_ERROR = _(\"Some fields were invalid. Please correct the errors and try again.\")\nSENT_MESSAGE = _(\"Your feedback has been sent. Thank you!\")\n\nDEFAULT_TITLE = _(\"It looks like we're having issues.\")\nDEFAULT_SUBTITLE = _(\"Our team has been notified.\")\nDEFAULT_SUBTITLE2 = _(\"If you'd like to help, tell us what happened below.\")\n\nDEFAULT_NAME_LABEL = _(\"Name\")\nDEFAULT_EMAIL_LABEL = _(\"Email\")\nDEFAULT_COMMENTS_LABEL = _(\"What happened?\")\n\nDEFAULT_CLOSE_LABEL = _(\"Close\")\nDEFAULT_SUBMIT_LABEL = _(\"Submit Crash Report\")\n\nDEFAULT_OPTIONS = {\n    \"title\": DEFAULT_TITLE,\n    \"subtitle\": DEFAULT_SUBTITLE,\n    \"subtitle2\": DEFAULT_SUBTITLE2,\n    \"labelName\": DEFAULT_NAME_LABEL,\n    \"labelEmail\": DEFAULT_EMAIL_LABEL,\n    \"labelComments\": DEFAULT_COMMENTS_LABEL,\n    \"labelClose\": DEFAULT_CLOSE_LABEL,\n    \"labelSubmit\": DEFAULT_SUBMIT_LABEL,\n    \"errorGeneric\": GENERIC_ERROR,\n    \"errorFormEntry\": FORM_ERROR,\n    \"successMessage\": SENT_MESSAGE,\n}\n\n\nclass UserReportForm(forms.ModelForm):\n    name = forms.CharField(\n        max_length=128, widget=forms.TextInput(attrs={\"placeholder\": _(\"Jane Doe\")})\n    )\n    email = forms.EmailField(\n        max_length=75,\n        widget=forms.TextInput(attrs={\"placeholder\": _(\"jane@example.com\"), \"type\": \"email\"}),\n    )\n    comments = forms.CharField(\n        widget=forms.Textarea(attrs={\"placeholder\": _(\"I clicked on 'X' and then hit 'Confirm'\")})\n    )\n\n    class Meta:\n        model = UserReport\n        fields = (\"name\", \"email\", \"comments\")\n\n\nclass ErrorPageEmbedView(View):\n    def _get_project_key(self, request):\n        try:\n            dsn = request.GET[\"dsn\"]\n        except KeyError:\n            return\n\n        try:\n            key = ProjectKey.from_dsn(dsn)\n        except ProjectKey.DoesNotExist:\n            return\n\n        return key\n\n    def _get_origin(self, request):\n        return origin_from_request(request)\n\n    def _smart_response(self, request, context=None, status=200):\n        json_context = json.dumps(context or {})\n        accept = request.META.get(\"HTTP_ACCEPT\") or \"\"\n        if \"text/javascript\" in accept:\n            content_type = \"text/javascript\"\n            content = \"\"\n        else:\n            content_type = \"application/json\"\n            content = json_context\n        response = HttpResponse(content, status=status, content_type=content_type)\n        response[\"Access-Control-Allow-Origin\"] = request.META.get(\"HTTP_ORIGIN\", \"\")\n        response[\"Access-Control-Allow-Methods\"] = \"GET, POST, OPTIONS\"\n        response[\"Access-Control-Max-Age\"] = \"1000\"\n        response[\"Access-Control-Allow-Headers\"] = \"Content-Type, Authorization, X-Requested-With\"\n        response[\"Vary\"] = \"Accept\"\n        if content == \"\" and context:\n            response[\"X-Sentry-Context\"] = json_context\n        return response\n\n    @csrf_exempt\n    def dispatch(self, request):\n        try:\n            event_id = request.GET[\"eventId\"]\n        except KeyError:\n            return self._smart_response(\n                request, {\"eventId\": \"Missing or invalid parameter.\"}, status=400\n            )\n\n        normalized_event_id = normalize_event_id(event_id)\n        if normalized_event_id:\n            event_id = normalized_event_id\n        elif event_id:\n            return self._smart_response(\n                request, {\"eventId\": \"Missing or invalid parameter.\"}, status=400\n            )\n\n        key = self._get_project_key(request)\n        if not key:\n            return self._smart_response(\n                request, {\"dsn\": \"Missing or invalid parameter.\"}, status=404\n            )\n\n        origin = self._get_origin(request)\n        if not is_valid_origin(origin, key.project):\n            return self._smart_response(request, status=403)\n\n        if request.method == \"OPTIONS\":\n            return self._smart_response(request)\n\n        # customization options\n        options = DEFAULT_OPTIONS.copy()\n        for name in six.iterkeys(options):\n            if name in request.GET:\n                options[name] = six.text_type(request.GET[name])\n\n        # TODO(dcramer): since we cant use a csrf cookie we should at the very\n        # least sign the request / add some kind of nonce\n        initial = {\"name\": request.GET.get(\"name\"), \"email\": request.GET.get(\"email\")}\n\n        form = UserReportForm(request.POST if request.method == \"POST\" else None, initial=initial)\n        if form.is_valid():\n            # TODO(dcramer): move this to post to the internal API\n            report = form.save(commit=False)\n            report.project = key.project\n            report.event_id = event_id\n\n            event = eventstore.get_event_by_id(report.project.id, report.event_id)\n\n            if event is not None:\n                Event.objects.bind_nodes([event])\n                report.environment = event.get_environment()\n                report.group = event.group\n\n            try:\n                with transaction.atomic():\n                    report.save()\n            except IntegrityError:\n                # There was a duplicate, so just overwrite the existing\n                # row with the new one. The only way this ever happens is\n                # if someone is messing around with the API, or doing\n                # something wrong with the SDK, but this behavior is\n                # more reasonable than just hard erroring and is more\n                # expected.\n                UserReport.objects.filter(project=report.project, event_id=report.event_id).update(\n                    name=report.name,\n                    email=report.email,\n                    comments=report.comments,\n                    date_added=timezone.now(),\n                )\n\n            else:\n                if report.group:\n                    report.notify()\n\n            user_feedback_received.send(project=report.project, group=report.group, sender=self)\n\n            return self._smart_response(request)\n        elif request.method == \"POST\":\n            return self._smart_response(request, {\"errors\": dict(form.errors)}, status=400)\n\n        show_branding = (\n            ProjectOption.objects.get_value(\n                project=key.project, key=\"feedback:branding\", default=\"1\"\n            )\n            == \"1\"\n        )\n\n        template = render_to_string(\n            \"sentry/error-page-embed.html\",\n            {\n                \"form\": form,\n                \"show_branding\": show_branding,\n                \"title\": options[\"title\"],\n                \"subtitle\": options[\"subtitle\"],\n                \"subtitle2\": options[\"subtitle2\"],\n                \"name_label\": options[\"labelName\"],\n                \"email_label\": options[\"labelEmail\"],\n                \"comments_label\": options[\"labelComments\"],\n                \"submit_label\": options[\"labelSubmit\"],\n                \"close_label\": options[\"labelClose\"],\n            },\n        )\n\n        context = {\n            \"endpoint\": mark_safe(\n                \"*/\" + json.dumps(absolute_uri(request.get_full_path())) + \";/*\"\n            ),\n            \"template\": mark_safe(\"*/\" + json.dumps(template) + \";/*\"),\n            \"strings\": json.dumps_htmlsafe(\n                {\n                    \"generic_error\": six.text_type(options[\"errorGeneric\"]),\n                    \"form_error\": six.text_type(options[\"errorFormEntry\"]),\n                    \"sent_message\": six.text_type(options[\"successMessage\"]),\n                }\n            ),\n        }\n\n        return render_to_response(\n            \"sentry/error-page-embed.js\", context, request, content_type=\"text/javascript\"\n        )\n", "path": "src/sentry/web/frontend/error_page_embed.py"}]}