Forums » Development »
Limit number of concurrent downloads
Added by Richard Rauch over 10 years ago
Because of 2 reasons I want to limit the number of concurrent downloads
A: I have frequently DoS attacks on my server, which are initiating a storm of download requests on huge files
B: when a user wants to download a huge file, it needs time and it seems, that the server is not responding. Then sometimes a user is initating the download request again several times
In both cases there are concurrent download requests, which are causing huge memory consumption on the server. When there is no further memory, the Redmine processes are crashing and the server stops.
Therefore I am trying to find anyhow a solutions.
My idea is now to change the attachments controller behaviour.
!!!Please excuse, I do not have server programming experience, no Ruby, no Rails experience!!!
I tried following changes in attachments_controller.rb:
def download
if @attachment.container.is_a?(Version) || @attachment.container.is_a?(Project)
@attachment.increment_download
end
if stale?(:etag => @attachment.digest)
if User.current.dnld_curr > 0
render_403 :message => :'Please finish previous download first'
else
temp = User.current.dnld_curr;
temp = temp +1;
User.current.update_column(:dnld_curr,temp)
temp = User.current.dnld_cnt;
temp = temp +1;
User.current.update_column(:dnld_cnt,temp)
# 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')
temp = User.current.dnld_curr;
if temp > 0
temp = temp - 1;
User.current.update_column(:dnld_curr,temp)
end
end
end
end
My idea is to count the concurrent downloads and restrict it e.g. to one.
In principle my code works (I added the rows to the database). The dnld_curr counter is incrementing and decrementing, BUT the value is decremented immediately, before the download is finished. I cannot detect the end of the download.
Has anybody an idea, how to improve my code?
I know, it is very dirty to patch the code directly. But I need a fast solution. My server is down nearby every morning because of some chinese hackers.
Many Thanks
Richard
Replies (1)
RE: Limit number of concurrent downloads - Added by Martin Denizet (redmine.org team member) over 10 years ago
Hello Richard,
I don't see a good way to implement this in Rails because from what I know there is no callback to send_file
(to know when the download is completed, it's an async method).
Maybe you could be using time to limit downloads:
def download
if @attachment.container.is_a?(Version) || @attachment.container.is_a?(Project)
@attachment.increment_download
end
if stale?(:etag => @attachment.digest)
downloads_blocked_until = User.current.last_download + 10.minutes
if downloads_blocked_until < DateTime.now
render_403 :message => :'One download allowed every 10 minutes'
else
User.current.update_column(:last_download ,DateTime.now)
# 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')
end
end
end
Maybe the solution for you would be to make a stream to have more control on the download.
I can't think of a way to implement this on the web server itself.
Cheers,