Extract several methods from Rack::File#serving#570
Conversation
Extracted methods: - mime_type - filesize - response_body
|
Thanks, generally looks good, but won't this break horribly if the file changes? |
|
I don't think so -- I'm playing around with it here and it seems to be working fine. If the file hasn't been modified since Of course, it would be pretty trivial to extract a method (not sure about the name): def cached?
last_modified = F.mtime(@path).httpdate
env['HTTP_IF_MODIFIED_SINCE'] == last_modified
endso that whoever's extending it can deal with the problem easier. |
|
But isn't the file size cached? |
|
Are you talking about the instance variable I set up in the Then yeah, I think you're right. I was only paying attention to the Rack::Directory scenario, where a new Rack::File is created for each request (at least that's how I understand it). But if your Can you confirm that's the problem you're talking about? |
|
Yes. I was referring to using Rack::File directly as an endpoint. |
|
Hopefully that takes care of it. |
There was a problem hiding this comment.
I do not like this comment. It seems more sensible to adjust the mime tables.
|
I think Rack::File should in future be avoiding setting Content-Length if it cannot determine the size of the body by stat. In the case where it cannot, it should be deferring to Rack::ContentLength and/or Rack::Chunked, to avoid slurping until the last responsible moment. |
|
In general, these changes are ok, I'm concerned about introducing comments that enforce inheritance as a public API. I would prefer that these are removed. |
Causes a bug if a file changes between requests.
|
Good point -- I didn't know about the MIME tables when I added those comments. Just removed the offending lines. |
It appears that the intention of rack#570 was to provide a seam on Rack::File where the response body may be provided by an overriding class (see their markdown example). However e0ac32 overwrites the value of response[2] (the body) after this is set. This is the simplest possible fix, ignore the step of overwriting if a value is already set. However it's worth noting that the design of the entire method would probably be served well to improve. At this point, I don't want to take that on. Also of note, there may very well be a latent bug in the previous implementation. Specifically, when response_body is overridden, it affects the calculation of filesize, therefore if the method is overridden the filesize of that overridden response_body would be returned which is probably not the correct size for the response read from the path. If that is in fact a defect, this PR may very well address it to, though it is unverified.
It appears that the intention of rack#570 was to provide a seam on Rack::File where the response body may be provided by an overriding class (see their markdown example). However e0ac32 overwrites the value of response[2] (the body) after this is set. This is the simplest possible fix, ignore the step of overwriting if a value is already set. However it's worth noting that the design of the entire method would probably be served well to improve. At this point, I don't want to take that on. Also of note, there may very well be a latent bug in the previous implementation. Specifically, when response_body is overridden, it affects the calculation of filesize, therefore if the method is overridden the filesize of that overridden response_body would be returned which is probably not the correct size for the response read from the path. If that is in fact a defect, this PR may very well address it to, though it is unverified.
Extracted methods:
Motivation
Example of Customization
Let's say you have a basic Rack::Directory setup.
But you have a lot of markdown files in the directory, and you want to compile and render them on the fly. That requires modifying the mime type, the response body, and the filesize.
By extracting the methods out of
Rack::File#serving, you only have to overwrite two methods (file_size is calculated based on the newresponse_bodyThe
config.ruwould look something like this:Other stuff
This doesn't change the behavior of Rack, it just makes it easier to customize and to work on in the future. Because of that, I didn't write any tests. Let me know if I should.