# File lib/mongrel/handlers.rb, line 182
182:     def send_file(req_path, request, response, header_only=false)
183: 
184:       stat = File.stat(req_path)
185: 
186:       # Set the last modified times as well and etag for all files
187:       mtime = stat.mtime
188:       # Calculated the same as apache, not sure how well the works on win32
189:       etag = Const::ETAG_FORMAT % [mtime.to_i, stat.size, stat.ino]
190: 
191:       modified_since = request.params[Const::HTTP_IF_MODIFIED_SINCE]
192:       none_match = request.params[Const::HTTP_IF_NONE_MATCH]
193: 
194:       # test to see if this is a conditional request, and test if
195:       # the response would be identical to the last response
196:       same_response = case
197:                       when modified_since && !last_response_time = Time.httpdate(modified_since) rescue nil : false
198:                       when modified_since && last_response_time > Time.now                                  : false
199:                       when modified_since && mtime > last_response_time                                     : false
200:                       when none_match     && none_match == '*'                                              : false
201:                       when none_match     && !none_match.strip.split(/\s*,\s*/).include?(etag)              : false
202:                       else modified_since || none_match  # validation successful if we get this far and at least one of the header exists
203:                       end
204: 
205:       header = response.header
206:       header[Const::ETAG] = etag
207: 
208:       if same_response
209:         response.start(304) {}
210:       else
211:         # first we setup the headers and status then we do a very fast send on the socket directly
212:         response.status = 200
213:         header[Const::LAST_MODIFIED] = mtime.httpdate
214: 
215:         # set the mime type from our map based on the ending
216:         dot_at = req_path.rindex('.')
217:         if dot_at
218:           header[Const::CONTENT_TYPE] = MIME_TYPES[req_path[dot_at .. -1]] || @default_content_type
219:         else
220:           header[Const::CONTENT_TYPE] = @default_content_type
221:         end
222: 
223:         # send a status with out content length
224:         response.send_status(stat.size)
225:         response.send_header
226: 
227:         if not header_only
228:           response.send_file(req_path, stat.size < Const::CHUNK_SIZE * 2)
229:         end
230:       end
231:     end