Existe uma maneira de obter um URL de referência por meio de um cabeçalho HTTP personalizado?


8

Atualmente, estou usando a seguinte função para obter uma exibição de referência:

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

Se eu redirecionei o viewresultado da lógica programática, por exemplo ..

return HttpResponseRedirect('dashboard')

... existe uma maneira de obter a visualização de referência sem usar HTTP_REFERERpara que eu possa usar essa variável no redirecionado view? Isso nem sempre é definido nos cabeçalhos do navegador.

Observe que, como as visualizações são redirecionadas de forma programática, não posso usar o POST para coletar os dados.

Talvez seja possível definir e recuperar um cabeçalho personalizado de alguma forma?


1
Você controla a visualização anterior e ela vem do seu aplicativo? Eu apenas adicionaria essas informações na carga útil e na resposta. Por exemplo, como um parâmetro GET de redirecionamento ?came_from=inbox. Ligado, Facebook, outros parecem fazê-lo, por isso deve ser uma boa prática.
Mikko Ohtamaa 15/01

1
@MikkoOhtamaa sim, eu controlo a vista. O caso de uso é geralmente um redirecionamento lógico condicional. Idealmente, eu gostaria de manter a URL limpa.
alias51 15/01

Os parâmetros de consulta GET são o caminho a percorrer. Como alternativa, você pode tentar ocultar algumas informações de estado nos dados da sessão do usuário, mas elas geralmente se desfazem quando o usuário tem várias janelas do navegador abertas e há substituições conflitantes nas variáveis ​​da sessão.
Mikko Ohtamaa 15/01

HttpResponseRedirectnão é realmente programático - ele retorna a resposta http 302 real e força o navegador a fazer uma nova solicitação para o novo URL da exibição para a qual está sendo redirecionado ...
Oleg Russkin

Respostas:


2

Use o componente de middleware do Django.

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

Algo assim deve funcionar:

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

Assim, você pode vincular qualquer informação necessária a cada ciclo de solicitação / resposta no Django (você também pode definir cabeçalhos personalizados, etc ...)

No exemplo acima HTTP_REFERER, estará disponível no objeto de solicitação como referer.

EDIT: Eu acho que você se preocupa é que HTTP_REFERERnem sempre é preenchida pelo cliente; para que você possa vincular HttpRequest.path a todas as solicitações feitas em um cabeçalho personalizado. Se o caminho não for suficiente, você também poderá salvar os argumentos da solicitação. É tudo o que eu penso. Então você tem um cabeçalho personalizado preenchido pelo último caminho. Além disso, se isso não for suficiente, você poderá usar o resolvedor de URLs do Django .


Obrigado, mas minha pergunta é feita explicitamente sem o uso de
HTTP_REFERER

@ alias51, eu entendo, mas como você tem total controle do ciclo de solicitação / resposta, por que você não usa um cabeçalho personalizado? Like: response ['EU SOU RASTREANDO ALGO EM UM PROTOCOLO IMOBILIÁRIO'] = 'O QUE QUER QUE VOCÊ PRECISA'. Vou alterar minha resposta.
jazz

1

Desde que você controla a página que faz a solicitação, com certeza. Adicione o URL atual a algum cabeçalho e extraia-o em sua função, semelhante a este: Adicione o cabeçalho da solicitação antes do redirecionamento

então, ao invés disso:

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

faça algo assim:

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

Isso deve produzir o 302 com o cabeçalho personalizado source-view, que você pode extrair na exibição de recebimento


0

Para os interessados, aqui está a solução que eu derivei. O truque é definir um cookie após a primeira solicitação para armazenar o view_nameou pathe depois chamá-lo e salvar no requestantes de renderizar a exibição.

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

Os valores são atualizados nesse ciclo sempre que a exibição é alterada.


1
A questão é que você conseguiu a solução para obter a direção certa. Se você preferir cookies em vez de um cabeçalho personalizado, por questão de gosto, eu preferiria o cabeçalho personalizado da perspectiva do design, pois o caminho anterior é volátil e o armazenamento dessas informações no cookie é redundante. Fico feliz em ajudá-lo :-) Eu vi sua "solução" tarde demais, caso contrário, não editaria minha resposta.
jazz

Obrigado, por que você acha que request.path é volátil? O motivo pelo qual eu uso um cookie em vez do cabeçalho é o cabeçalho pode ser facilmente manipulado e, portanto, menos seguro.
alias51
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.