Complete.

This commit is contained in:
colin-adams
2012-06-15 08:38:30 -07:00
parent c9b11a6401
commit f6d64b42c6

View File

@@ -58,17 +58,131 @@ Now we are in a position to do some negotiating. At the beginning of your handle
local local
l_media_variants: MEDIA_TYPE_VARIANT_RESULTS l_media_variants: MEDIA_TYPE_VARIANT_RESULTS
l_is_head: BOOLEAN
h: HTTP_HEADER
l_msg: STRING
do do
l_is_head := False -- or `True' if this is for a HEAD handler
l_media_variants:= conneg.media_type_preference (mime_types_supported, a_req.http_accept) l_media_variants:= conneg.media_type_preference (mime_types_supported, a_req.http_accept)
if not l_media_variants.is_acceptable then if not l_media_variants.is_acceptable then
send_unacceptable_media_type (a_res) send_unacceptable_media_type (a_res, l_is_head)
elseif not conneg.charset_preference (charsets_supported, a_req.http_accept_charset).is_acceptable then elseif not conneg.charset_preference (charsets_supported, a_req.http_accept_charset).is_acceptable then
send_unacceptable_charset (a_res) send_unacceptable_charset (a_res, l_is_head)
elseif not conneg.encoding_preference (encodings_supported, a_req.http_accept_encoding).is_acceptable then elseif not conneg.encoding_preference (encodings_supported, a_req.http_accept_encoding).is_acceptable then
send_unacceptable_encoding (a_res) send_unacceptable_encoding (a_res, l_is_head)
elseif not conneg.language_preference (languages_supported, a_req.http_accept_language).is_acceptable then elseif not conneg.language_preference (languages_supported, a_req.http_accept_language).is_acceptable then
send_unacceptable_encoding (a_res) send_unacceptable_encoding (a_res)
else else
-- We have agreed a representation, let's go and serve it to the client -- We have agreed a representation, let's go and serve it to the client
` `
Now for those `send_unnacceptable_...` routines. They are fairly simple:
send_unacceptable_media_type (a_res: WSF_RESPONSE; a_is_head: BOOLEAN) is
-- Send error result as text/plain that the media type is unnacceptable.
require
a_res_not_void: a_res /= Void
status_not_set: not a_res.status_is_set
header_not_committed: not a_res.header_committed
local
l_error_text: STRING
do
l_error_text := "The requested media type(s) is/are not supported by this server."
send_unacceptable (a_res, a_is_head, l_error_text)
end
send_unacceptable_charset (a_res: WSF_RESPONSE; a_is_head: BOOLEAN) is
-- Send error result as text/plain that the character set is unnacceptable.
require
a_res_not_void: a_res /= Void
status_not_set: not a_res.status_is_set
header_not_committed: not a_res.header_committed
local
l_error_text: STRING
do
l_error_text := "The requested character set(s) is/are not supported by this server. Only UTF-8 is supported."
send_unacceptable (a_res, a_is_head, l_error_text)
end
send_unacceptable_encoding (a_res: WSF_RESPONSE; a_is_head: BOOLEAN) is
-- Send error result as text/plain that the encoding is unnacceptable.
require
a_res_not_void: a_res /= Void
status_not_set: not a_res.status_is_set
header_not_committed: not a_res.header_committed
local
l_error_text: STRING
do
l_error_text := "The requested encoding(s) is/are not supported by this server. Only identity is supported."
send_unacceptable (a_res, a_is_head, l_error_text)
end
send_unacceptable_language (a_res: WSF_RESPONSE; a_is_head: BOOLEAN) is
-- Send error result as text/plain that the language unnacceptable.
require
a_res_not_void: a_res /= Void
status_not_set: not a_res.status_is_set
header_not_committed: not a_res.header_committed
local
l_error_text: STRING
do
l_error_text := "The requested language(s) is/are not supported by this server. Only en (English) is supported."
send_unacceptable (a_res, a_is_head, l_error_text)
end
send_unacceptable (a_res: WSF_RESPONSE; a_is_head: BOOLEAN; a_error_text: STRING) is
-- Send a_error_text as text/plain that a header is unnacceptable.
require
a_res_not_void: a_res /= Void
status_not_set: not a_res.status_is_set
header_not_committed: not a_res.header_committed
a_error_text_not_void: a_error_text /= Void
local
h: HTTP_HEADER
do
create h.make
set_content_type (h, Void)
h.put_content_length (a_error_text.count)
h.put_current_date
a_res.set_status_code ({HTTP_STATUS_CODE}.not_acceptable)
a_res.put_header_text (h.string)
if not a_is_head then
a_res.put_string (a_error_text)
end
end
We'll see that `set_content_type` routine in a bit. But for now, we just have to generate the response. Let's go back to that `else ...` bit:
else
-- We have agreed a representation, let's go and serve it to the client
create h.make
set_content_type (h, a_media_variants)
if a_media_variants.media_type ~ {HTTP_MIME_TYPES}.application_xml then
l_msg := "<?xml version='1.0' encoding='UTF-8' ?><my-tag>etc."
else
l_msg := json.value (<some-value>).representation
end
h.put_content_length (l_msg.count)
h.put_current_date
a_res.set_status_code ({HTTP_STATUS_CODE}.ok)
a_res.put_header_text (h.string)
if not a_is_head then
a_res.put_string (l_msg)
end
There's that `set_content_type` again. Finally, we will take a look at it:
set_content_type (a_h: HTTP_HEADER; a_media_variants: MEDIA_TYPE_VARIANT_RESULTS) is
-- Set the content=type header in `a_h' according to `a_media_variants'.
require
a_h_not_void: a_h /= Void
do
if a_media_variants = Void or else not a_media_variants.is_acceptable then
a_h.put_content_type ({HTTP_MIME_TYPES}.text_plain)
else
a_h.put_content_type (a_media_variants.media_type)
end
a_h.put_header_key_value ({HTTP_HEADER_NAMES}.header_vary, {HTTP_HEADER_NAMES}.header_accept)
end
Firstly, if we haven't agreed a media-type, then we send our (negative) response as `plain/text`. Otherwise we will send the response in the agreed media-type. But in each case we add a `Vary:Accept` header. This tells proxy caches that they have to check the media-type before returning a cached result, as there may be a different representation available. Since we do not vary our representation by language, charset or encoding, we don't add `Vary:Accept-Language,Accept-Charset,Accept-Encoding`. But if we were to negotiate different representations on those dimensions also, we would need to list the appropriate headers in the `Vary` header.