from django.conf import settings
from django.conf.urls import include
from django.contrib import admin
from django.contrib.auth.decorators import login_required
from django.urls import path
from django.urls import re_path
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import RedirectView
from documents.views import AcknowledgeTasksView
from documents.views import BulkDownloadView
from documents.views import BulkEditView
from documents.views import CorrespondentViewSet
from documents.views import DocumentTypeViewSet
from documents.views import IndexView
from documents.views import LogViewSet
from documents.views import PostDocumentView
from documents.views import RemoteVersionView
from documents.views import SavedViewViewSet
from documents.views import SearchAutoCompleteView
from documents.views import SelectionDataView
from documents.views import StatisticsView
from documents.views import StoragePathViewSet
from documents.views import TagViewSet
from documents.views import TasksViewSet
from documents.views import UiSettingsView
from documents.views import UnifiedSearchViewSet
from paperless.consumers import StatusConsumer
from paperless.views import FaviconView
from paperless_mail.views import MailAccountViewSet
from paperless_mail.views import MailRuleViewSet
from rest_framework.authtoken import views
from rest_framework.routers import DefaultRouter

api_router = DefaultRouter()
api_router.register(r"correspondents", CorrespondentViewSet)
api_router.register(r"document_types", DocumentTypeViewSet)
api_router.register(r"documents", UnifiedSearchViewSet)
api_router.register(r"logs", LogViewSet, basename="logs")
api_router.register(r"tags", TagViewSet)
api_router.register(r"saved_views", SavedViewViewSet)
api_router.register(r"storage_paths", StoragePathViewSet)
api_router.register(r"tasks", TasksViewSet, basename="tasks")
api_router.register(r"mail_accounts", MailAccountViewSet)
api_router.register(r"mail_rules", MailRuleViewSet)


urlpatterns = [
    re_path(
        r"^api/",
        include(
            [
                re_path(
                    r"^auth/",
                    include(
                        ("rest_framework.urls", "rest_framework"),
                        namespace="rest_framework",
                    ),
                ),
                re_path(
                    r"^search/autocomplete/",
                    SearchAutoCompleteView.as_view(),
                    name="autocomplete",
                ),
                re_path(r"^statistics/", StatisticsView.as_view(), name="statistics"),
                re_path(
                    r"^documents/post_document/",
                    PostDocumentView.as_view(),
                    name="post_document",
                ),
                re_path(
                    r"^documents/bulk_edit/",
                    BulkEditView.as_view(),
                    name="bulk_edit",
                ),
                re_path(
                    r"^documents/selection_data/",
                    SelectionDataView.as_view(),
                    name="selection_data",
                ),
                re_path(
                    r"^documents/bulk_download/",
                    BulkDownloadView.as_view(),
                    name="bulk_download",
                ),
                re_path(
                    r"^remote_version/",
                    RemoteVersionView.as_view(),
                    name="remoteversion",
                ),
                re_path(
                    r"^ui_settings/",
                    UiSettingsView.as_view(),
                    name="ui_settings",
                ),
                re_path(
                    r"^acknowledge_tasks/",
                    AcknowledgeTasksView.as_view(),
                    name="acknowledge_tasks",
                ),
                path("token/", views.obtain_auth_token),
            ]
            + api_router.urls,
        ),
    ),
    re_path(r"^favicon.ico$", FaviconView.as_view(), name="favicon"),
    re_path(r"admin/", admin.site.urls),
    re_path(
        r"^fetch/",
        include(
            [
                re_path(
                    r"^doc/(?P<pk>\d+)$",
                    RedirectView.as_view(
                        url=settings.BASE_URL + "api/documents/%(pk)s/download/",
                    ),
                ),
                re_path(
                    r"^thumb/(?P<pk>\d+)$",
                    RedirectView.as_view(
                        url=settings.BASE_URL + "api/documents/%(pk)s/thumb/",
                    ),
                ),
                re_path(
                    r"^preview/(?P<pk>\d+)$",
                    RedirectView.as_view(
                        url=settings.BASE_URL + "api/documents/%(pk)s/preview/",
                    ),
                ),
            ],
        ),
    ),
    re_path(
        r"^push$",
        csrf_exempt(
            RedirectView.as_view(
                url=settings.BASE_URL + "api/documents/post_document/",
            ),
        ),
    ),
    # Frontend assets TODO: this is pretty bad, but it works.
    path(
        "assets/<path:path>",
        RedirectView.as_view(
            url=settings.STATIC_URL + "frontend/en-US/assets/%(path)s",
        ),
    ),
    # TODO: with localization, this is even worse! :/
    # login, logout
    path("accounts/", include("django.contrib.auth.urls")),
    # Root of the Frontent
    re_path(r".*", login_required(IndexView.as_view()), name="base"),
]


websocket_urlpatterns = [
    re_path(r"ws/status/$", StatusConsumer.as_asgi()),
]

# Text in each page's <h1> (and above login form).
admin.site.site_header = "Paperless-ngx"
# Text at the end of each page's <title>.
admin.site.site_title = "Paperless-ngx"
# Text at the top of the admin index page.
admin.site.index_title = _("Paperless-ngx administration")

src/paperless/urls.py
from django.conf import settings
from django.conf.urls import include
from django.contrib import admin
from django.contrib.auth.decorators import login_required
from django.urls import path
from django.urls import re_path
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import RedirectView
from documents.views import AcknowledgeTasksView
from documents.views import BulkDownloadView
from documents.views import BulkEditView
from documents.views import CorrespondentViewSet
from documents.views import DocumentTypeViewSet
from documents.views import IndexView
from documents.views import LogViewSet
from documents.views import PostDocumentView
from documents.views import RemoteVersionView
from documents.views import SavedViewViewSet
from documents.views import SearchAutoCompleteView
from documents.views import SelectionDataView
from documents.views import StatisticsView
from documents.views import StoragePathViewSet
from documents.views import TagViewSet
from documents.views import TasksViewSet
from documents.views import UiSettingsView
from documents.views import UnifiedSearchViewSet
from paperless.consumers import StatusConsumer
from paperless.views import FaviconView
from paperless_mail.views import MailAccountViewSet
from paperless_mail.views import MailRuleViewSet
from rest_framework.authtoken import views
from rest_framework.routers import DefaultRouter

api_router = DefaultRouter()
api_router.register(r"correspondents", CorrespondentViewSet)
api_router.register(r"document_types", DocumentTypeViewSet)
api_router.register(r"documents", UnifiedSearchViewSet)
api_router.register(r"logs", LogViewSet, basename="logs")
api_router.register(r"tags", TagViewSet)
api_router.register(r"saved_views", SavedViewViewSet)
api_router.register(r"storage_paths", StoragePathViewSet)
api_router.register(r"tasks", TasksViewSet, basename="tasks")
api_router.register(r"mail_accounts", MailAccountViewSet)
api_router.register(r"mail_rules", MailRuleViewSet)


urlpatterns = [
    re_path(
        r"^api/",
        include(
            [
                re_path(
                    r"^auth/",
                    include(
                        ("rest_framework.urls", "rest_framework"),
                        namespace="rest_framework",
                    ),
                ),
                re_path(
                    r"^search/autocomplete/",
                    SearchAutoCompleteView.as_view(),
                    name="autocomplete",
                ),
                re_path(r"^statistics/", StatisticsView.as_view(), name="statistics"),
                re_path(
                    r"^documents/post_document/",
                    PostDocumentView.as_view(),
                    name="post_document",
                ),
                re_path(
                    r"^documents/bulk_edit/",
                    BulkEditView.as_view(),
                    name="bulk_edit",
                ),
                re_path(
                    r"^documents/selection_data/",
                    SelectionDataView.as_view(),
                    name="selection_data",
                ),
                re_path(
                    r"^documents/bulk_download/",
                    BulkDownloadView.as_view(),
                    name="bulk_download",
                ),
                re_path(
                    r"^remote_version/",
                    RemoteVersionView.as_view(),
                    name="remoteversion",
                ),
                re_path(
                    r"^ui_settings/",
                    UiSettingsView.as_view(),
                    name="ui_settings",
                ),
                re_path(
                    r"^acknowledge_tasks/",
                    AcknowledgeTasksView.as_view(),
                    name="acknowledge_tasks",
                ),
                path("token/", views.obtain_auth_token),
            ]
            + api_router.urls,
        ),
    ),
    re_path(r"^favicon.ico$", FaviconView.as_view(), name="favicon"),
    re_path(r"admin/", admin.site.urls),
    re_path(
        r"^fetch/",
        include(
            [
                re_path(
                    r"^doc/(?P<pk>\d+)$",
                    RedirectView.as_view(
                        url=settings.BASE_URL + "api/documents/%(pk)s/download/",
                    ),
                ),
                re_path(
                    r"^thumb/(?P<pk>\d+)$",
                    RedirectView.as_view(
                        url=settings.BASE_URL + "api/documents/%(pk)s/thumb/",
                    ),
                ),
                re_path(
                    r"^preview/(?P<pk>\d+)$",
                    RedirectView.as_view(
                        url=settings.BASE_URL + "api/documents/%(pk)s/preview/",
                    ),
                ),
            ],
        ),
    ),
    re_path(
        r"^push$",
        csrf_exempt(
            RedirectView.as_view(
                url=settings.BASE_URL + "api/documents/post_document/",
            ),
        ),
    ),
    # Frontend assets TODO: this is pretty bad, but it works.
    path(
        "assets/<path:path>",
        RedirectView.as_view(
            url=settings.STATIC_URL + "frontend/en-US/assets/%(path)s",
        ),
    ),
    # TODO: with localization, this is even worse! :/
    # login, logout
    path("accounts/", include("django.contrib.auth.urls")),
    # Root of the Frontent
    re_path(r".*", login_required(IndexView.as_view()), name="base"),
]


websocket_urlpatterns = [
    path(settings.BASE_URL.lstrip("/") + "ws/status/", StatusConsumer.as_asgi()),
]

# Text in each page's <h1> (and above login form).
admin.site.site_header = "Paperless-ngx"
# Text at the end of each page's <title>.
admin.site.site_title = "Paperless-ngx"
# Text at the top of the admin index page.
admin.site.index_title = _("Paperless-ngx administration")

src/paperless/urls.py
diff --git a/src/paperless/urls.py b/src/paperless/urls.py
index 8e8f4b40490..490be525a99 100644
--- a/src/paperless/urls.py
+++ b/src/paperless/urls.py
@@ -154,7 +154,7 @@
 
 
 websocket_urlpatterns = [
-    re_path(r"ws/status/$", StatusConsumer.as_asgi()),
+    path(settings.BASE_URL.lstrip("/") + "ws/status/", StatusConsumer.as_asgi()),
 ]
 
 # Text in each page's <h1> (and above login form).

[Bug] Websockets do not respect subpath
### Discussed in https://github.com/paperless-ngx/paperless-ngx/discussions/2236

<div type='discussions-op-text'>

<sup>Originally posted by **davidgiga1993** December 21, 2022</sup>
I migrated from paprless-ng to paperless-ngx and the websocket connection isn't working anymore:
```
WebSocket connection to 'wss://home.dev-core.org/paperless/ws/status/' failed:
```
The server returns status code 500.

I'm using `/paperless` as path and configured it according to the [documentation](https://docs.paperless-ngx.com/configuration/#hosting-and-security)
```
PAPERLESS_FORCE_SCRIPT_NAME=/paperless
PAPERLESS_STATIC_URL=/paperless/static/
PAPERLESS_MEDIA_URL=/paperless/media/

PAPERLESS_URL=https://my-domain.com
```

my nginx config hasn't changed since and worked fine before:
```
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;

client_body_buffer_size 128k;
proxy_next_upstream error timeout;
proxy_redirect  http://  $scheme://;
proxy_http_version 1.1;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 64 256k;

# Allow websockets
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

real_ip_header X-Forwarded-For;
real_ip_recursive on;

send_timeout 5m;
proxy_read_timeout 360;
proxy_send_timeout 360;
proxy_connect_timeout 360;
```

It looks like paperless ngx isn't using the context path for the websockets - here is a test using curl. The first request (with the correct path) returns `500`, the second one without any context path returns correctly `403`
```
nas paperless # curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: my-domain.com" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" -H "Sec-WebSocket-Version: 13" localhost:8000/paperless/ws/status/
HTTP/1.1 500 Internal Server Error
content-type: text/plain; charset=utf-8
content-length: 21
connection: close

Internal Server Error#
nas paperless # curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: my-domain.com" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" -H "Sec-WebSocket-Version: 13" localhost:8000/ws/status/
HTTP/1.1 403 Forbidden
Date: Sun, 11 Dec 2022 10:03:35 GMT
Server: Python/3.9 websockets/10.4
Content-Length: 0
Content-Type: text/plain
Connection: close
```

any ideas? Anything else I should test?
    </div>
