Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x-sendfileの有効化 #5

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions roles/apache/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@
sudo: yes
yum: name='httpd,httpd-devel'

- name: mod_xsendfile.cのダウンロード
get_url:
url=https://tn123.org/mod_xsendfile/mod_xsendfile.c
dest={{ work_dir }}

- name: mod_xsendfile.cのコンパイル
sudo: yes
command:
/usr/bin/apxs -cia {{ work_dir }}/mod_xsendfile.c

- name: attachment_controller.rbへの適用
sudo: yes
template:
src=attachments_controller.rb
dest=/var/lib/redmine/app/controllers/attachments_controller.rb

- name: production.rbへの適用
sudo: yes
template:
src=production.rb
dest=/var/lib/redmine/config/environments/production.rb

- name: Redmineディレクトリ以下のオーナーを変更
sudo: yes
command:
Expand Down
192 changes: 192 additions & 0 deletions roles/apache/templates/attachments_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# Redmine - project management software
# Copyright (C) 2006-2015 Jean-Philippe Lang
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

class AttachmentsController < ApplicationController
before_filter :find_attachment, :only => [:show, :download, :thumbnail, :destroy]
before_filter :find_editable_attachments, :only => [:edit, :update]
before_filter :file_readable, :read_authorize, :only => [:show, :download, :thumbnail]
before_filter :delete_authorize, :only => :destroy
before_filter :authorize_global, :only => :upload

accept_api_auth :show, :download, :thumbnail, :upload

def show
respond_to do |format|
format.html {
if @attachment.is_diff?
@diff = File.new(@attachment.diskfile, "rb").read
@diff_type = params[:type] || User.current.pref[:diff_type] || 'inline'
@diff_type = 'inline' unless %w(inline sbs).include?(@diff_type)
# Save diff type as user preference
if User.current.logged? && @diff_type != User.current.pref[:diff_type]
User.current.pref[:diff_type] = @diff_type
User.current.preference.save
end
render :action => 'diff'
elsif @attachment.is_text? && @attachment.filesize <= Setting.file_max_size_displayed.to_i.kilobyte
@content = File.new(@attachment.diskfile, "rb").read
render :action => 'file'
else
download
end
}
format.api
end
end

def download
if @attachment.container.is_a?(Version) || @attachment.container.is_a?(Project)
@attachment.increment_download
end

if stale?(:etag => @attachment.digest)
# images are sent inline
send_file @attachment.diskfile, :filename => filename_for_content_disposition(@attachment.filename),
:type => detect_content_type(@attachment),
:disposition => (@attachment.image? ? 'inline' : 'attachment'),
:x_sendfile => true
end
end

def thumbnail
if @attachment.thumbnailable? && tbnail = @attachment.thumbnail(:size => params[:size])
if stale?(:etag => tbnail)
send_file tbnail,
:filename => filename_for_content_disposition(@attachment.filename),
:type => detect_content_type(@attachment),
:disposition => 'inline'
end
else
# No thumbnail for the attachment or thumbnail could not be created
render :nothing => true, :status => 404
end
end

def upload
# Make sure that API users get used to set this content type
# as it won't trigger Rails' automatic parsing of the request body for parameters
unless request.content_type == 'application/octet-stream'
render :nothing => true, :status => 406
return
end

@attachment = Attachment.new(:file => request.raw_post)
@attachment.author = User.current
@attachment.filename = params[:filename].presence || Redmine::Utils.random_hex(16)
@attachment.content_type = params[:content_type].presence
saved = @attachment.save

respond_to do |format|
format.js
format.api {
if saved
render :action => 'upload', :status => :created
else
render_validation_errors(@attachment)
end
}
end
end

def edit
end

def update
if params[:attachments].is_a?(Hash)
if Attachment.update_attachments(@attachments, params[:attachments])
redirect_back_or_default home_path
return
end
end
render :action => 'edit'
end

def destroy
if @attachment.container.respond_to?(:init_journal)
@attachment.container.init_journal(User.current)
end
if @attachment.container
# Make sure association callbacks are called
@attachment.container.attachments.delete(@attachment)
else
@attachment.destroy
end

respond_to do |format|
format.html { redirect_to_referer_or project_path(@project) }
format.js
end
end

private

def find_attachment
@attachment = Attachment.find(params[:id])
# Show 404 if the filename in the url is wrong
raise ActiveRecord::RecordNotFound if params[:filename] && params[:filename] != @attachment.filename
@project = @attachment.project
rescue ActiveRecord::RecordNotFound
render_404
end

def find_editable_attachments
klass = params[:object_type].to_s.singularize.classify.constantize rescue nil
unless klass && klass.reflect_on_association(:attachments)
render_404
return
end

@container = klass.find(params[:object_id])
if @container.respond_to?(:visible?) && [email protected]?
render_403
return
end
@attachments = @container.attachments.select(&:editable?)
if @container.respond_to?(:project)
@project = @container.project
end
render_404 if @attachments.empty?
rescue ActiveRecord::RecordNotFound
render_404
end

# Checks that the file exists and is readable
def file_readable
if @attachment.readable?
true
else
logger.error "Cannot send attachment, #{@attachment.diskfile} does not exist or is unreadable."
render_404
end
end

def read_authorize
@attachment.visible? ? true : deny_access
end

def delete_authorize
@attachment.deletable? ? true : deny_access
end

def detect_content_type(attachment)
content_type = attachment.content_type
if content_type.blank? || content_type == "application/octet-stream"
content_type = Redmine::MimeType.of(attachment.filename)
end
content_type.to_s
end
end
29 changes: 29 additions & 0 deletions roles/apache/templates/production.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb

config.log_level = :info

# Code is not reloaded between requests.
config.cache_classes = true

# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true

# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true

# Disable delivery errors
config.action_mailer.raise_delivery_errors = false

# No email in production log
config.action_mailer.logger = nil

# Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log

config.action_dispatch.x_sendfile_header = "X-Sendfile"
end
4 changes: 4 additions & 0 deletions roles/apache/templates/redmine.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<Directory "/var/lib/redmine/public">
Require all granted
</Directory>
<IfModule mod_xsendfile.c>
XSendFilePath /var/lib/redmine/files
XSendFile on
</IfModule>

{{ passenger_snippet_vars.stdout }}

Expand Down