Files
EWF/doc/wiki/EWSGI/specification.md

26 KiB

WARNING THIS PAGE IS IN PROGRESS, AS IT IS NOW, IT NEEDS UPDATE SINCE IT DOES NOT REFLECT THE FUTURE INTERFACE

The Eiffel Web Server Gateway Interface

Preface

This specification is a proposition based on recent discussion on the mailing list. This is work in progress, so far nothing had been decided. You can find another proposal at http://eiffel.seibostudios.se/wiki/EWSGI , it has common background and goal, however still differ on specific parts. The main goal for now is to unified those 2 specifications.


Note the following is work in progress, and reflect a specification proposal, rather than the final specification. 2011-08-01

For now, the specification from EWF is done in Eiffel interface please see: https://github.com/Eiffel-World/Eiffel-Web-Framework/tree/master/library/server/ewsgi/specification

WGI_APPLICATION

deferred class 
	WGI_APPLICATION

feature {NONE} -- Execution

	execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER)
			-- Execute the request
			-- See `req.input' for input stream
			--     `req.meta_variables' for the CGI meta variable
			-- and `res' for the output buffer
		require
			res_status_unset: not res.status_is_set
		deferred
		ensure
			res_status_set: res.status_is_set
	end
	
end

WGI_REQUEST

deferred class 
	WGI_REQUEST

feature -- Access: Input

	input: WGI_INPUT_STREAM
			-- Server input channel
		deferred
		end
	
feature -- Access: extra values

	request_time: detachable DATE_TIME
			-- Request time (UTC)
		deferred
		end
	
feature -- Access: CGI meta variables		

	meta_variable (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE
			-- Environment variable related to `a_name'
		require
			a_name_valid: a_name /= Void and then not a_name.is_empty
		deferred
		end

	meta_string_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
			-- Environment variable related to `a_name'
		require
			a_name_valid: a_name /= Void and then not a_name.is_empty
		do
			if attached meta_variable (a_name) as val then
				Result := val.as_string
			end
		end

	meta_variables: ITERABLE [WGI_VALUE]
			-- These variables are specific to requests made with HTTP.
			-- Interpretation of these variables may depend on the value of
			-- SERVER_PROTOCOL.
			--
			-- Environment variables with names beginning with "HTTP_" contain
			-- header data read from the client, if the protocol used was HTTP.
			-- The HTTP header name is converted to upper case, has all
			-- occurrences of "-" replaced with "_" and has "HTTP_" prepended to
			-- give the environment variable name. The header data may be
			-- presented as sent by the client, or may be rewritten in ways which
			-- do not change its semantics. If multiple headers with the same
			-- field-name are received then they must be rewritten as a single
			-- header having the same semantics. Similarly, a header that is
			-- received on more than one line must be merged onto a single line.
			-- The server must, if necessary, change the representation of the
			-- data (for example, the character set) to be appropriate for a CGI
			-- environment variable.
			--
			-- The server is not required to create environment variables for all
			-- the headers that it receives. In particular, it may remove any
			-- headers carrying authentication information, such as
			-- "Authorization"; it may remove headers whose value is available to
			-- the script via other variables, such as "Content-Length" and
			-- "Content-Type".
			--
			-- For convenience it might also include the following CGI entries
		deferred
		end
	
feature -- Common Gateway Interface - 1.1       8 January 1996

	auth_type: detachable READABLE_STRING_32
			-- This variable is specific to requests made via the "http"
			-- scheme.
			--
			-- If the Script-URI required access authentication for external
			-- access, then the server MUST set the value of this variable
			-- from the 'auth-scheme' token in the request's "Authorization"
			-- header field. Otherwise it is set to NULL.
			--
			--  AUTH_TYPE   = "" | auth-scheme
			--  auth-scheme = "Basic" | "Digest" | token
			--
			-- HTTP access authentication schemes are described in section 11
			-- of the HTTP/1.1 specification [8]. The auth-scheme is not
			-- case-sensitive.
			--
			-- Servers MUST provide this metavariable to scripts if the
			-- request header included an "Authorization" field that was
			-- authenticated.
		deferred
		end

	content_length: detachable READABLE_STRING_32
			-- This metavariable is set to the size of the message-body
			-- entity attached to the request, if any, in decimal number of
			-- octets. If no data are attached, then this metavariable is
			-- either NULL or not defined. The syntax is the same as for the
			-- HTTP "Content-Length" header field (section 14.14, HTTP/1.1
			-- specification [8]).
			--
			--  CONTENT_LENGTH = "" | 1*digit
			--
			-- Servers MUST provide this metavariable to scripts if the
			-- request was accompanied by a message-body entity.
		deferred
		end

	content_length_value: NATURAL_64
			-- Integer value related to `content_length"
		deferred
		end

	content_type: detachable READABLE_STRING_32
			-- If the request includes a message-body, CONTENT_TYPE is set to
			-- the Internet Media Type [9] of the attached entity if the type
			-- was provided via a "Content-type" field in the request header,
			-- or if the server can determine it in the absence of a supplied
			-- "Content-type" field. The syntax is the same as for the HTTP
			-- "Content-Type" header field.
			--
			--  CONTENT_TYPE = "" | media-type
			--  media-type   = type "/" subtype *( ";" parameter)
			--  type         = token
			--  subtype      = token
			--  parameter    = attribute "=" value
			--  attribute    = token
			--  value        = token | quoted-string
			--
			-- The type, subtype, and parameter attribute names are not
			-- case-sensitive. Parameter values MAY be case sensitive. Media
			-- types and their use in HTTP are described in section 3.7 of
			-- the HTTP/1.1 specification [8].
			--
			-- Example:
			--
			--  application/x-www-form-urlencoded
			--
			-- There is no default value for this variable. If and only if it
			-- is unset, then the script MAY attempt to determine the media
			-- type from the data received. If the type remains unknown, then
			-- the script MAY choose to either assume a content-type of
			-- application/octet-stream or reject the request with a 415
			-- ("Unsupported Media Type") error. See section 7.2.1.3 for more
			-- information about returning error status values.
			--
			-- Servers MUST provide this metavariable to scripts if a
			-- "Content-Type" field was present in the original request
			-- header. If the server receives a request with an attached
			-- entity but no "Content-Type" header field, it MAY attempt to
			-- determine the correct datatype, or it MAY omit this
			-- metavariable when communicating the request information to the
			-- script.
		deferred
		end

	gateway_interface: READABLE_STRING_32
			-- This metavariable is set to the dialect of CGI being used by
			-- the server to communicate with the script. Syntax:
			--
			--  GATEWAY_INTERFACE = "CGI" "/" major "." minor
			--  major             = 1*digit
			--  minor             = 1*digit
			--
			-- Note that the major and minor numbers are treated as separate
			-- integers and hence each may be more than a single digit. Thus
			-- CGI/2.4 is a lower version than CGI/2.13 which in turn is
			-- lower than CGI/12.3. Leading zeros in either the major or the
			-- minor number MUST be ignored by scripts and SHOULD NOT be
			-- generated by servers.
			--
			-- This document defines the 1.1 version of the CGI interface
			-- ("CGI/1.1").
			--
			-- Servers MUST provide this metavariable to scripts.
			--
			-- The version of the CGI specification to which this server
			-- complies.  Syntax:
			--
			--  GATEWAY_INTERFACE =  "CGI" "/" 1*digit "." 1*digit
			--
			-- Note that the major and minor numbers are treated as separate
			-- integers and that each may be incremented higher than a single
			-- digit.  Thus CGI/2.4 is a lower version than CGI/2.13 which in
			-- turn is lower than CGI/12.3. Leading zeros must be ignored by
			-- scripts and should never be generated by servers.
		deferred
		end

	path_info: READABLE_STRING_32
			-- The PATH_INFO metavariable specifies a path to be interpreted
			-- by the CGI script. It identifies the resource or sub-resource
			-- to be returned by the CGI script, and it is derived from the
			-- portion of the URI path following the script name but
			-- preceding any query data. The syntax and semantics are similar
			-- to a decoded HTTP URL 'path' token (defined in RFC 2396 [4]),
			-- with the exception that a PATH_INFO of "/" represents a single
			-- void path segment.
			--
			--  PATH_INFO = "" | ( "/" path )
			--  path      = segment *( "/" segment )
			--  segment   = *pchar
			--  pchar     = <any CHAR except "/">
			--
			-- The PATH_INFO string is the trailing part of the <path>
			-- component of the Script-URI (see section 3.2) that follows the
			-- SCRIPT_NAME portion of the path.
			--
			-- Servers MAY impose their own restrictions and limitations on
			-- what values they will accept for PATH_INFO, and MAY reject or
			-- edit any values they consider objectionable before passing
			-- them to the script.
			--
			-- Servers MUST make this URI component available to CGI scripts.
			-- The PATH_INFO value is case-sensitive, and the server MUST
			-- preserve the case of the PATH_INFO element of the URI when
			-- making it available to scripts.
		deferred
		end

	path_translated: detachable READABLE_STRING_32
			-- PATH_TRANSLATED is derived by taking any path-info component
			-- of the request URI (see section 6.1.6), decoding it (see
			-- section 3.1), parsing it as a URI in its own right, and
			-- performing any virtual-to-physical translation appropriate to
			-- map it onto the server's document repository structure. If the
			-- request URI includes no path-info component, the
			-- PATH_TRANSLATED metavariable SHOULD NOT be defined.
			--
			--
			--  PATH_TRANSLATED = *CHAR
			--
			-- For a request such as the following:
			--
			--  http://somehost.com/cgi-bin/somescript/this%2eis%2epath%2einfo
			--
			-- the PATH_INFO component would be decoded, and the result
			-- parsed as though it were a request for the following:
			--
			--  http://somehost.com/this.is.the.path.info
			--
			-- This would then be translated to a location in the server's
			-- document repository, perhaps a filesystem path something like
			-- this:
			--
			--  /usr/local/www/htdocs/this.is.the.path.info
			--
			-- The result of the translation is the value of PATH_TRANSLATED.
			--
			-- The value of PATH_TRANSLATED may or may not map to a valid
			-- repository location. Servers MUST preserve the case of the
			-- path-info segment if and only if the underlying repository
			-- supports case-sensitive names. If the repository is only
			-- case-aware, case-preserving, or case-blind with regard to
			-- document names, servers are not required to preserve the case
			-- of the original segment through the translation.
			--
			-- The translation algorithm the server uses to derive
			-- PATH_TRANSLATED is implementation defined; CGI scripts which
			-- use this variable may suffer limited portability.
			--
			-- Servers SHOULD provide this metavariable to scripts if and
			-- only if the request URI includes a path-info component.
		deferred
		end

	query_string: READABLE_STRING_32
			-- A URL-encoded string; the <query> part of the Script-URI. (See
			-- section 3.2.)
			--
			--  QUERY_STRING = query-string
			--  query-string = *uric
			-- The URL syntax for a query string is described in section 3 of
			-- RFC 2396 [4].
			--
			-- Servers MUST supply this value to scripts. The QUERY_STRING
			-- value is case-sensitive. If the Script-URI does not include a
			-- query component, the QUERY_STRING metavariable MUST be defined
			-- as an empty string ("").
		deferred
		end

	remote_addr: READABLE_STRING_32
			-- The IP address of the client sending the request to the
			-- server. This is not necessarily that of the user agent (such
			-- as if the request came through a proxy).
			--
			--  REMOTE_ADDR  = hostnumber
			--  hostnumber   = ipv4-address | ipv6-address
			-- The definitions of ipv4-address and ipv6-address are provided
			-- in Appendix B of RFC 2373 [13].
			--
			-- Servers MUST supply this value to scripts.
		deferred
		end

	remote_host: detachable READABLE_STRING_32
			-- The fully qualified domain name of the client sending the
			-- request to the server, if available, otherwise NULL. (See
			-- section 6.1.9.) Fully qualified domain names take the form as
			-- described in section 3.5 of RFC 1034 [10] and section 2.1 of
			-- RFC 1123 [5]. Domain names are not case sensitive.
			--
			-- Servers SHOULD provide this information to scripts.
		deferred
		end

	remote_ident: detachable READABLE_STRING_32
			-- The identity information reported about the connection by a
			-- RFC 1413 [11] request to the remote agent, if available.
			-- Servers MAY choose not to support this feature, or not to
			-- request the data for efficiency reasons.
			--
			--  REMOTE_IDENT = *CHAR
			--
			-- The data returned may be used for authentication purposes, but
			-- the level of trust reposed in them should be minimal.
			--
			-- Servers MAY supply this information to scripts if the RFC1413
			-- [11] lookup is performed.
		deferred
		end

	remote_user: detachable READABLE_STRING_32
			-- If the request required authentication using the "Basic"
			-- mechanism (i.e., the AUTH_TYPE metavariable is set to
			-- "Basic"), then the value of the REMOTE_USER metavariable is
			-- set to the user-ID supplied. In all other cases the value of
			-- this metavariable is undefined.
			--
			--  REMOTE_USER = *OCTET
			--
			-- This variable is specific to requests made via the HTTP
			-- protocol.
			--
			-- Servers SHOULD provide this metavariable to scripts.
		deferred
		end

	request_method: READABLE_STRING_32
			-- The REQUEST_METHOD metavariable is set to the method with
			-- which the request was made, as described in section 5.1.1 of
			-- the HTTP/1.0 specification [3] and section 5.1.1 of the
			-- HTTP/1.1 specification [8].
			--
			--  REQUEST_METHOD   = http-method
			--  http-method      = "GET" | "HEAD" | "POST" | "PUT" | "DELETE"
			--                     | "OPTIONS" | "TRACE" | extension-method
			--  extension-method = token
			--
			-- The method is case sensitive. CGI/1.1 servers MAY choose to
			-- process some methods directly rather than passing them to
			-- scripts.
			--
			-- This variable is specific to requests made with HTTP.
			--
			-- Servers MUST provide this metavariable to scripts.
		deferred
		end

	script_name: READABLE_STRING_32
			-- The SCRIPT_NAME metavariable is set to a URL path that could
			-- identify the CGI script (rather than the script's output). The
			-- syntax and semantics are identical to a decoded HTTP URL
			-- 'path' token (see RFC 2396 [4]).
			--
			--  SCRIPT_NAME = "" | ( "/" [ path ] )
			--
			-- The SCRIPT_NAME string is some leading part of the <path>
			-- component of the Script-URI derived in some implementation
			-- defined manner. No PATH_INFO or QUERY_STRING segments (see
			-- sections 6.1.6 and 6.1.8) are included in the SCRIPT_NAME
			-- value.
			--
			-- Servers MUST provide this metavariable to scripts.
		deferred
		end

	server_name: READABLE_STRING_32
			-- The SERVER_NAME metavariable is set to the name of the server,
			-- as derived from the <host> part of the Script-URI (see section
			-- 3.2).
			--
			--  SERVER_NAME = hostname | hostnumber
			--
			-- Servers MUST provide this metavariable to scripts.
		deferred
		end

	server_port: INTEGER_32
			-- The SERVER_PORT metavariable is set to the port on which the
			-- request was received, as used in the <port> part of the
			-- Script-URI.
			--
			--  SERVER_PORT = 1*digit
			--
			-- If the <port> portion of the script-URI is blank, the actual
			-- port number upon which the request was received MUST be
			-- supplied.
			--
			-- Servers MUST provide this metavariable to scripts.
		deferred
		end

	server_protocol: READABLE_STRING_32
			-- The SERVER_PROTOCOL metavariable is set to the name and
			-- revision of the information protocol with which the request
			-- arrived. This is not necessarily the same as the protocol
			-- version used by the server in its response to the client.
			--
			--  SERVER_PROTOCOL   = HTTP-Version | extension-version
			--                      | extension-token
			--  HTTP-Version      = "HTTP" "/" 1*digit "." 1*digit
			--  extension-version = protocol "/" 1*digit "." 1*digit
			--  protocol          = 1*( alpha | digit | "+" | "-" | "." )
			--  extension-token   = token
			--
			-- 'protocol' is a version of the <scheme> part of the
			-- Script-URI, but is not identical to it. For example, the
			-- scheme of a request may be "https" while the protocol remains
			-- "http". The protocol is not case sensitive, but by convention,
			-- 'protocol' is in upper case.
			--
			-- A well-known extension token value is "INCLUDED", which
			-- signals that the current document is being included as part of
			-- a composite document, rather than being the direct target of
			-- the client request.
			--
			-- Servers MUST provide this metavariable to scripts.
		deferred
		end

	server_software: READABLE_STRING_32
			-- The SERVER_SOFTWARE metavariable is set to the name and
			-- version of the information server software answering the
			-- request (and running the gateway).
			--
			--  SERVER_SOFTWARE = 1*product
			--  product         = token [ "/" product-version ]
			--  product-version = token
			-- Servers MUST provide this metavariable to scripts.
		deferred
		end
	
feature -- HTTP_*

	http_accept: detachable READABLE_STRING_32
			-- Contents of the Accept: header from the current request, if there is one.
			-- Example: 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
		deferred
		end

	http_accept_charset: detachable READABLE_STRING_32
			-- Contents of the Accept-Charset: header from the current request, if there is one.
			-- Example: 'iso-8859-1,*,utf-8'.
		deferred
		end

	http_accept_encoding: detachable READABLE_STRING_32
			-- Contents of the Accept-Encoding: header from the current request, if there is one.
			-- Example: 'gzip'.
		deferred
		end

	http_accept_language: detachable READABLE_STRING_32
			-- Contents of the Accept-Language: header from the current request, if there is one.
			-- Example: 'en'.
		deferred
		end

	http_connection: detachable READABLE_STRING_32
			-- Contents of the Connection: header from the current request, if there is one.
			-- Example: 'Keep-Alive'.
		deferred
		end

	http_host: detachable READABLE_STRING_32
			-- Contents of the Host: header from the current request, if there is one.
		deferred
		end

	http_referer: detachable READABLE_STRING_32
			-- The address of the page (if any) which referred the user agent to the current page.
			-- This is set by the user agent.
			-- Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature.
			-- In short, it cannot really be trusted.
		deferred
		end

	http_user_agent: detachable READABLE_STRING_32
			-- Contents of the User-Agent: header from the current request, if there is one.
			-- This is a string denoting the user agent being which is accessing the page.
			-- A typical example is: Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586).
			-- Among other things, you can use this value to tailor your page's
			-- output to the capabilities of the user agent.
		deferred
		end

	http_authorization: detachable READABLE_STRING_32
			-- Contents of the Authorization: header from the current request, if there is one.
		deferred
		end
	
feature -- Extra CGI environment variables

	request_uri: READABLE_STRING_32
			-- The URI which was given in order to access this page; for instance, '/index.html'.
		deferred
		end

	orig_path_info: detachable READABLE_STRING_32
			-- Original version of path_info before processed by Current environment
		deferred
		end
	
feature -- Query string Parameters

	query_parameters: ITERABLE [WGI_VALUE]
			-- Variables extracted from QUERY_STRING
		deferred
		end

	query_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE
			-- Parameter for name `n'.
		require
			a_name_valid: a_name /= Void and then not a_name.is_empty
		deferred
		end
	
feature -- Form fields and related

	form_data_parameters: ITERABLE [WGI_VALUE]
			-- Variables sent by POST request
		deferred
		end

	form_data_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE
			-- Field for name `a_name'.
		require
			a_name_valid: a_name /= Void and then not a_name.is_empty
		deferred
		end

	uploaded_files: HASH_TABLE [WGI_UPLOADED_FILE_DATA, READABLE_STRING_GENERAL]
			-- Table of uploaded files information
		deferred
		end
	
feature -- Cookies	

	cookies: ITERABLE [WGI_VALUE]
			-- Expanded cookies variable
		deferred
		end

	cookie (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE
			-- Field for name `a_name'.
		require
			a_name_valid: a_name /= Void and then not a_name.is_empty
		deferred
		end
	
feature -- Access: all variables

	items: ITERABLE [WGI_VALUE]
			-- Table containing all the various variables
			-- Warning: this is computed each time, if you change the content of other containers
			-- this won't update this Result's content, unless you query it again
		deferred
		end

	item (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE
			-- Variable named `a_name' from any of the variables container
			-- and following a specific order
			-- execution, environment, get, post, cookies
		require
			a_name_valid: a_name /= Void and then not a_name.is_empty
		deferred
		end
	
feature -- Uploaded File Handling

	is_uploaded_file (a_filename: READABLE_STRING_GENERAL): BOOLEAN
			-- Is `a_filename' a file uploaded via HTTP POST
		deferred
		end
	
feature -- URL Utility

	absolute_script_url (a_path: STRING_8): STRING_8
			-- Absolute Url for the script if any, extended by `a_path'
		deferred
		end

	script_url (a_path: STRING_8): STRING_8
			-- Url relative to script name if any, extended by `a_path'
		require
			a_path_attached: a_path /= Void
		deferred
		end
	
invariant
	server_name_not_empty: not server_name.is_empty
	server_port_set: server_port /= 0
	request_method_attached: request_method /= Void
	path_info_attached: path_info /= Void
	query_string_attached: query_string /= Void
	remote_addr_attached: remote_addr /= Void
	same_orig_path_info: orig_path_info ~ meta_string_variable ({WGI_META_NAMES}.orig_path_info)
	same_path_info: path_info ~ meta_string_variable ({WGI_META_NAMES}.path_info)
	path_info_identical: path_info ~ meta_string_variable ({WGI_META_NAMES}.path_info)
end

WGI_RESPONSE_BUFFER

deferred class
	WGI_RESPONSE_BUFFER

feature {WGI_APPLICATION} -- Commit

	commit
			-- Commit the current response
		deferred
		ensure
			status_is_set: status_is_set
			header_committed: header_committed
			message_committed: message_committed
		end

feature -- Status report

	header_committed: BOOLEAN
			-- Header committed?
		deferred
		end

	message_committed: BOOLEAN
			-- Message committed?
		deferred
		end

	message_writable: BOOLEAN
			-- Can message be written?
		deferred
		end

feature {WGI_RESPONSE_BUFFER} -- Core output operation

	write (s: READABLE_STRING_8)
			-- Send the string `s'
			-- this can be used for header and body
		deferred
		end

feature -- Status setting

	status_is_set: BOOLEAN
			-- Is status set?
		deferred
		end

	set_status_code (a_code: INTEGER)
			-- Set response status code
			-- Should be done before sending any data back to the client
		require
			status_not_set: not status_is_set
			header_not_committed: not header_committed
		deferred
		ensure
			status_code_set: status_code = a_code
			status_set: status_is_set
		end

	status_code: INTEGER
			-- Response status
		deferred
		end

feature -- Header output operation

	write_headers_string (a_headers: READABLE_STRING_8)
		require
			status_set: status_is_set
			header_not_committed: not header_committed
		deferred
		ensure
			status_set: status_is_set
			header_committed: header_committed
			message_writable: message_writable
		end

	write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]])
			-- Send headers with status `a_status', and headers from `a_headers'
		require
			status_not_set: not status_is_set
			header_not_committed: not header_committed
		deferred
		ensure
			header_committed: header_committed
			status_set: status_is_set
			message_writable: message_writable
		end

feature -- Output operation

	write_string (s: READABLE_STRING_8)
			-- Send the string `s'
		require
			message_writable: message_writable
		deferred
		end

	write_substring (s: READABLE_STRING_8; a_begin_index, a_end_index: INTEGER)
			-- Send the substring `s[a_begin_index:a_end_index]'
		require
			message_writable: message_writable
		deferred
		end

	write_file_content (fn: READABLE_STRING_8)
			-- Send the content of file `fn'
		require
			message_writable: message_writable
		deferred
		end

	flush
			-- Flush if it makes sense
		deferred
		end
end

Proof-of-concept and reference implementation

Specification overview

The Server/Gateway Side

The Application/Framework Side

Specification Details

Implementation/Application Notes

Questions and Answers

Proposed/Under Discussion

Acknowledgements

References