Skip to content

Commit

Permalink
local-uploads: Add support for using django-sendfile.
Browse files Browse the repository at this point in the history
This commit will be introducing support for using django-sendfile for
serving uploads (attachments) when using LocalStorage. For the dev
environment the django backend will be used but for the Production nginx
will be used to serve files but after django performs authentication
checks.

Fixes: #320, #291.
  • Loading branch information
adnrs96 committed Apr 16, 2017
1 parent 2c88e07 commit 73e83a9
Show file tree
Hide file tree
Showing 6 changed files with 20 additions and 15 deletions.
3 changes: 2 additions & 1 deletion puppet/zulip/files/nginx/sites-available/zulip-enterprise
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ server {
ssl_certificate /etc/ssl/certs/zulip.combined-chain.crt;
ssl_certificate_key /etc/ssl/private/zulip.key;

location /user_uploads {
location /serve_uploads {
internal;
add_header X-Content-Type-Options nosniff;
include /etc/nginx/zulip-include/uploads.types;
alias /home/zulip/uploads/files;
Expand Down
5 changes: 5 additions & 0 deletions requirements/common.txt
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,8 @@ git+https://github.com/rafaelmartins/pyoembed.git@eb9901917c2a44b49e2887c077ead8
# used in development for some tests and in production for things like
# Nagios checks.
api/

# Needed for serving uploaded files from nginx but perform auth checks in django.
# We are using a commit from a PR https://github.com/johnsensible/django-sendfile/pull/64
# in Django-sendfile repo as it might be sometime before it gets merged.
git+https://github.com/adnrs96/django-sendfile.git@f45fac5fdd83e7d42a8d5275038e33f8c2cdb920#egg=django-sendfile==0.3.12
9 changes: 2 additions & 7 deletions zerver/views/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,19 @@
from zerver.lib.validator import check_bool
from zerver.models import UserProfile, validate_attachment_request
from django.conf import settings
from sendfile import sendfile

def serve_s3(request, url_path):
# type: (HttpRequest, str) -> HttpResponse
uri = get_signed_upload_url(url_path)
return redirect(uri)

# TODO: Rewrite this once we have django-sendfile
def serve_local(request, path_id):
# type: (HttpRequest, str) -> HttpResponse
import os
import mimetypes
local_path = get_local_file_path(path_id)
if local_path is None:
return HttpResponseNotFound('<p>File not found</p>')
filename = os.path.basename(local_path)
response = FileResponse(open(local_path, 'rb'),
content_type = mimetypes.guess_type(filename))
return response
return sendfile(request, local_path)

@has_request_variables
def serve_file_backend(request, user_profile, realm_id_str, filename):
Expand Down
2 changes: 2 additions & 0 deletions zproject/dev_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,5 @@
# Don't require anything about password strength in development
PASSWORD_MIN_LENGTH = 0
PASSWORD_MIN_ZXCVBN_QUALITY = 0
# Make sendfile use django to serve files in development
SENDFILE_BACKEND = 'sendfile.backends.development'
13 changes: 6 additions & 7 deletions zproject/prod_settings_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,21 +166,20 @@
# directly on the Zulip server. If file storage in Amazon S3 is
# desired, you can configure that as follows:
#
# (1) Set s3_key and s3_secret_key in /etc/zulip/zulip-secrets.conf to
# Set s3_key and s3_secret_key in /etc/zulip/zulip-secrets.conf to
# be the S3 access and secret keys that you want to use, and setting
# the S3_AUTH_UPLOADS_BUCKET and S3_AVATAR_BUCKET to be the S3 buckets
# you've created to store file uploads and user avatars, respectively.
# Then restart Zulip (scripts/restart-zulip).
#
# (2) Edit /etc/nginx/sites-available/zulip-enterprise to comment out
# the nginx configuration for /user_uploads and /user_avatars (see
# https://github.com/zulip/zulip/issues/291 for discussion of a better
# solution that won't be automatically reverted by the Zulip upgrade
# script), and then restart nginx.
LOCAL_UPLOADS_DIR = "/home/zulip/uploads"
#S3_AUTH_UPLOADS_BUCKET = ""
#S3_AVATAR_BUCKET = ""

# Setup the version of NGINX which is being used for this installation.
# By default a NGINX version greater that 1.5.9 is assumed but if you are using
# a older version, it is necessary to specify it here.
# NGINX_VERSION = '1.4.6'

# Maximum allowed size of uploaded files, in megabytes. DO NOT SET
# ABOVE 80MB. The file upload implementation doesn't support chunked
# uploads, so browsers will crash if you try uploading larger files.
Expand Down
3 changes: 3 additions & 0 deletions zproject/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ def get_secret(key):
# Import prod_settings after determining the deployment/machine type
if PRODUCTION:
from .prod_settings import *
SENDFILE_BACKEND = 'sendfile.backends.nginx'
SENDFILE_ROOT = os.path.join(LOCAL_UPLOADS_DIR, 'files')
SENDFILE_URL = '/serve_uploads'
else:
from .dev_settings import *

Expand Down

0 comments on commit 73e83a9

Please sign in to comment.