19 de Dezembro de 2011
As vezes você tem uma aplicação que precisa servir arquivos estáticos protegidos (entende-se arquivos estáticos que apenas alguns usuários deveriam ter acesso). Abaixo irei mostrar um snippet para nginx e django, com o qual é possível fazer a verificação da requisição do arquivo protegido com django e deixar o nginx servir o arquivo.
O apache utiliza o xsendfile que é bem semelhante ao X-Accel-Redirect do nginx, com a diferença que o apache deseja que você informe o caminho completo do arquivo e o nginx o caminho relativo a pasta que você irá definir que contém os arquivos protegidos.
Crie um modulo python e armazene o seguinte script (estou supondo que você tem uma settings chamada PROJECT_ROOT que contém o caminho root do projeto, você deve colocar a variável settings USE_XACCELREDIRECT=True no ambiente de produção e False no ambiente de desenvolvimento)
# -*- coding: utf-8 -*-
import os
from django.core.files.storage import FileSystemStorage
from django.conf import settings
from django.views.static import serve
from django.http import HttpResponse
from django.utils.encoding import smart_str
SECURE_STORAGE = FileSystemStorage(location=settings.PROJECT_ROOT, base_url='/')
USE_XACCELREDIRECT = getattr(settings, 'USE_XACCELREDIRECT', False)
def xaccelredirect(request, path, document_root=settings.PROJECT_ROOT):
split = path.split('/')
filename = split[-1]
filename = filename.replace(" ", '_')
if USE_XACCELREDIRECT:
#fullpath = smart_str(os.path.join(document_root, path))
# This is where the magic takes place.
response = HttpResponse()
if not path.startswith('/'):
path = "/" + path
response['X-Accel-Redirect'] = path
# Unset the Content-Type as to allow for the webserver
# to determine it.
response['Content-Type'] = ''
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(filename)
return response
response = serve(request, path, document_root)
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(filename)
return response
Na sua view você deve importar esta função e utilizar ela como resposta da sua view.
Por Exemplo: você cria uma pasta chamada protected dentro do diretório ROOT do projeto e supondo que você quer enviar um arquivo protegido chamado imagem.png, que está dentro desta pasta, você chama a função acima criada passando como parâmetros o objeto request e o caminho "protected/imagem.png".
def minha_view(request):
# minha verificação se o usuário pode acessar o arquivo
return xaccelredirect(request, "protected/imagem.png")
Nas configurações do nginx é preciso que você insira essa linha dentro das configurações do seu site
location /protected/ {
internal;
root /caminho/root/do/projeto/;
}
Bem é isso ai.
