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