Skip to content

Commit 8219af9

Browse files
authored
Add location function to redirect to a non-Inertia URL (#53)
* Add location function to redirect to a non-Inertia URL * Add section of External Redirects to Readme
1 parent e93f118 commit 8219af9

File tree

7 files changed

+41
-9
lines changed

7 files changed

+41
-9
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,21 @@ def inertia_share(get_response):
112112
return middleware
113113
```
114114

115+
### External Redirects
116+
117+
It is possible to redirect to an external website, or even another non-Inertia endpoint in your app while handling an Inertia request.
118+
This can be accomplished using a server-side initiated `window.location` visit via the `location` method:
119+
120+
```python
121+
from inertia import location
122+
123+
def external():
124+
return location("http://foobar.com/")
125+
```
126+
127+
It will generate a `409 Conflict` response and include the destination URL in the `X-Inertia-Location` header.
128+
When this response is received client-side, Inertia will automatically perform a `window.location = url` visit.
129+
115130
### Lazy Props
116131
On the front end, Inertia supports the concept of "partial reloads" where only the props requested
117132
are returned by the server. Sometimes, you may want to use this flow to avoid processing a particularly slow prop on the intial load. In this case, you can use `Lazy props`. Lazy props aren't evaluated unless they're specifically requested by name in a partial reload.

inertia/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
from .http import inertia, render
1+
from .http import inertia, render, location
22
from .utils import lazy
33
from .share import share

inertia/http.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from django.http import JsonResponse
1+
from http import HTTPStatus
2+
from django.http import HttpResponse, JsonResponse
23
from django.shortcuts import render as base_render
34
from .settings import settings
45
from json import dumps as json_encode
@@ -81,6 +82,11 @@ def page_data():
8182
**template_data,
8283
})
8384

85+
def location(location):
86+
return HttpResponse('', status=HTTPStatus.CONFLICT, headers={
87+
'X-Inertia-Location': location,
88+
})
89+
8490
def inertia(component):
8591
def decorator(func):
8692
@wraps(func)

inertia/middleware.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from django.contrib import messages
33
from django.http import HttpResponse
44
from django.middleware.csrf import get_token
5+
from .http import location
56

67
class InertiaMiddleware:
78
def __init__(self, get_response):
@@ -42,6 +43,4 @@ def is_stale_inertia_get(self, request):
4243

4344
def force_refresh(self, request):
4445
messages.get_messages(request).used = False
45-
return HttpResponse('', status=409, headers={
46-
'X-Inertia-Location': request.build_absolute_uri(),
47-
})
46+
return location(request.build_absolute_uri())

inertia/tests/test_middleware.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,12 @@ def test_a_request_not_from_inertia_is_ignored(self):
2929
HTTP_X_INERTIA_VERSION='some-nonsense',
3030
)
3131

32-
self.assertEqual(response.status_code, 200)
32+
self.assertEqual(response.status_code, 200)
33+
34+
def test_external_redirect_status(self):
35+
response = self.inertia.post('/external-redirect/')
36+
self.assertEqual(response.status_code, 409)
37+
self.assertIn("X-Inertia-Location", response.headers)
38+
self.assertEqual(
39+
"http://foobar.com/", response.headers["X-Inertia-Location"]
40+
)

inertia/tests/testapp/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@
1111
path('complex-props/', views.complex_props_test),
1212
path('share/', views.share_test),
1313
path('inertia-redirect/', views.inertia_redirect_test),
14-
]
14+
path('external-redirect/', views.external_redirect_test),
15+
]

inertia/tests/testapp/views.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django.http.response import HttpResponse
22
from django.shortcuts import redirect
33
from django.utils.decorators import decorator_from_middleware
4-
from inertia import inertia, render, lazy, share
4+
from inertia import inertia, render, lazy, share, location
55

66
class ShareMiddleware:
77
def __init__(self, get_response):
@@ -27,6 +27,9 @@ def redirect_test(request):
2727
def inertia_redirect_test(request):
2828
return redirect(empty_test)
2929

30+
def external_redirect_test(request):
31+
return location("http://foobar.com/")
32+
3033
@inertia('TestComponent')
3134
def props_test(request):
3235
return {
@@ -61,4 +64,4 @@ def complex_props_test(request):
6164
def share_test(request):
6265
return {
6366
'name': 'Brandon',
64-
}
67+
}

0 commit comments

Comments
 (0)