Compare commits

...

3 Commits

Author SHA1 Message Date
5e79751522 Updated WGI_OUTPUT_STREAM.put_file_content . 2016-10-25 13:44:44 +02:00
ac908e4efd Fixed expiration, and cache-control: max-age implementation.
Also use `FILE.date` instead of `FILE.change_date` (`change_date` is the date of the last status change, quite often same as creation date, while `date` is the last modification date).
2016-10-24 12:51:21 +02:00
885195dbaa Added WSF_RESPONSE.put_file_content (f: FILE, a_offset: INTEGER; a_count: INTEGER) to allow potential future optimization. 2016-10-24 12:47:33 +02:00
9 changed files with 145 additions and 33 deletions

View File

@@ -508,8 +508,15 @@ feature -- Others
put_expires (a_seconds: INTEGER) put_expires (a_seconds: INTEGER)
-- Put "Expires" header to `a_seconds' seconds -- Put "Expires" header to `a_seconds' seconds
-- and also "Cache-Control: max-age=.." .
-- To be supported by most browser.
local
dt: DATE_TIME
do do
put_expires_string (a_seconds.out) create dt.make_now_utc
dt.second_add (a_seconds)
put_expires_date (dt)
put_cache_control ("max-age=" + a_seconds.out)
end end
put_expires_string (a_expires: STRING) put_expires_string (a_expires: STRING)

View File

@@ -131,6 +131,12 @@ feature -- Output operation
wgi_response.put_substring (s, a_begin_index, a_end_index) wgi_response.put_substring (s, a_begin_index, a_end_index)
end end
put_file_content (f: FILE; a_offset: INTEGER; a_count: INTEGER)
-- Send `a_count' bytes from the content of file `f' starting at offset `a_offset'.
do
wgi_response.put_file_content (f, a_offset, a_count)
end
flush flush
-- Flush if it makes sense -- Flush if it makes sense
do do

View File

@@ -142,6 +142,14 @@ feature -- Output operation
deferred deferred
end end
put_file_content (f: FILE; a_offset: INTEGER; a_count: INTEGER)
-- Send `a_count' bytes from the content of file `f' starting at offset `a_offset'.
require
message_writable: message_writable
not_too_big: a_offset + a_count <= f.count
deferred
end
flush flush
-- Flush if it makes sense -- Flush if it makes sense
deferred deferred

View File

@@ -37,6 +37,53 @@ feature -- Output
end end
end end
put_file_content (a_file: FILE; a_offset: INTEGER; a_byte_count: INTEGER)
-- Send `a_byte_count' bytes from the content of file `a_file' starting at offset `a_offset'.
--| Could be redefined for optimization.
require
a_file_closed_or_openread: a_file.exists and then (a_file.is_access_readable or a_file.is_closed)
is_open_write: is_open_write
a_file_not_void: a_file /= Void
local
l_close_needed: BOOLEAN
l_remain: INTEGER
l_done: BOOLEAN
s: STRING
do
if a_file.exists and then a_file.is_access_readable then
if a_file.is_open_read then
l_close_needed := False
else
l_close_needed := True
a_file.open_read
end
if a_offset > 0 then
a_file.move (a_offset)
end
from
l_remain := a_byte_count
l_done := False
until
a_file.exhausted or l_done
loop
a_file.read_stream (l_remain.min (4_096))
s := a_file.last_string
if s.is_empty then
-- network error?
l_done := True
else
put_string (s)
l_remain := l_remain - s.count
check l_remain >= 0 end
l_done := l_remain = 0
end
end
if l_close_needed then
a_file.close
end
end
end
put_character (c: CHARACTER_8) put_character (c: CHARACTER_8)
-- Write `c' to output stream. -- Write `c' to output stream.
--| Could be redefined for optimization --| Could be redefined for optimization

View File

@@ -103,6 +103,12 @@ feature -- Output operation
output.put_substring (s, start_index, end_index) output.put_substring (s, start_index, end_index)
end end
put_file_content (f: FILE; a_offset: INTEGER; a_count: INTEGER)
-- Send `a_count' bytes from the content of file `f' starting at offset `a_offset'.
do
output.put_file_content (f, a_offset, a_count)
end
flush flush
do do
output.flush output.flush

View File

@@ -39,6 +39,7 @@ feature {NONE} -- Initialization
make_with_path (d: like document_root) make_with_path (d: like document_root)
do do
max_age := -1
if d.is_empty then if d.is_empty then
document_root := execution_environment.current_working_path document_root := execution_environment.current_working_path
else else
@@ -87,6 +88,7 @@ feature -- Access
document_root: PATH document_root: PATH
max_age: INTEGER max_age: INTEGER
-- Max age, initialized at -1 by default.
index_disabled: BOOLEAN index_disabled: BOOLEAN
-- Index disabled? -- Index disabled?
@@ -369,13 +371,15 @@ feature -- Execution
-- cache control -- cache control
create dt.make_now_utc create dt.make_now_utc
fres.header.put_cache_control ("private, max-age=" + max_age.out)
fres.header.put_utc_date (dt) fres.header.put_utc_date (dt)
if max_age >= 0 then
fres.set_max_age (max_age)
if max_age > 0 then if max_age > 0 then
dt := dt.twin dt := dt.twin
dt.second_add (max_age) dt.second_add (max_age)
end end
fres.header.put_expires_date (dt) fres.set_expires_date (dt)
end
fres.set_answer_head_request_method (req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head)) fres.set_answer_head_request_method (req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head))
res.send (fres) res.send (fres)
@@ -388,14 +392,15 @@ feature -- Execution
do do
create dt.make_now_utc create dt.make_now_utc
create h.make create h.make
h.put_cache_control ("private, max-age=" + max_age.out)
h.put_utc_date (dt) h.put_utc_date (dt)
if max_age >= 0 then
h.put_cache_control ("max-age=" + max_age.out)
if max_age > 0 then if max_age > 0 then
dt := dt.twin dt := dt.twin
dt.second_add (max_age) dt.second_add (max_age)
end end
h.put_expires_date (dt) h.put_expires_date (dt)
end
if a_utc_date /= Void then if a_utc_date /= Void then
h.put_last_modified (a_utc_date) h.put_last_modified (a_utc_date)
end end
@@ -637,7 +642,7 @@ feature {NONE} -- implementation: date time
end end
note note
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -13,6 +13,7 @@ inherit
put_character, put_character,
put_string, put_string,
put_substring, put_substring,
put_file_content,
flush, flush,
message_writable, message_writable,
message_committed message_committed
@@ -108,6 +109,13 @@ feature -- Output operation
Precursor (s, a_begin_index, a_end_index) Precursor (s, a_begin_index, a_end_index)
end end
put_file_content (f: FILE; a_offset: INTEGER; a_count: INTEGER)
-- Send `a_count' bytes from the content of file `f' starting at offset `a_offset'.
do
process_header
Precursor (f, a_offset, a_count)
end
flush flush
-- Flush if it makes sense -- Flush if it makes sense
do do

View File

@@ -1,8 +1,7 @@
note note
description : "Objects that ..." description: "Response to send a file back to the client"
author : "$Author$" date: "$Date$"
date : "$Date$" revision: "$Revision$"
revision : "$Revision$"
class class
WSF_FILE_RESPONSE WSF_FILE_RESPONSE
@@ -105,22 +104,46 @@ feature {NONE} -- Initialization
feature -- Element change feature -- Element change
set_expires_in_seconds (sec: INTEGER) set_max_age (sec: INTEGER)
do do
set_expires (sec.out) header.put_cache_control ("max-age=" + sec.out)
end
set_public_max_age (sec: INTEGER)
do
header.put_cache_control ("public, max-age=" + sec.out)
end
set_private_max_age (sec: INTEGER)
do
header.put_cache_control ("private, max-age=" + sec.out)
end
set_expires_in_seconds (sec: INTEGER)
-- Set Expires and Cache-control: max-age... to value related `sec' seconds.
do
header.put_expires (sec)
end end
set_expires (s: STRING) set_expires (s: STRING)
-- Set Expires header value to `s'.
do do
header.put_expires_string (s) header.put_expires_string (s)
end end
set_expires_date (dt: DATE_TIME)
-- Set Expires header value to date time `dt'.
do
header.put_expires_date (dt)
end
set_no_cache set_no_cache
local local
h: like header h: like header
do do
h := header h := header
h.put_expires (0) h.put_expires (0)
h.put_cache_control ("max-age=0")
h.put_cache_control ("no-cache, must-revalidate") h.put_cache_control ("no-cache, must-revalidate")
h.put_pragma_no_cache h.put_pragma_no_cache
end end
@@ -250,7 +273,7 @@ feature {NONE} -- Implementation: file system helper
f: RAW_FILE f: RAW_FILE
do do
create f.make_with_path (file_path) create f.make_with_path (file_path)
create Result.make_from_epoch (f.change_date) create Result.make_from_epoch (f.date)
end end
file_extension (fn: PATH): STRING_32 file_extension (fn: PATH): STRING_32
@@ -293,19 +316,11 @@ feature {NONE} -- Implementation: output
create f.make_with_path (fn) create f.make_with_path (fn)
check f.is_readable end check f.is_readable end
f.open_read res.put_file_content (f, 0, f.count)
from
until
f.exhausted
loop
f.read_stream (4_096)
res.put_string (f.last_string)
end
f.close
end end
note note
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -383,6 +383,16 @@ feature -- Body
increment_transfered_content_length (a_end_index - a_begin_index + 1) increment_transfered_content_length (a_end_index - a_begin_index + 1)
end end
put_file_content (f: FILE; a_offset: INTEGER; a_count: INTEGER)
-- Send `a_count' bytes from the content of file `f' starting at offset `a_offset'.
require
message_writable: message_writable
not_too_big: a_offset + a_count <= f.count
do
wgi_response.put_file_content (f, a_offset, a_count)
increment_transfered_content_length (a_count)
end
feature -- Chunk body feature -- Chunk body
put_chunk (a_content: READABLE_STRING_8; a_ext: detachable READABLE_STRING_8) put_chunk (a_content: READABLE_STRING_8; a_ext: detachable READABLE_STRING_8)
@@ -572,7 +582,7 @@ feature {NONE} -- Implemenation
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software