Is there a way to get a referring URL via a custom HTTP header?

I am currently using the following function to get a referring view:

def get_referer_view(request, default=None):   
    referer = request.META.get('HTTP_REFERER')
    if not referer:
        return default

    # remove the protocol and split the url at the slashes
    referer = re.sub('^https?:\/\/', '', referer).split('/')
    if referer[0] != request.META.get('SERVER_NAME'):
        return default

    # add the slash at the relative path's view and finished
    referer = u'/' + u'/'.join(referer[1:])
    return referer

If I redirected the view as a result of programmatic logic, e.g...

return HttpResponseRedirect('dashboard')

...is there a way to get the referring view without using HTTP_REFERER so that I can use that variable in the redirected view? This is not always set in the headers of the browser.

Note because the views are redirected pro grammatically, I can't use POST to collect the data.

Perhaps its possible to set and retrieve a custom header somehow?

Use Django's middleware component.

https://docs.djangoproject.com/en/3.0/topics/http/middleware/

Something like this should work:

class HTTPReferer:

    def __init__(self, get_response):
        self.get_response = get_response

def __call__old(self, request):
    # old
    referer = request.META.get('HTTP_REFERER', None)
    request.referer = referer
    # other business logic as you like it
    response = self.get_response(request)
    return response

def __call__(self, request):
    # reflecting last edit
    path = request.path
    response = self.get_response(request)
    response['previous_path'] = path
    return response

So you could tie any information you need to every request/response cycle in Django (you could also set custom headers, etc...)

In the example above HTTP_REFERER will be available in request object as referer.

EDIT: I think, you concern is that HTTP_REFERER is not always populated by the client; so you could tie HttpRequest.path to every request made to a custom header. If path is not enough, you could save the request args too. That's all, I think. Then you have a custom header populated by the last path. Further on, if this is not enough, you could use Django's URL resolver.

Referrer-Policy, The Referrer-Policy HTTP header controls how much referrer information (sent via the Referer header) should be included with requests. The origin, path, and querystring of the URL are sent as a referrer when the protocol security Get the latest and greatest from MDN delivered straight to your inbox. The HTTP referer (a misspelling of referrer) is an optional HTTP header field that identifies the address of the webpage (i.e., the URI or IRI) which is linked to the resource being requested. By checking the referrer, the new webpage can see where the request originated.

Since you control the page making the request, sure. Add the current URL to some header and extract it in your function, similar to this: Add request header before redirection

so instead of this:

def current_view():
   ...
   return HttpResponseRedirect('dashboard')

do something like this:

def current_view():
    ...
    response = redirect('/dashboard')
    response['source-view'] = request.resolver_match.view_name
    return response

This should produce the 302 with the custom header source-view, which you can extract in the receiving view

Referer, The Referer request header contains the address of the previous web page from Important: Although this header has many innocent uses it can have An unsecured HTTP request is used and the referring page was received with a < url>: An absolute or partial address of the previous web page from� Note that referer is actually a misspelling of the word "referrer". See HTTP referer on Wikipedia for more details. A Referer header is not sent by browsers if: The referring resource is a local "file" or "data" URI. An unsecured HTTP request is used and the referring page was received with a secure protocol (HTTPS).

For those interested, here's the solution I derived. The trick is to set a cookie after the first request to store the view_name or path and then call it and save to the request before rendering the view.

class MyMiddleware:

    def __init__(self, get_response):
        # One-time configuration and initialization.
        self.get_response = get_response

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        # Add the referer cookie be accessible in request.response
        request.referer_view = request.COOKIES.get('referer_view', None)
        request.referer_path = request.COOKIES.get('referer_path', None)
        print('request.referer_view', request.referer_view)
        print('request.referer_path', request.referer_path)

        response = self.get_response(request)
        # Code to be executed for each request/response after
        # the view is called.

        # Set a cookie with the current view name that is cleared each time the view changes
        response.set_cookie('referer_view', request.resolver_match.view_name)
        response.set_cookie('referer_path', request.path)

        return response

The values then update in this cycle each time the view is changed.

Request Headers in the HTTP protocol, These header lines are sent by the client in a HTTP protocol From; Accept; Accept-Encoding; Accept-Language; User-Agent; Referer; Authorization; Charge- To for example, and enable a more appropriate custom-designed black This request header is used with GET method to make it conditional: if� External CSS stylesheets use the default policy (no-referrer-when-downgrade), unless it's overwritten via a Referrer-Policy HTTP header on the CSS stylesheet’s response. For <style> elements or style attributes , the owner document's referrer policy is used.

Referrer Policy, While the header can be suppressed for links with the noreferrer link type, Note that there are other ways for capability URLs to leak, and controlling the referrer is a Referer HTTP header with a value of https://example.com/page.html For this spec to make sense with W3C HTML5, those would need to� HTTP headers let the client and the server pass additional information with an HTTP request or response. An HTTP header consists of its case-insensitive name followed by a colon (:), then by its value. Whitespace before the value is ignored.

HTTP Headers for Dummies - Code Tuts, And if there was a referring url, that would have been in the header too. After the browser sends the HTTP request, the server responds with an There are other ways in which access can be blocked, and 403 can be sent. Is there a way we can add LOGON_USER to a USER_NAME header after the authentication happens? Based on my understanding, build a custom module to assign the current log user information to the USER_NAME header. Please find how to build custom module in the following link.

How To Secure Your Web App With HTTP Headers — Smashing , HTTP response headers can be leveraged to tighten up the security of web apps, Make sure to disable caching only for resources that actually require Now, consider how will the web app above handle a URL constructed with malicious You may also add Referrer-Policy header to this list, see� The web service requires a cusom http header to be provided in the payload. Is there any way I can add a http header as part of the web service call. When I look at the generated stubs I don't see any way i can provide the header. Thanks. Joe. BTW In WPF I was using the behaviors elements in the app.config to pass on the http header

Comments
  • Do you control the previous view and it comes from your application? I would just add this information in the payload and response. E.g. as a redirect GET parameter ?came_from=inbox. Linked, Facebook, others seem to do it, so it should be ok practice.
  • @MikkoOhtamaa yes, I control the view. The use case is typically a conditional logic redirect. Ideally I would like the keep the URL clean though.
  • GET query parameters are the way to go. Alternative you can try to stash some state information in the user session data, but it usually falls apart when the user has multiple browser windows open and there are conflicting overwrites to session variables.
  • HttpResponseRedirect is not really programatic - it returns actual http 302 response and forces browser to make new request to new url of the view it is being redirected to...
  • Thanks, but my question asks explicitly without using HTTP_REFERER
  • @alias51, I understand, but as you have full control to the request/response cycle, why don't you use than a custom header instead? Like: response['I-AM-TRACKING-SOMETHING-IN-A-STATELESS-PROTOCOL'] = 'WHATEVER-YOU-NEED'. I will amend my answer.
  • Point is, that you got the solution getting the direction to it. If you prefer cookies over a custom header, matter of taste, I'd had preferred the custom header from a design perspective, as the previous path is volatile and storing this information in cookie is redundant. Glad to helped you :-) I saw your "solution" too late, otherwise, I would not edited my answer.
  • Thanks, why do you think that request.path is volatile? The reason I use a cookie rather than the header is headers can be easily manipulated and are therefore less secure.