Skip to content

Commit

Permalink
Add location function to redirect to a non-Inertia URL (#53)
Browse files Browse the repository at this point in the history
* Add location function to redirect to a non-Inertia URL

* Add section of External Redirects to Readme
  • Loading branch information
keinstn authored Nov 21, 2024
1 parent e93f118 commit 8219af9
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 9 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,21 @@ def inertia_share(get_response):
return middleware
```

### External Redirects

It is possible to redirect to an external website, or even another non-Inertia endpoint in your app while handling an Inertia request.
This can be accomplished using a server-side initiated `window.location` visit via the `location` method:

```python
from inertia import location

def external():
return location("http://foobar.com/")
```

It will generate a `409 Conflict` response and include the destination URL in the `X-Inertia-Location` header.
When this response is received client-side, Inertia will automatically perform a `window.location = url` visit.

### Lazy Props
On the front end, Inertia supports the concept of "partial reloads" where only the props requested
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.
Expand Down
2 changes: 1 addition & 1 deletion inertia/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .http import inertia, render
from .http import inertia, render, location
from .utils import lazy
from .share import share
8 changes: 7 additions & 1 deletion inertia/http.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.http import JsonResponse
from http import HTTPStatus
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render as base_render
from .settings import settings
from json import dumps as json_encode
Expand Down Expand Up @@ -81,6 +82,11 @@ def page_data():
**template_data,
})

def location(location):
return HttpResponse('', status=HTTPStatus.CONFLICT, headers={
'X-Inertia-Location': location,
})

def inertia(component):
def decorator(func):
@wraps(func)
Expand Down
5 changes: 2 additions & 3 deletions inertia/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.contrib import messages
from django.http import HttpResponse
from django.middleware.csrf import get_token
from .http import location

class InertiaMiddleware:
def __init__(self, get_response):
Expand Down Expand Up @@ -42,6 +43,4 @@ def is_stale_inertia_get(self, request):

def force_refresh(self, request):
messages.get_messages(request).used = False
return HttpResponse('', status=409, headers={
'X-Inertia-Location': request.build_absolute_uri(),
})
return location(request.build_absolute_uri())
10 changes: 9 additions & 1 deletion inertia/tests/test_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,12 @@ def test_a_request_not_from_inertia_is_ignored(self):
HTTP_X_INERTIA_VERSION='some-nonsense',
)

self.assertEqual(response.status_code, 200)
self.assertEqual(response.status_code, 200)

def test_external_redirect_status(self):
response = self.inertia.post('/external-redirect/')
self.assertEqual(response.status_code, 409)
self.assertIn("X-Inertia-Location", response.headers)
self.assertEqual(
"http://foobar.com/", response.headers["X-Inertia-Location"]
)
3 changes: 2 additions & 1 deletion inertia/tests/testapp/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
path('complex-props/', views.complex_props_test),
path('share/', views.share_test),
path('inertia-redirect/', views.inertia_redirect_test),
]
path('external-redirect/', views.external_redirect_test),
]
7 changes: 5 additions & 2 deletions inertia/tests/testapp/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.http.response import HttpResponse
from django.shortcuts import redirect
from django.utils.decorators import decorator_from_middleware
from inertia import inertia, render, lazy, share
from inertia import inertia, render, lazy, share, location

class ShareMiddleware:
def __init__(self, get_response):
Expand All @@ -27,6 +27,9 @@ def redirect_test(request):
def inertia_redirect_test(request):
return redirect(empty_test)

def external_redirect_test(request):
return location("http://foobar.com/")

@inertia('TestComponent')
def props_test(request):
return {
Expand Down Expand Up @@ -61,4 +64,4 @@ def complex_props_test(request):
def share_test(request):
return {
'name': 'Brandon',
}
}

0 comments on commit 8219af9

Please sign in to comment.