Files
EWF/library/server/wsf/src/response/wsf_file_response.e
Jocelyn Fiat 45daa731cf Added put_expires_string (s: STRING) and put_expires_date (dt: DATE_TIME)
Better implementation for WSF_FILE_RESPONSE (added last modified, and other caching related info)
2012-09-10 09:27:32 +02:00

292 lines
5.7 KiB
Plaintext

note
description : "Objects that ..."
author : "$Author$"
date : "$Date$"
revision : "$Revision$"
class
WSF_FILE_RESPONSE
inherit
WSF_RESPONSE_MESSAGE
create
make,
make_with_content_type,
make_html
feature {NONE} -- Initialization
make (a_file_name: READABLE_STRING_8)
do
file_name := a_file_name
get_content_type
initialize
end
make_with_content_type (a_content_type: READABLE_STRING_8; a_filename: READABLE_STRING_8)
-- Initialize `Current'.
do
file_name := a_filename
content_type := a_content_type
initialize
end
make_html (a_filename: READABLE_STRING_8)
-- Initialize `Current'.
do
make_with_content_type ({HTTP_MIME_TYPES}.text_html, a_filename)
end
initialize
local
h: like header
do
get_file_exists
create h.make
header := h
h.put_content_type (content_type)
if file_exists then
if attached file_last_modified as dt then
h.put_last_modified (dt)
end
get_file_size
if file_size = 0 then
set_status_code ({HTTP_STATUS_CODE}.not_found)
else
set_status_code ({HTTP_STATUS_CODE}.ok)
end
else
set_status_code ({HTTP_STATUS_CODE}.not_found)
end
update_content_length
end
update_content_length
local
n: INTEGER
do
if file_exists then
n := file_size
if attached head as h then
n := n + h.count
end
if attached bottom as b then
n := n + b.count
end
else
n := 0
end
content_length := n
header.put_content_length (n)
end
feature -- Element change
set_expires_in_seconds (sec: INTEGER)
do
set_expires (sec.out)
end
set_expires (s: STRING)
do
header.put_expires_string (s)
end
set_no_cache
local
h: like header
do
h := header
h.put_expires (0)
h.put_cache_control ("no-cache, must-revalidate")
h.put_pragma_no_cache
end
feature -- Access
status_code: INTEGER assign set_status_code
header: HTTP_HEADER
content_length: INTEGER
-- Content-Length of the response
content_type: READABLE_STRING_8
-- Content-Type of the response
file_name: READABLE_STRING_8
file_exists: BOOLEAN
-- File exists?
file_size: INTEGER
-- Size of file named `file_name'
head, bottom: detachable READABLE_STRING_8
-- Eventual head and bottom part
-- before and after the file content.
feature -- Settings
answer_head_request_method: BOOLEAN assign set_answer_head_request_method
-- For HEAD request method, only http header should be sent
feature -- Element change
set_status_code (c: like status_code)
-- Set `status_code' to `c'.
require
valid_status_code: c > 0
do
status_code := c
ensure
status_code_set: status_code = c
end
set_answer_head_request_method (b: BOOLEAN)
-- Set answer_head_request_method' to `b'.
do
answer_head_request_method := b
end
set_head (s: like head)
-- Set `head' to `s'
-- it also change the `content_length' and associated value in `header'
do
head := s
update_content_length
end
set_bottom (s: like bottom)
-- Set `bottom' to `s'
-- it also change the `content_length' and associated value in `header'
do
bottom := s
update_content_length
end
feature {WSF_RESPONSE} -- Output
send_to (res: WSF_RESPONSE)
local
s: detachable READABLE_STRING_8
do
res.set_status_code (status_code)
if status_code = {HTTP_STATUS_CODE}.not_found then
else
res.put_header_text (header.string)
s := head
if s /= Void then
res.put_string (s)
end
if not answer_head_request_method then
send_file_content_to (file_name, res)
end
s := bottom
if s /= Void then
res.put_string (s)
end
end
end
feature {NONE} -- Implementation: file system helper
get_file_exists
-- Get `file_exists'
local
f: RAW_FILE
do
create f.make (file_name)
file_exists := f.exists
end
get_file_size
-- Get `file_size' from file named `file_name'
require
file_exists: file_exists
local
f: RAW_FILE
do
create f.make (file_name)
file_size := f.count
end
file_last_modified: detachable DATE_TIME
-- Get `file_size' from file named `file_name'
require
file_exists: file_exists
local
f: RAW_FILE
do
create f.make (file_name)
create Result.make_from_epoch (f.change_date)
end
file_extension (fn: STRING): STRING
-- Extension of file `fn'.
local
p: INTEGER
do
p := fn.last_index_of ('.', fn.count)
if p > 0 then
Result := fn.substring (p + 1, fn.count)
else
create Result.make_empty
end
end
feature -- Content-type related
get_content_type
-- Content type associated with `file_name'
local
m_map: HTTP_FILE_EXTENSION_MIME_MAPPING
m: detachable READABLE_STRING_8
do
create m_map.make_default
m := m_map.mime_type (file_extension (file_name).as_lower)
if m = Void then
m := {HTTP_MIME_TYPES}.application_force_download
end
content_type := m
end
feature {NONE} -- Implementation: output
send_file_content_to (fn: READABLE_STRING_8; res: WSF_RESPONSE)
-- Send the content of file `fn'
require
string_not_empty: not fn.is_empty
is_readable: (create {RAW_FILE}.make (fn)).is_readable
file_exists: file_exists
local
f: RAW_FILE
do
create f.make (fn)
check f.is_readable end
f.open_read
from
until
f.exhausted
loop
f.read_stream (4_096)
res.put_string (f.last_string)
end
f.close
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end