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