Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8ddd10b46 | ||
|
|
db39068ceb | ||
|
|
a1b4337438 | ||
|
|
74121be470 | ||
|
|
1c9f5ac0e7 | ||
|
|
edec837c4e | ||
|
|
f1642a444a | ||
|
|
48af63af83 | ||
|
|
2f98d7031f | ||
|
|
70f00651c7 | ||
|
|
199f84c7ef | ||
|
|
9b97627c76 | ||
|
|
72c87cd74d | ||
|
|
2ed4d03168 | ||
|
|
18ed92a61d | ||
|
|
0a6a4281e7 | ||
|
|
38cf5d7a6f | ||
|
|
96648a16dc | ||
|
|
6f35ad7b16 | ||
|
|
8ff20d34a7 | ||
|
|
85c8a46c89 | ||
|
|
498e4a6ec2 | ||
|
|
ab507d543a | ||
|
|
20a90db2e3 | ||
|
|
6ed91699b8 | ||
|
|
bb334aef80 | ||
|
|
c2764e25ff | ||
|
|
6425482070 | ||
|
|
818c3fb460 | ||
|
|
dac50b490d | ||
|
|
16d5076fe5 | ||
|
|
2748e1d9ee | ||
|
|
27ee20f99b | ||
|
|
9a3164df70 | ||
|
|
02383810b4 | ||
|
|
dbf5e76047 | ||
|
|
5c31905427 | ||
|
|
67bdcfb6ef | ||
|
|
ca4043b102 | ||
|
|
310e96e185 |
19
.travis.yml
19
.travis.yml
@@ -0,0 +1,19 @@
|
||||
language: eiffel
|
||||
before_script:
|
||||
- export current_dir=$PWD ; echo current_dir=$current_dir ; cd ..
|
||||
- export ISE_VERSION=17.05; export ISE_BUILD=100416
|
||||
- curl -sSL http://downloads.sourceforge.net/eiffelstudio/Eiffel_${ISE_VERSION}_gpl_${ISE_BUILD}-linux-x86-64.tar.bz2 | tar -x --bzip2
|
||||
- export ISE_EIFFEL=$PWD/Eiffel_${ISE_VERSION} ; export ISE_PLATFORM=linux-x86-64
|
||||
- export PATH=$PATH:$ISE_EIFFEL/studio/spec/$ISE_PLATFORM/bin:$PATH:$ISE_EIFFEL/tools/spec/$ISE_PLATFORM/bin
|
||||
- echo `ec -version`
|
||||
- cd $current_dir
|
||||
- echo Check projects compilation status...
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- v1
|
||||
|
||||
script: compile_all -ecb -melt -list_failures -log_verbose -clean -options dotnet=false
|
||||
group: stable
|
||||
os: linux
|
||||
|
||||
@@ -7,14 +7,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- jwt: new JSON Web Token (JWT) library (supports for claim exp, iat, nbf, iss, aud).
|
||||
- `jwt`: new JSON Web Token (JWT) library (supports for claim exp, iat, nbf, iss, aud).
|
||||
- `http_client`: added support for ciphers setting in the libcurl implementation only.
|
||||
- `http_client`: added convenient `get` and `custom` functions on HTTP_CLIENT directly.
|
||||
|
||||
### Changed
|
||||
- adopted ecf version 1-16-0 and use a single .ecf file (the -safe.ecf are now redirection to normal .ecf)
|
||||
### Deprecated
|
||||
- removed support for Eiffel version before 17.05 .
|
||||
- SSL 2 or 3 is obsolete and will raise an exception if used.
|
||||
### Removed
|
||||
### Fixed
|
||||
- Removed a few obsolete calls.
|
||||
- `http_client`: Added support for multiple file in form data. Made clear what is the meaning of `upload_filename`, `upload_data` and `form_data`.
|
||||
- `authentication`: HTTP_AUTHORIZATION acceps now READABLE_STRING_GENERAL for username and password argument.
|
||||
- `http_client`: fixed curl implementation by setting `Content-Type` to `x-www-form-urlencoded` (if not set) when POST send data as `x-www-form-urlencoded`.
|
||||
### Security
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Eiffel Web Framework
|
||||
|
||||
[](https://travis-ci.org/EiffelWebFramework/EWF/)
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package nino
|
||||
|
||||
project
|
||||
nino = "nino-safe.ecf"
|
||||
nino = "nino.ecf"
|
||||
|
||||
note
|
||||
|
||||
@@ -59,7 +59,7 @@ feature -- Basic operations
|
||||
end
|
||||
```
|
||||
|
||||
When using the "standalone" connector (or the deprecated "nino" connector), by default the service listens on port 80, but often this port is already used by other applications, so it is recommended to use another port.
|
||||
When using the [standalone](../connectors/standalone.md) connector (or the deprecated "nino" connector), by default the service listens on port 80, but often this port is already used by other applications, so it is recommended to use another port.
|
||||
To define another port, redefine the feature `initialize` and set up a new port number using the service options (see below).
|
||||
|
||||
|
||||
@@ -86,6 +86,8 @@ feature {NONE} -- Initialization
|
||||
end
|
||||
```
|
||||
|
||||
Learn more about the [Standalone](../connectors/standalone.md) connector.
|
||||
|
||||
The **WSF_REQUEST** gives access to the incoming data; the class provides features to get information such as request method, form data, query parameters, uploaded files, HTTP request headers, and hostname of the client among others.
|
||||
|
||||
The **WSF_RESPONSE** provides features to define the response with information such as HTTP status codes (10x,20x, 30x, 40x, and 50x), response headers (Content-Type, Content-Length, etc.) and obviously the body of the message itself.
|
||||
|
||||
27
docs/workbook/connectors/standalone.md
Normal file
27
docs/workbook/connectors/standalone.md
Normal file
@@ -0,0 +1,27 @@
|
||||
Nav: [Workbook](../workbook.md)
|
||||
|
||||
## The EiffelWeb standalone connector
|
||||
|
||||
It provides a standalone httpd server for the EiffelWeb framework.
|
||||
It implements HTTP/1.1 with persistent connection, concurrent connection, ...
|
||||
|
||||
To easily set the standalone connector, see class `WSF_STANDALONE_SERVICE_OPTIONS`.
|
||||
|
||||
### Main settings:
|
||||
|
||||
* `port`: Listening port number (defaut: 80).
|
||||
* `max_concurrent_connections`: maximum of concurrent connections (default: 100)
|
||||
* `max_tcp_clients`: Listen on socket for at most `max_tcp_clients` connections (default: 100)
|
||||
* `socket_timeout`: Amount of seconds the server waits for receipts and transmissions during communications. With timeout of 0, socket can wait for ever. (default: 60)
|
||||
* `socket_recv_timeout`: Amount of seconds the server waits for receiving data during communications. With timeout of 0, socket can waits for ever. (default: 5)
|
||||
* `keep_alive_timeout`: Persistent connection timeout. Number of seconds the server waits after a request has been served before it closes the connection (default: 5)
|
||||
* `max_keep_alive_requests`: Maximum number of requests allowed per persistent connection. To disable KeepAlive, set `max_keep_alive_requests` to `0`. To have no limit, set `max_keep_alive_requests` to `-1` (default: 300).
|
||||
|
||||
* `is_secure`: check SSL certificate?
|
||||
* `secure_certificate`: path to SSL certificate.
|
||||
* `secure_certificate_key`: certificate key
|
||||
|
||||
* `verbose`: display verbose output (Default: false)
|
||||
|
||||
See also `WGI_STANDALONE_CONSTANTS` for default values.
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<target name="websocket_app">
|
||||
<root class="APPLICATION" feature="make_and_launch"/>
|
||||
<file_rule>
|
||||
<exclude>/\.svn$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
@@ -17,6 +17,14 @@
|
||||
<library name="wsf" location="..\..\library\server\wsf\wsf.ecf"/>
|
||||
<cluster name="app" location=".\" recursive="true"/>
|
||||
</target>
|
||||
<target name="websocket_app_st" extends="websocket_app">
|
||||
<description>Single thread solution.
|
||||
Warning: as it can not handle concurrent request, it is recommended to set Keep-Alive-Timeout to very low value, as browser will keep persistent connection open too long.
|
||||
</description>
|
||||
<capability>
|
||||
<concurrency use="none"/>
|
||||
</capability>
|
||||
</target>
|
||||
<target name="websocket_app_ssl" extends="websocket_app">
|
||||
<variable name="ssl_enabled" value="true"/>
|
||||
</target>
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
verbose=true
|
||||
verbose_level=INFORMATION
|
||||
port=9090
|
||||
|
||||
#Socket and timeout
|
||||
max_concurrent_connections=100
|
||||
keep_alive_timeout=35
|
||||
max_tcp_clients=100
|
||||
socket_timeout=30
|
||||
socket_recv_timeout=5
|
||||
max_keep_alive_requests=300
|
||||
|
||||
#Persistent connections
|
||||
keep_alive_timeout=2
|
||||
max_keep_alive_requests=-1
|
||||
|
||||
#SSL
|
||||
is_secure=false
|
||||
secure_certificate=ca.crt
|
||||
secure_certificate_key=ca.key
|
||||
|
||||
#Debug
|
||||
verbose=true
|
||||
verbose_level=INFORMATION
|
||||
|
||||
@@ -10,6 +10,9 @@ It provides simple routine to perform http requests, and get response.
|
||||
- Eiffel Net library
|
||||
- and optionally Eiffel NetSSL library to support `https://...`
|
||||
|
||||
* Note: set ciphers setting is supported only with libcurl implementation for now, net implementation
|
||||
set all the ciphers as part of the OpenSSL initialization.
|
||||
|
||||
This means on Windows, do not forget to copy the libcurl.dll (and related) either in the same directory of the executable, or ensure the .dll are in the PATH environment.
|
||||
|
||||
It is possible to exclude the libcurl implementation xor the Eiffel Net implementation:
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
<exclude>/\.svn$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="curl" location="$ISE_LIBRARY\library\cURL\cURL.ecf">
|
||||
<condition>
|
||||
@@ -32,8 +30,8 @@
|
||||
</library>
|
||||
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri.ecf"/>
|
||||
<cluster name="src" location=".\src\">
|
||||
<cluster name="implementation" location="$|implementation" recursive="true" hidden="true"/>
|
||||
<cluster name="parameters" location="$|parameters" recursive="true"/>
|
||||
<cluster name="implementation" location="$|implementation\" recursive="true" hidden="true"/>
|
||||
<cluster name="parameters" location="$|parameters\" recursive="true"/>
|
||||
<cluster name="spec_null" location="$|spec\null\" recursive="true"/>
|
||||
<cluster name="spec_net" location="$|spec\net\">
|
||||
<condition>
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
<exclude>/\.svn$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="curl" location="$ISE_LIBRARY\library\cURL\cURL.ecf"/>
|
||||
<library name="encoder" location="..\..\text\encoder\encoder.ecf"/>
|
||||
@@ -16,8 +14,8 @@
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
|
||||
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri.ecf"/>
|
||||
<cluster name="src" location=".\src\">
|
||||
<cluster name="implementation" location="$|implementation" recursive="true" hidden="true"/>
|
||||
<cluster name="parameters" location="$|parameters" recursive="true"/>
|
||||
<cluster name="implementation" location="$|implementation\" recursive="true" hidden="true"/>
|
||||
<cluster name="parameters" location="$|parameters\" recursive="true"/>
|
||||
<cluster name="spec_libcurl" location="$|spec\libcurl\" recursive="true"/>
|
||||
<cluster name="default_libcurl" location="$|default\libcurl\"/>
|
||||
</cluster>
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
<exclude>/\.svn$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="encoder" location="..\..\text\encoder\encoder.ecf"/>
|
||||
<library name="http" location="..\protocol\http\http.ecf"/>
|
||||
@@ -25,8 +23,8 @@
|
||||
</library>
|
||||
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri.ecf"/>
|
||||
<cluster name="src" location=".\src\">
|
||||
<cluster name="implementation" location="$|implementation" recursive="true" hidden="true"/>
|
||||
<cluster name="parameters" location="$|parameters" recursive="true"/>
|
||||
<cluster name="implementation" location="$|implementation\" recursive="true" hidden="true"/>
|
||||
<cluster name="parameters" location="$|parameters\" recursive="true"/>
|
||||
<cluster name="spec_net" location="$|spec\net\">
|
||||
<cluster name="net_implementation" location="$|implementation\" hidden="true"/>
|
||||
</cluster>
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
package http_client
|
||||
|
||||
project
|
||||
http_client = "http_client-safe.ecf"
|
||||
http_client = "http_client.ecf"
|
||||
libcurl_http_client = "libcurl_http_client-safe.ecf"
|
||||
libcurl_http_client = "libcurl_http_client.ecf"
|
||||
net_http_client = "net_http_client-safe.ecf"
|
||||
net_http_client = "net_http_client.ecf"
|
||||
|
||||
note
|
||||
title: HTTP client
|
||||
description: "[
|
||||
Provides simple routines to perform http requests, and get associated response.
|
||||
It has two implementations:
|
||||
- using Eiffel cURL (i.e libcurl)
|
||||
- using EiffelNET (and the EiffelNET SSL extension)
|
||||
]"
|
||||
collection:EWF
|
||||
description: "[
|
||||
Provides simple routines to perform http requests, and get associated response.
|
||||
It has two implementations:
|
||||
- using Eiffel cURL (i.e libcurl)
|
||||
- using EiffelNET (and the EiffelNET SSL extension)
|
||||
]"
|
||||
|
||||
collection: EWF
|
||||
tags: http,client,network,request,web,curl,EWF
|
||||
copyright: 1984-2016 Eiffel Software and others
|
||||
license: Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)
|
||||
|
||||
@@ -16,8 +16,19 @@ feature -- Access
|
||||
deferred
|
||||
end
|
||||
|
||||
get (a_url: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
do
|
||||
Result := new_session (a_url).get ("", ctx)
|
||||
end
|
||||
|
||||
custom (a_method: READABLE_STRING_8; a_url: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
|
||||
-- Response for `a_method' request based on `a_url' and optional `ctx'.
|
||||
do
|
||||
Result := new_session (a_url).custom (a_method, "", ctx)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -30,8 +30,19 @@ feature {NONE} -- Initialization
|
||||
-- Initialize Current with `a_url' and `ctx'.
|
||||
-- This can be used to reset/reinitialize Current with new url
|
||||
-- in the case of redirection.
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
url := a_url
|
||||
i := a_url.substring_index ("://", 1)
|
||||
if i > 0 then
|
||||
check
|
||||
a_url.substring (1, i).same_string ("http")
|
||||
or a_url.substring (1, i).same_string ("https")
|
||||
end
|
||||
url := a_url
|
||||
else
|
||||
url := session.url (a_url, Void)
|
||||
end
|
||||
headers := session.headers.twin
|
||||
if ctx /= Void then
|
||||
context := ctx
|
||||
|
||||
@@ -272,6 +272,14 @@ feature -- Authentication
|
||||
-- Associated optional credentials value.
|
||||
-- Computed as `username':`password'.
|
||||
|
||||
ciphers_setting: detachable READABLE_STRING_8
|
||||
-- SSL cipher preference lists
|
||||
-- examples: DEFAULT, ALL, TLSv1
|
||||
-- check https://www.openssl.org/docs/man1.1.0/apps/ciphers.html
|
||||
-- Warning: At the moment only used for LIB_CURL_HTTP_CLIENT
|
||||
-- Net implementation set all the ciphers using the OpenSSL at
|
||||
-- initialization time.
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_is_debug (b: BOOLEAN)
|
||||
@@ -401,6 +409,14 @@ feature -- Element change
|
||||
chunk_size := a_size
|
||||
end
|
||||
|
||||
set_ciphers_setting (a_ciphers_setting: READABLE_STRING_8)
|
||||
-- Set 'ciphers_setting' with 'a_ciphers_setting'.
|
||||
do
|
||||
create {STRING_8} ciphers_setting.make_from_string (a_ciphers_setting)
|
||||
ensure
|
||||
ciphers_setting_set: attached ciphers_setting as c_setting and then c_setting.same_string (a_ciphers_setting)
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -206,7 +206,10 @@ feature -- Execution
|
||||
l_use_curl_form := True
|
||||
end
|
||||
else
|
||||
l_headers.force ("application/x-www-form-urlencoded", "Content-Type")
|
||||
l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
|
||||
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_postfields, l_upload_data)
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_postfieldsize, l_upload_data.count)
|
||||
end
|
||||
if l_use_curl_form then
|
||||
create l_form.make
|
||||
@@ -372,6 +375,11 @@ feature -- Execution
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_ssl_verifypeer, 0)
|
||||
end
|
||||
|
||||
--| Cipher List
|
||||
if attached session.ciphers_setting as c_list then
|
||||
curl_easy.setopt_string (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_ssl_cipher_list, c_list )
|
||||
end
|
||||
|
||||
--| Request method
|
||||
if request_method.is_case_insensitive_equal ("GET") then
|
||||
curl_easy.setopt_integer (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httpget, 1)
|
||||
|
||||
@@ -113,6 +113,7 @@ feature -- Access
|
||||
-- Get URL data
|
||||
l_is_https := url.starts_with_general ("https://")
|
||||
create l_uri.make_from_string (url)
|
||||
check valid_url: l_uri.is_valid end
|
||||
l_port := l_uri.port
|
||||
if l_port = 0 then
|
||||
if l_is_https then
|
||||
|
||||
@@ -7,117 +7,32 @@
|
||||
<exclude>/\.svn$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true">
|
||||
</option>
|
||||
<external_include location="$ECF_CONFIG_PATH/spec/include">
|
||||
<condition>
|
||||
<version type="compiler" min="16.9.9.9124"/>
|
||||
</condition>
|
||||
</external_include>
|
||||
<external_include location="$ECF_CONFIG_PATH/spec/include_until_16_05">
|
||||
<condition>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
</condition>
|
||||
</external_include>
|
||||
<external_include location="$(ISE_LIBRARY)/unstable/library/network/socket/netssl/spec/include">
|
||||
<condition>
|
||||
<platform excluded_value="windows"/>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</external_include>
|
||||
<external_include location="$(ISE_LIBRARY)\unstable\library\network\socket\netssl\spec\include">
|
||||
<condition>
|
||||
<platform value="windows"/>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</external_include>
|
||||
<external_cflag value="-D_WINSOCKAPI_">
|
||||
<condition>
|
||||
<platform value="windows"/>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</external_cflag>
|
||||
<external_include location="$ECF_CONFIG_PATH/spec/include"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
|
||||
<library name="net_ssl" location="$ISE_LIBRARY\unstable\library\network\socket\netssl\net_ssl.ecf">
|
||||
<condition>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</library>
|
||||
<library name="openssl" location="$ISE_LIBRARY\unstable\library\network\openssl\openssl.ecf">
|
||||
<condition>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
<condition>
|
||||
<custom name="httpd_ssl_enabled" value="true"/>
|
||||
<version type="compiler" min="17.10.0.0"/>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</library>
|
||||
<cluster name="network" location=".\src\">
|
||||
<file_rule>
|
||||
<exclude>/http_stream_socket_ext.e$</exclude>
|
||||
<condition>
|
||||
<version type="compiler" max="17.02"/>
|
||||
</condition>
|
||||
</file_rule>
|
||||
<cluster name="disabled_ssl_network" location="$|no_ssl\" recursive="true">
|
||||
<condition>
|
||||
<custom name="ssl_enabled" excluded_value="true"/>
|
||||
<custom name="net_ssl_enabled" excluded_value="true"/>
|
||||
<custom name="httpd_ssl_enabled" excluded_value="true"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="ssl_network" location="$|ssl\" recursive="true">
|
||||
<condition>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
<condition>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
<condition>
|
||||
<custom name="httpd_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
<file_rule>
|
||||
<exclude>/http_stream_secure_socket_ext.e$</exclude>
|
||||
<condition>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
<condition>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
<condition>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
<custom name="httpd_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</cluster>
|
||||
<cluster name="network_until_16_05" location=".\src\until_16_05\">
|
||||
<condition>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
</condition>
|
||||
<cluster name="ssl_network_until_16_05" location="$|ssl\" recursive="true">
|
||||
<condition>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
<condition>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
<custom name="net_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
<condition>
|
||||
<version type="compiler" max="16.9.9.9124"/>
|
||||
<custom name="httpd_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
</cluster>
|
||||
<cluster name="network_until_17_01" location=".\src\until_17_01\">
|
||||
<condition>
|
||||
<version type="compiler" min="16.9.9.9124" max="17.02"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
</target>
|
||||
<target name="http_network_ssl" extends="http_network">
|
||||
<variable name="ssl_enabled" value="true"/>
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
indexing
|
||||
description: "Functions used by the EiffelWeb http networking classes. "
|
||||
copyright: "Copyright (c) 2011-2016, Jocelyn Fiat, 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
|
||||
]"
|
||||
*/
|
||||
|
||||
#ifndef _ew_network_h_
|
||||
#define _ew_network_h_
|
||||
|
||||
#include "eif_config.h"
|
||||
|
||||
#ifdef EIF_WINDOWS
|
||||
# ifndef _WINSOCKAPI_
|
||||
# define FD_SETSIZE 256
|
||||
# include <winsock2.h>
|
||||
# include <Ws2tcpip.h>
|
||||
# include <stdio.h>
|
||||
# endif
|
||||
#else /* unix-specific */
|
||||
# include <sys/socket.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* extern declarations ... */
|
||||
#ifdef EIF_WINDOWS
|
||||
extern int setsockopt(int, int, int, char*, int);
|
||||
extern int recv(int, char *, int, int);
|
||||
extern int send(int, char *, int, int);
|
||||
#else
|
||||
extern int setsockopt(int, int, int, const void*, socklen_t);
|
||||
extern ssize_t recv(int, void *, size_t, int);
|
||||
extern ssize_t send(int, const void *, size_t, int);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -9,8 +9,6 @@ class
|
||||
inherit
|
||||
NETWORK_STREAM_SOCKET
|
||||
|
||||
HTTP_STREAM_SOCKET_EXT
|
||||
|
||||
create
|
||||
make, make_empty,
|
||||
make_client_by_port, make_client_by_address_and_port,
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Extension to HTTPD_STREAM_SOCKET to support backward compatibility.
|
||||
|
||||
TO BE REMOVED IN THE FUTURE, When there is no need to support older compilers.
|
||||
]"
|
||||
|
||||
deferred class
|
||||
HTTP_STREAM_SOCKET_EXT
|
||||
|
||||
note
|
||||
copyright: "2011-2017, 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)"
|
||||
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
|
||||
@@ -55,12 +55,19 @@ feature -- Secure connection Helpers
|
||||
end
|
||||
|
||||
set_secure_protocol_to_ssl_2_or_3
|
||||
-- Set `ssl_protocol' with `Ssl_23'.
|
||||
do
|
||||
set_secure_protocol ({SSL_PROTOCOL}.Ssl_23)
|
||||
end
|
||||
-- Set `ssl_protocol' with `Ssl_23'.
|
||||
-- Protocol not supported anymore.
|
||||
obsolete
|
||||
"Use set_secure_protocol_to_tls_1_2 [2017-06-23]."
|
||||
local
|
||||
err: DEVELOPER_EXCEPTION
|
||||
do
|
||||
create err
|
||||
err.set_description ("SSL_2 or SSL_3 are not supported anymore, upgrate to TLS set_secure_protocol_to_tls_1_2")
|
||||
err.raise
|
||||
end
|
||||
|
||||
set_secure_protocol_to_tls_1_0
|
||||
set_secure_protocol_to_tls_1_0
|
||||
-- Set `ssl_protocol' with `Tls_1_0'.
|
||||
do
|
||||
set_secure_protocol ({SSL_PROTOCOL}.Tls_1_0)
|
||||
@@ -176,7 +183,14 @@ feature -- Output
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Javier Velilla, Jocelyn Fiat and others"
|
||||
copyright: "2011-2017, 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)"
|
||||
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
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Until 16.05, the EiffelNet socket interface DOES NOT have
|
||||
- make_server_by_address_and_port
|
||||
- recv_timeout
|
||||
- send_timeout.
|
||||
|
||||
TO BE REMOVED IN THE FUTURE, WHEN 16.05 IS OLD.
|
||||
]"
|
||||
|
||||
deferred class
|
||||
HTTP_STREAM_SOCKET_EXT
|
||||
|
||||
inherit
|
||||
PLATFORM
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make
|
||||
deferred
|
||||
end
|
||||
|
||||
make_server_by_address_and_port (a_address: INET_ADDRESS; a_port: INTEGER)
|
||||
-- Create server socket on `a_address' and `a_port'.
|
||||
require
|
||||
valid_port: a_port >= 0
|
||||
do
|
||||
make
|
||||
set_address (create {like address_type}.make_from_address_and_port (a_address, a_port))
|
||||
bind
|
||||
end
|
||||
|
||||
feature -- Basic operation
|
||||
|
||||
bind
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
set_address (addr: detachable like address_type)
|
||||
deferred
|
||||
end
|
||||
|
||||
address_type: NETWORK_SOCKET_ADDRESS
|
||||
deferred
|
||||
end
|
||||
|
||||
descriptor: INTEGER
|
||||
-- Socket descriptor of current socket
|
||||
deferred
|
||||
end
|
||||
|
||||
socket_buffer: MANAGED_POINTER
|
||||
deferred
|
||||
end
|
||||
|
||||
read_socket_buffer: MANAGED_POINTER
|
||||
do
|
||||
Result := socket_buffer
|
||||
end
|
||||
|
||||
put_socket_buffer: MANAGED_POINTER
|
||||
do
|
||||
Result := socket_buffer
|
||||
end
|
||||
|
||||
feature -- Socket Recv and Send timeout.
|
||||
|
||||
set_recv_timeout (a_timeout_seconds: INTEGER)
|
||||
-- Set the receive timeout in seconds on Current socket.
|
||||
-- if `0' the related operations will never timeout.
|
||||
require
|
||||
positive_timeout: a_timeout_seconds >= 0
|
||||
do
|
||||
c_set_sock_recv_timeout (descriptor, level_sol_socket, a_timeout_seconds)
|
||||
end
|
||||
|
||||
set_send_timeout (a_timeout_seconds: INTEGER)
|
||||
-- Set the send timeout in milliseconds on Current socket.
|
||||
-- if `0' the related operations will never timeout.
|
||||
require
|
||||
positive_timeout: a_timeout_seconds >= 0
|
||||
do
|
||||
c_set_sock_send_timeout (descriptor, level_sol_socket, a_timeout_seconds)
|
||||
end
|
||||
|
||||
feature {NONE} -- Externals
|
||||
|
||||
level_sol_socket: INTEGER
|
||||
-- SOL_SOCKET level of options
|
||||
deferred
|
||||
end
|
||||
|
||||
c_set_sock_recv_timeout (a_fd, a_level: INTEGER; a_timeout_seconds: INTEGER)
|
||||
-- C routine to set socket option `SO_RCVTIMEO' with `a_timeout_seconds' seconds.
|
||||
external
|
||||
"C inline use %"ew_network.h%""
|
||||
alias
|
||||
"[
|
||||
#ifdef SO_RCVTIMEO
|
||||
int flag = SO_RCVTIMEO;
|
||||
#else
|
||||
int flag = 0x1006;
|
||||
#endif
|
||||
|
||||
#ifdef EIF_WINDOWS
|
||||
int arg = (int) 1000 * $a_timeout_seconds; /* Timeout in milliseconds */
|
||||
setsockopt((int) $a_fd, (int) $a_level, flag, (char *) &arg, sizeof(arg));
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = $a_timeout_seconds; /* Timeout in seconds */
|
||||
tv.tv_usec = 0;
|
||||
setsockopt((int) $a_fd, (int) $a_level, flag, (struct timeval *)&tv, sizeof(struct timeval));
|
||||
#endif
|
||||
]"
|
||||
end
|
||||
|
||||
c_set_sock_send_timeout (a_fd, a_level: INTEGER; a_timeout_seconds: INTEGER)
|
||||
-- C routine to set socket option `SO_SNDTIMEO' with `a_timeout_seconds' seconds.
|
||||
external
|
||||
"C inline use %"ew_network.h%""
|
||||
alias
|
||||
"[
|
||||
#ifdef SO_RCVTIMEO
|
||||
int flag = SO_SNDTIMEO;
|
||||
#else
|
||||
int flag = 0x1005;
|
||||
#endif
|
||||
#ifdef EIF_WINDOWS
|
||||
int arg = (int) 1000 * $a_timeout_seconds; /* Timeout in milliseconds */
|
||||
setsockopt((int) $a_fd, (int) $a_level, flag, (char *) &arg, sizeof(arg));
|
||||
#else
|
||||
struct timeval tv;
|
||||
tv.tv_sec = $a_timeout_seconds; /* Timeout in seconds */
|
||||
tv.tv_usec = 0;
|
||||
setsockopt((int) $a_fd, (int) $a_level, flag, (struct timeval *)&tv, sizeof(struct timeval));
|
||||
#endif
|
||||
]"
|
||||
end
|
||||
|
||||
feature {NONE} -- No-Exception network operation
|
||||
|
||||
c_recv_noexception (a_fd: INTEGER; buf: POINTER; len: INTEGER; flags: INTEGER): INTEGER
|
||||
-- External routine to read a `len' number of characters
|
||||
-- into buffer `buf' from socket `a_fd' with options `flags'.
|
||||
external
|
||||
"C inline use %"ew_network.h%""
|
||||
alias
|
||||
"[
|
||||
recv((int) $a_fd, (char *) $buf, (int) $len, (int) $flags)
|
||||
]"
|
||||
end
|
||||
|
||||
c_read_stream_noexception (a_fd: INTEGER; len: INTEGER; buf: POINTER): INTEGER
|
||||
-- External routine to read a `len' number of characters
|
||||
-- into buffer `buf' from socket `a_fd'.
|
||||
do
|
||||
Result := c_recv_noexception (a_fd, buf, len, 0)
|
||||
end
|
||||
|
||||
c_put_stream_noexception (a_fd: INTEGER; buf: POINTER; len: INTEGER): INTEGER
|
||||
-- External routine to write stream pointed by `s' of
|
||||
-- length `length' to socket `fd'.
|
||||
-- Note: does not raise exception on error, but return error value as Result.
|
||||
external
|
||||
"C inline use %"ew_network.h%""
|
||||
alias
|
||||
"[
|
||||
send((int) $a_fd, (char *) $buf, (int) $len, (int) 0)
|
||||
]"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,41 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Extension to HTTP_STREAM_SOCKET to support backward compatibility.
|
||||
|
||||
TO BE REMOVED IN THE FUTURE, WHEN 16.05 IS OLD.
|
||||
]"
|
||||
|
||||
deferred class
|
||||
HTTP_STREAM_SECURE_SOCKET_EXT
|
||||
|
||||
feature {NONE} -- SSL bridge
|
||||
|
||||
ssl_write (a_ssl: SSL; a_pointer: POINTER; a_byte_count: INTEGER): INTEGER
|
||||
do
|
||||
-- In delivery until 16.05
|
||||
-- SSL.write does not return any value!
|
||||
-- So let's use `c_ssl_write' from Current class
|
||||
-- instead of:
|
||||
-- a_ssl.write (a_pointer, a_byte_count)
|
||||
|
||||
Result := c_ssl_write (a_ssl.ptr, a_pointer, a_byte_count)
|
||||
if a_ssl.was_error then
|
||||
-- Until 16.05, there is no error check for `SSL.write'
|
||||
-- so nothing can be done here.
|
||||
|
||||
if Result >= 0 then
|
||||
Result := -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
c_ssl_write (an_ssl_ptr: POINTER; buffer: POINTER; nb_bytes: INTEGER_32): INTEGER_32
|
||||
-- External call to SSL_write
|
||||
-- (export status {NONE})
|
||||
external
|
||||
"C use %"eif_openssl.h%""
|
||||
alias
|
||||
"SSL_write"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,29 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Extension to HTTPD_STREAM_SOCKET to support backward compatibility.
|
||||
|
||||
TO BE REMOVED IN THE FUTURE, WHEN 17.01 IS OLD.
|
||||
]"
|
||||
|
||||
deferred class
|
||||
HTTP_STREAM_SOCKET_EXT
|
||||
|
||||
feature -- Access
|
||||
|
||||
socket_buffer: MANAGED_POINTER
|
||||
deferred
|
||||
end
|
||||
|
||||
read_socket_buffer: MANAGED_POINTER
|
||||
do
|
||||
Result := socket_buffer
|
||||
end
|
||||
|
||||
put_socket_buffer: MANAGED_POINTER
|
||||
do
|
||||
Result := socket_buffer
|
||||
end
|
||||
|
||||
feature {NONE} -- No-Exception network operation
|
||||
|
||||
end
|
||||
@@ -1,14 +1,14 @@
|
||||
package content_negotiation
|
||||
|
||||
project
|
||||
conneg = "conneg-safe.ecf"
|
||||
conneg = "conneg.ecf"
|
||||
|
||||
note
|
||||
title: CONneg Content Negotiation
|
||||
description: "[
|
||||
CONneg is a library that provides utilities to select the best repesentation of a resource for a client where there are multiple representations available.
|
||||
]"
|
||||
CONneg is a library that provides utilities to select the best repesentation of a resource for a client where there are multiple representations available.
|
||||
]"
|
||||
|
||||
collection: EWF
|
||||
tags: content,accept,conneg,negotiation,EWF,web,request
|
||||
copyright: 2011-2016, Javier Velilla, Jocelyn Fiat, Eiffel Software and others
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package http
|
||||
|
||||
project
|
||||
http = "http-safe.ecf"
|
||||
http = "http.ecf"
|
||||
|
||||
note
|
||||
title: HTTP protocol
|
||||
description: "[
|
||||
Collection of interfaces related to HTTP protocol:
|
||||
- header
|
||||
- status codes, request methods
|
||||
- content type, media type, mime type.
|
||||
- cookie
|
||||
- date used in web protocol
|
||||
- file extension mime mapping
|
||||
]"
|
||||
Collection of interfaces related to HTTP protocol:
|
||||
- header
|
||||
- status codes, request methods
|
||||
- content type, media type, mime type.
|
||||
- cookie
|
||||
- date used in web protocol
|
||||
- file extension mime mapping
|
||||
]"
|
||||
|
||||
collection: EWF
|
||||
tags: http,web,header,status,method,type,mime,cookie
|
||||
license: Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
package notification_email
|
||||
|
||||
project
|
||||
notification_email = "notification_email-safe.ecf"
|
||||
notification_email = "notification_email.ecf"
|
||||
|
||||
note
|
||||
title: Notification Email
|
||||
description: "[
|
||||
Abstract interface to send message via various mailers:
|
||||
- smtp
|
||||
- sendmail
|
||||
- external script
|
||||
- store on local file
|
||||
- ...
|
||||
]"
|
||||
Abstract interface to send message via various mailers:
|
||||
- smtp
|
||||
- sendmail
|
||||
- external script
|
||||
- store on local file
|
||||
- ...
|
||||
]"
|
||||
|
||||
collection: EWF
|
||||
tags: message,smtp,sendmail,mailer
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
|
||||
copyright: 2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others
|
||||
license: Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)
|
||||
link[license]: http://www.eiffel.com/licensing/forum.txt
|
||||
link[source]: "github" https://github.com/EiffelWebFramework/EWF/tree/master/library/runtime/process/notification_email
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -4,10 +4,6 @@
|
||||
<root all_classes="true"/>
|
||||
<option warning="true">
|
||||
</option>
|
||||
<capability>
|
||||
<concurrency support="scoop" use="scoop"/>
|
||||
<void_safety support="all" use="all"/>
|
||||
</capability>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto.ecf"/>
|
||||
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf"/>
|
||||
|
||||
@@ -6,7 +6,7 @@ project
|
||||
note
|
||||
title: JSON Web Token
|
||||
description: JSON Web Token
|
||||
tags:jwt,web,jws,jwe,token,jose
|
||||
tags: jwt,web,jws,jwe,token,jose
|
||||
copyright: 2011-2017, Jocelyn Fiat, Eiffel Software and others
|
||||
license: Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)
|
||||
link[license]: http://www.eiffel.com/licensing/forum.txt
|
||||
|
||||
36
library/security/jwt/src/errors/jwt_mismatched_alg_error.e
Normal file
36
library/security/jwt/src/errors/jwt_mismatched_alg_error.e
Normal file
@@ -0,0 +1,36 @@
|
||||
note
|
||||
description: "Summary description for {JWT_MISMATCHED_ALG_ERROR}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
JWT_MISMATCHED_ALG_ERROR
|
||||
|
||||
inherit
|
||||
JWT_ERROR
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_alg, a_header_alg: READABLE_STRING_8)
|
||||
do
|
||||
alg := a_alg
|
||||
header_alg := a_header_alg
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
alg: READABLE_STRING_8
|
||||
|
||||
header_alg: READABLE_STRING_8
|
||||
|
||||
id: STRING = "ALG_MISMATCH"
|
||||
|
||||
message: READABLE_STRING_8
|
||||
do
|
||||
Result := "Header alg [" + header_alg + "] does not match given alg [" + alg + "]!"
|
||||
end
|
||||
|
||||
end
|
||||
@@ -59,6 +59,8 @@ feature -- Status report
|
||||
do
|
||||
if attached claimset.issuer as iss then
|
||||
Result := a_issuer = Void or else a_issuer.same_string (iss)
|
||||
else
|
||||
Result := a_issuer = Void
|
||||
end
|
||||
end
|
||||
|
||||
@@ -66,6 +68,8 @@ feature -- Status report
|
||||
do
|
||||
if attached claimset.audience as aud then
|
||||
Result := a_audience = Void or else a_audience.same_string (aud)
|
||||
else
|
||||
Result := a_audience = Void
|
||||
end
|
||||
end
|
||||
|
||||
@@ -118,6 +122,11 @@ feature {JWT_UTILITIES} -- Error reporting
|
||||
l_errors.extend (err)
|
||||
end
|
||||
|
||||
report_mismatched_alg_error (alg, a_header_alg: READABLE_STRING_8)
|
||||
do
|
||||
report_error (create {JWT_MISMATCHED_ALG_ERROR}.make (alg, a_header_alg))
|
||||
end
|
||||
|
||||
report_unsupported_alg_error (alg: READABLE_STRING_8)
|
||||
do
|
||||
report_error (create {JWT_UNSUPPORTED_ALG_ERROR}.make (alg))
|
||||
|
||||
@@ -266,11 +266,10 @@ feature {NONE} -- Implementation
|
||||
|
||||
base64_hmacsha256 (s: READABLE_STRING_8; a_secret: READABLE_STRING_8): STRING_8
|
||||
local
|
||||
hs256: HMAC_SHA256
|
||||
ut: JWT_UTILITIES
|
||||
do
|
||||
create hs256.make_ascii_key (a_secret)
|
||||
hs256.update_from_string (s)
|
||||
Result := hs256.base64_digest --lowercase_hexadecimal_string_digest
|
||||
create ut
|
||||
Result := ut.base64_hmacsha256 (s, a_secret)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
note
|
||||
description: "Summary description for {JWT_LOADER}."
|
||||
author: ""
|
||||
description: "Loader and verifier to JWT token."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=Known Critical vulnerabilities in JWT libs", "protocol=URI", "src=https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/"
|
||||
|
||||
class
|
||||
JWT_LOADER
|
||||
@@ -12,9 +12,13 @@ inherit
|
||||
|
||||
feature -- Access
|
||||
|
||||
token (a_token_input: READABLE_STRING_8; a_secret: READABLE_STRING_8; ctx: detachable JWT_CONTEXT): detachable JWT
|
||||
-- Decoded token from `a_token_input` given the secret `a_secret`, and optional context `ctx`
|
||||
token (a_token_input: READABLE_STRING_8; a_alg: detachable READABLE_STRING_8; a_verification_key: READABLE_STRING_8; ctx: detachable JWT_CONTEXT): detachable JWT
|
||||
-- Decoded token from `a_token_input` given the verification key `a_verification_key` and optional (but recommended) signature algorithm `a_alg`, and optional context `ctx`
|
||||
-- used to specify eventual issuer and various parameters.
|
||||
-- WARNING: passing Void for `a_alg` is not safe, as the server should know which alg he used for tokens,
|
||||
-- leaving the possibility to use the header alg is dangerous as client may use "none" and then bypass verification!
|
||||
require
|
||||
a_valid_alg: a_alg /= Void implies is_supporting_signature_algorithm (a_alg)
|
||||
local
|
||||
jws: JWS
|
||||
i,j,n: INTEGER
|
||||
@@ -29,20 +33,27 @@ feature -- Access
|
||||
l_enc_payload := a_token_input.substring (i + 1, j - 1)
|
||||
l_signature := a_token_input.substring (j + 1, n)
|
||||
create jws.make_with_json_payload (base64url_decode (l_enc_payload))
|
||||
|
||||
alg := signature_algorithm_from_encoded_header (l_enc_header)
|
||||
jws.set_algorithm (alg)
|
||||
if alg = Void then
|
||||
-- Use default
|
||||
alg := alg_hs256
|
||||
if a_alg /= Void then
|
||||
if alg /= Void and then not alg.is_case_insensitive_equal_general (a_alg) then
|
||||
jws.report_mismatched_alg_error (a_alg, alg)
|
||||
else
|
||||
alg := a_alg
|
||||
end
|
||||
else
|
||||
if alg = Void then
|
||||
-- Use default
|
||||
alg := alg_hs256
|
||||
end
|
||||
end
|
||||
jws.set_algorithm (alg)
|
||||
check alg_set: alg /= Void end
|
||||
if ctx = Void or else not ctx.validation_ignored then
|
||||
if not is_supporting_signature_algorithm (alg) then
|
||||
jws.report_unsupported_alg_error (alg)
|
||||
alg := alg_hs256
|
||||
end
|
||||
if not l_signature.same_string (signature (l_enc_header, l_enc_payload, a_secret, alg)) then
|
||||
if not l_signature.same_string (signature (l_enc_header, l_enc_payload, a_verification_key, alg)) then
|
||||
jws.report_unverified_token_error
|
||||
end
|
||||
if
|
||||
|
||||
@@ -61,7 +61,33 @@ feature -- Encoding
|
||||
do
|
||||
create hs256.make_ascii_key (a_secret)
|
||||
hs256.update_from_string (s)
|
||||
Result := hs256.base64_digest --lowercase_hexadecimal_string_digest
|
||||
-- if Version >= EiffelStudio 17.11 then
|
||||
-- Result := hs256.base64_digest --lowercase_hexadecimal_string_digest
|
||||
-- else
|
||||
Result := base64_bytes_encoded_string (hs256.digest)
|
||||
-- end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
base64_bytes_encoded_string (a_bytes: SPECIAL [NATURAL_8]): STRING_8
|
||||
-- Base64 string from `a_bytes`.
|
||||
--| Note: to be removed when 17.11 is not latest release anymore.
|
||||
local
|
||||
s: STRING
|
||||
i,n: INTEGER
|
||||
do
|
||||
from
|
||||
i := 1
|
||||
n := a_bytes.count
|
||||
create s.make (n)
|
||||
until
|
||||
i > n
|
||||
loop
|
||||
s.append_code (a_bytes[i - 1])
|
||||
i := i + 1
|
||||
end
|
||||
Result := (create {BASE64}).encoded_string (s)
|
||||
end
|
||||
|
||||
feature -- Decoding
|
||||
|
||||
@@ -54,7 +54,14 @@ feature -- Test
|
||||
|
||||
create jwt_loader
|
||||
|
||||
if attached jwt_loader.token (tok, "secret", Void) as l_tok then
|
||||
-- Use header alg!
|
||||
if attached jwt_loader.token (tok, Void, "secret", Void) as l_tok then
|
||||
assert ("no error", not l_tok.has_error)
|
||||
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||
end
|
||||
|
||||
-- Use given alg!
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", Void) as l_tok then
|
||||
assert ("no error", not l_tok.has_error)
|
||||
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||
end
|
||||
@@ -96,21 +103,21 @@ feature -- Test
|
||||
create jwt_loader
|
||||
|
||||
-- Test with validation + exp
|
||||
if attached jwt_loader.token (tok, "secret", Void) as l_tok then
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", Void) as l_tok then
|
||||
assert ("no error", not l_tok.has_error)
|
||||
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||
end
|
||||
|
||||
create ctx
|
||||
ctx.set_time (now)
|
||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||
assert ("no error", not l_tok.has_error)
|
||||
end
|
||||
|
||||
dt := duplicated_time (now)
|
||||
dt.hour_add (5)
|
||||
ctx.set_time (dt)
|
||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||
assert ("exp error", l_tok.has_error)
|
||||
end
|
||||
|
||||
@@ -122,7 +129,7 @@ feature -- Test
|
||||
tok := jwt.encoded_string ("secret")
|
||||
|
||||
ctx.set_time (now)
|
||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||
assert ("has nbf error", l_tok.has_error)
|
||||
end
|
||||
|
||||
@@ -130,7 +137,7 @@ feature -- Test
|
||||
dt.second_add (15)
|
||||
ctx.set_time (dt)
|
||||
|
||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||
assert ("has nbf error", l_tok.has_error)
|
||||
end
|
||||
|
||||
@@ -138,31 +145,51 @@ feature -- Test
|
||||
dt.minute_add (45)
|
||||
ctx.set_time (dt)
|
||||
|
||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||
assert ("no error", not l_tok.has_error)
|
||||
end
|
||||
|
||||
-- Test Issuer
|
||||
ctx.set_issuer ("urn:foobar")
|
||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||
assert ("has iss error", l_tok.has_error)
|
||||
end
|
||||
ctx.set_issuer ("urn:foo")
|
||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||
assert ("no error", not l_tok.has_error)
|
||||
end
|
||||
|
||||
-- Test Audience
|
||||
ctx.set_audience ("urn:foobar")
|
||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||
assert ("has aud error", l_tok.has_error)
|
||||
end
|
||||
ctx.set_audience ("urn:foo")
|
||||
if attached jwt_loader.token (tok, "secret", ctx) as l_tok then
|
||||
if attached jwt_loader.token (tok, jwt.algorithm, "secret", ctx) as l_tok then
|
||||
assert ("no error", not l_tok.has_error)
|
||||
end
|
||||
end
|
||||
|
||||
test_mismatched_alg_jwt
|
||||
local
|
||||
jwt: JWS
|
||||
payload: STRING
|
||||
tok: STRING
|
||||
do
|
||||
payload := "[
|
||||
{"iss":"joe","exp":1300819380,"http://example.com/is_root":true}
|
||||
]"
|
||||
|
||||
create jwt.make_with_json_payload (payload)
|
||||
jwt.set_algorithm ("none")
|
||||
tok := jwt.encoded_string ("secret")
|
||||
|
||||
if attached (create {JWT_LOADER}).token (tok, "HS256", "secret", Void) as l_tok then
|
||||
assert ("no error", not jwt.has_error)
|
||||
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||
end
|
||||
end
|
||||
|
||||
test_unsecured_jwt
|
||||
local
|
||||
jwt: JWS
|
||||
@@ -177,7 +204,11 @@ feature -- Test
|
||||
jwt.set_algorithm ("none")
|
||||
tok := jwt.encoded_string ("secret")
|
||||
|
||||
if attached (create {JWT_LOADER}).token (tok, "secret", Void) as l_tok then
|
||||
if attached (create {JWT_LOADER}).token (tok, "none", "secret", Void) as l_tok then
|
||||
assert ("no error", not jwt.has_error)
|
||||
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||
end
|
||||
if attached (create {JWT_LOADER}).token (tok, Void, "secret", Void) as l_tok then
|
||||
assert ("no error", not jwt.has_error)
|
||||
assert ("same payload", l_tok.claimset.string.same_string (payload))
|
||||
end
|
||||
|
||||
@@ -2,11 +2,10 @@ package openid
|
||||
|
||||
project
|
||||
openid = "consumer/openid.ecf"
|
||||
openid = "consumer/openid-safe.ecf"
|
||||
|
||||
note
|
||||
title: Eiffel OpenID
|
||||
description: OpenID consumer library
|
||||
description: OpenID consumer library
|
||||
tags: openid,security,web,authentication,sso
|
||||
copyright: 2011-2016, Jocelyn Fiat, Eiffel Software and others
|
||||
license: Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)
|
||||
@@ -15,4 +14,3 @@ note
|
||||
link[doc]: "Documentation" https://github.com/EiffelWebFramework/EWF/tree/master/library/security/http_authorization/README.md
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package http_authorization
|
||||
|
||||
project
|
||||
http_authorization = "http_authorization-safe.ecf"
|
||||
http_authorization = "http_authorization.ecf"
|
||||
|
||||
note
|
||||
title: HTTP Authorization
|
||||
description: "[
|
||||
Class to manipulate HTTP 'Authorization' header value.
|
||||
]"
|
||||
Class to manipulate HTTP 'Authorization' header value.
|
||||
]"
|
||||
|
||||
collection: EWF
|
||||
tags: http,authorization,authentication,web
|
||||
copyright: 2011-2016, Jocelyn Fiat, Eiffel Software and others
|
||||
@@ -17,4 +17,3 @@ note
|
||||
link[source]: "github" https://github.com/EiffelWebFramework/EWF/tree/master/library/server/authentication/http_authorization
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -76,13 +76,13 @@ feature -- Initialization
|
||||
a_http_authorization /= Void implies http_authorization /= Void
|
||||
end
|
||||
|
||||
make_basic_auth (u: READABLE_STRING_32; p: READABLE_STRING_32)
|
||||
make_basic_auth (u: READABLE_STRING_GENERAL; p: READABLE_STRING_GENERAL)
|
||||
-- Create a Basic authentication.
|
||||
do
|
||||
make_custom_auth (u, p, Basic_auth_type)
|
||||
end
|
||||
|
||||
make_custom_auth (u: READABLE_STRING_32; p: READABLE_STRING_32; a_type: READABLE_STRING_8)
|
||||
make_custom_auth (u: READABLE_STRING_GENERAL; p: READABLE_STRING_GENERAL; a_type: READABLE_STRING_8)
|
||||
-- Create a custom `a_type' authentication.
|
||||
require
|
||||
a_type_accepted: a_type.is_case_insensitive_equal (Basic_auth_type)
|
||||
@@ -90,15 +90,20 @@ feature -- Initialization
|
||||
local
|
||||
t: STRING_8
|
||||
utf: UTF_CONVERTER
|
||||
s: STRING_32
|
||||
do
|
||||
login := u
|
||||
password := p
|
||||
create login.make_from_string_general (u)
|
||||
create password.make_from_string_general (p)
|
||||
create t.make_from_string (a_type)
|
||||
t.left_adjust; t.right_adjust
|
||||
type := t
|
||||
if t.is_case_insensitive_equal (Basic_auth_type) then
|
||||
type := Basic_auth_type
|
||||
create http_authorization.make_from_string ("Basic " + (create {BASE64}).encoded_string (utf.string_32_to_utf_8_string_8 (u + {STRING_32} ":" + p)))
|
||||
create s.make_from_string_general (u)
|
||||
s.extend (':')
|
||||
s.append_string_general (p)
|
||||
create http_authorization.make_from_string ("Basic " + (create {BASE64}).encoded_string (utf.string_32_to_utf_8_string_8 (s)))
|
||||
|
||||
elseif t.is_case_insensitive_equal (Digest_auth_type) then
|
||||
type := Digest_auth_type
|
||||
to_implement ("HTTP Authorization %""+ t +"%", not yet implemented")
|
||||
@@ -115,9 +120,9 @@ feature -- Access
|
||||
|
||||
type: READABLE_STRING_8
|
||||
|
||||
login: detachable READABLE_STRING_32
|
||||
login: detachable IMMUTABLE_STRING_32
|
||||
|
||||
password: detachable READABLE_STRING_32
|
||||
password: detachable IMMUTABLE_STRING_32
|
||||
|
||||
feature -- Status report
|
||||
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
package ewsgi
|
||||
|
||||
project
|
||||
ewsgi = "ewsgi-safe.ecf"
|
||||
ewsgi = "ewsgi.ecf"
|
||||
connector_cgi = "connectors/cgi/cgi-safe.ecf"
|
||||
connector_cgi = "connectors/cgi/cgi.ecf"
|
||||
connector_libfcgi = "connectors/libfcgi/libfcgi-safe.ecf"
|
||||
connector_libfcgi = "connectors/libfcgi/libfcgi.ecf"
|
||||
connector_null = "connectors/null/null-safe.ecf"
|
||||
connector_null = "connectors/null/null.ecf"
|
||||
connector_standalone = "connectors/standalone/standalone-safe.ecf"
|
||||
connector_standalone = "connectors/standalone/standalone.ecf"
|
||||
httpd = "connectors/standalone/src/httpd/httpd-safe.ecf"
|
||||
httpd = "connectors/standalone/src/httpd/httpd.ecf"
|
||||
ewsgi_spec = "ewsgi_spec.ecf"
|
||||
connector_nino = "connectors/nino/nino.ecf"
|
||||
|
||||
note
|
||||
title: EWSGI
|
||||
description: "[
|
||||
Eiffel Web Server Gateway Interface (EWSGI) specification, and a few connectors.
|
||||
]"
|
||||
Eiffel Web Server Gateway Interface (EWSGI) specification, and a few connectors.
|
||||
]"
|
||||
|
||||
collection: EWF
|
||||
tags: ewsgi,cgi,web,httpd,ewf
|
||||
copyright: 2011-2016, Jocelyn Fiat, Eiffel Software and others
|
||||
@@ -26,5 +22,5 @@ note
|
||||
link[license]: http://www.eiffel.com/licensing/forum.txt
|
||||
link[source]: "github" https://github.com/EiffelWebFramework/EWF/tree/master/library/server/ewsgi
|
||||
link[doc]: "Documentation" https://github.com/EiffelWebFramework/EWF/tree/master/library/server/ewsgi/doc
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -8,19 +8,9 @@ deferred class
|
||||
|
||||
inherit
|
||||
HTTPD_REQUEST_HANDLER_I
|
||||
redefine
|
||||
is_persistent_connection_supported
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_persistent_connection_supported: BOOLEAN = False
|
||||
-- <Precursor>
|
||||
-- When there is no concurrency support, do not try to support
|
||||
-- persistent connection!
|
||||
|
||||
note
|
||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -167,7 +167,7 @@ feature -- Element change
|
||||
end
|
||||
|
||||
set_socket_timeout (a_nb_seconds: like socket_timeout)
|
||||
-- Set `socket_timeout' with `a_nb_seconds'
|
||||
-- Set `socket_timeout' with `a_nb_seconds'.
|
||||
do
|
||||
socket_timeout := a_nb_seconds
|
||||
ensure
|
||||
@@ -175,7 +175,7 @@ feature -- Element change
|
||||
end
|
||||
|
||||
set_socket_recv_timeout (a_nb_seconds: like socket_recv_timeout)
|
||||
-- Set `socket_recv_timeout' with `a_nb_seconds'
|
||||
-- Set `socket_recv_timeout' with `a_nb_seconds'.
|
||||
do
|
||||
socket_recv_timeout := a_nb_seconds
|
||||
ensure
|
||||
@@ -183,7 +183,7 @@ feature -- Element change
|
||||
end
|
||||
|
||||
set_keep_alive_timeout (a_seconds: like keep_alive_timeout)
|
||||
-- Set `keep_alive_timeout' with `a_seconds'
|
||||
-- Set `keep_alive_timeout' with `a_seconds'.
|
||||
do
|
||||
keep_alive_timeout := a_seconds
|
||||
ensure
|
||||
@@ -191,7 +191,7 @@ feature -- Element change
|
||||
end
|
||||
|
||||
set_max_keep_alive_requests (nb: like max_keep_alive_requests)
|
||||
-- Set `max_keep_alive_requests' with `nb'
|
||||
-- Set `max_keep_alive_requests' with `nb'.
|
||||
do
|
||||
max_keep_alive_requests := nb
|
||||
ensure
|
||||
@@ -254,7 +254,7 @@ feature -- Element change
|
||||
end
|
||||
|
||||
mark_secure
|
||||
-- Set is_secure in True
|
||||
-- Set is_secure in True.
|
||||
do
|
||||
set_is_secure (True)
|
||||
ensure
|
||||
@@ -287,7 +287,7 @@ feature -- Element change
|
||||
end
|
||||
|
||||
set_secure_protocol (a_version: NATURAL)
|
||||
-- Set `secure_protocol' with `a_version'
|
||||
-- Set `secure_protocol' with `a_version'.
|
||||
do
|
||||
secure_protocol := a_version
|
||||
ensure
|
||||
@@ -295,18 +295,19 @@ feature -- Element change
|
||||
end
|
||||
|
||||
set_secure_protocol_from_string (a_ssl_version: READABLE_STRING_GENERAL)
|
||||
-- Set `secure_protocol' with `a_ssl_version'
|
||||
-- Set `secure_protocol' with `a_ssl_version'.
|
||||
do
|
||||
if a_ssl_version.is_case_insensitive_equal ("ssl_2_3") then
|
||||
set_secure_protocol_to_ssl_2_or_3
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_0") then
|
||||
set_secure_protocol_to_tls_1_0
|
||||
if a_ssl_version.is_case_insensitive_equal ("tls_1_2") then
|
||||
set_secure_protocol_to_tls_1_2
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_1") then
|
||||
set_secure_protocol_to_tls_1_1
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_2") then
|
||||
set_secure_protocol_to_tls_1_2
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("tls_1_0") then
|
||||
set_secure_protocol_to_tls_1_0
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("dtls_1_0") then
|
||||
set_secure_protocol_to_dtls_1_0
|
||||
elseif a_ssl_version.is_case_insensitive_equal ("ssl_2_3") then
|
||||
-- Obsolete!
|
||||
set_secure_protocol_to_ssl_2_or_3
|
||||
else -- Default
|
||||
set_secure_protocol_to_tls_1_2
|
||||
end
|
||||
@@ -316,6 +317,8 @@ feature -- SSL Helpers
|
||||
|
||||
set_secure_protocol_to_ssl_2_or_3
|
||||
-- Set `secure_protocol' with `Ssl_23'.
|
||||
obsolete
|
||||
"Use `set_secure_protocol_to_tls_1_2` [2017-06-23]."
|
||||
deferred
|
||||
end
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ feature -- Default timeout settings
|
||||
|
||||
feature -- Default persistent connection settings
|
||||
|
||||
default_keep_alive_timeout: INTEGER = 15 -- seconds
|
||||
default_max_keep_alive_requests: INTEGER = 100
|
||||
default_keep_alive_timeout: INTEGER = 5 -- seconds
|
||||
default_max_keep_alive_requests: INTEGER = 300
|
||||
|
||||
note
|
||||
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
<exclude>/\.svn$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="http_network" location="..\..\network\http_network\http_network.ecf" readonly="false"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
|
||||
@@ -16,8 +14,11 @@
|
||||
<condition>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</library>
|
||||
<library name="openssl" location="$ISE_LIBRARY\unstable\library\network\openssl\openssl.ecf">
|
||||
<condition>
|
||||
<custom name="httpd_ssl_enabled" value="true"/>
|
||||
<version type="compiler" min="17.10.0.0"/>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</library>
|
||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf">
|
||||
@@ -35,16 +36,12 @@
|
||||
<cluster name="no_ssl" location="$|no_ssl\" recursive="true">
|
||||
<condition>
|
||||
<custom name="ssl_enabled" excluded_value="true"/>
|
||||
<custom name="httpd_ssl_enabled" excluded_value="true"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="ssl" location="$|ssl\" recursive="true">
|
||||
<condition>
|
||||
<custom name="ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
<condition>
|
||||
<custom name="httpd_ssl_enabled" value="true"/>
|
||||
</condition>
|
||||
</cluster>
|
||||
<cluster name="concurrency_none" location="$|concurrency\none\" recursive="true">
|
||||
<condition>
|
||||
|
||||
@@ -140,7 +140,8 @@ feature -- Settings
|
||||
is_persistent_connection_supported: BOOLEAN
|
||||
-- Is persistent connection supported?
|
||||
do
|
||||
Result := {HTTPD_SERVER}.is_persistent_connection_supported and then max_keep_alive_requests > 0
|
||||
Result := {HTTPD_SERVER}.is_persistent_connection_supported and then
|
||||
max_keep_alive_requests /= 0 --| `-1` no limit
|
||||
end
|
||||
|
||||
is_next_persistent_connection_supported: BOOLEAN
|
||||
@@ -247,7 +248,8 @@ feature -- Execution
|
||||
l_exit
|
||||
loop
|
||||
n := n + 1
|
||||
if n >= m then
|
||||
-- If `m` is `-1`, no limit for the number of keep_alive requests.
|
||||
if m >= 0 and n >= m then
|
||||
is_next_persistent_connection_supported := False
|
||||
elseif n > 1 and is_verbose then
|
||||
log ("Reuse connection (" + n.out + ")", information_level)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package httpd
|
||||
|
||||
project
|
||||
httpd = "httpd-safe.ecf"
|
||||
httpd = "httpd.ecf"
|
||||
|
||||
note
|
||||
title: HTTP server
|
||||
description: "[
|
||||
Simple HTTP listener and handler, that can be extended easily.
|
||||
]"
|
||||
Simple HTTP listener and handler, that can be extended easily.
|
||||
]"
|
||||
|
||||
tags: http,httpd,server,web
|
||||
collection: EWF
|
||||
copyright: 2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others
|
||||
|
||||
@@ -36,9 +36,16 @@ feature -- Access
|
||||
feature -- SSL Helpers
|
||||
|
||||
set_secure_protocol_to_ssl_2_or_3
|
||||
-- Set `secure_protocol' with `Ssl_23'.
|
||||
-- Set `ssl_protocol' with `Ssl_23'.
|
||||
-- Protocol not supported anymore.
|
||||
obsolete
|
||||
"Use set_secure_protocol_to_tls_1_2 [2017-06-23]."
|
||||
local
|
||||
err: DEVELOPER_EXCEPTION
|
||||
do
|
||||
set_secure_protocol ({SSL_PROTOCOL}.Ssl_23)
|
||||
create err
|
||||
err.set_description ("SSL_2 or SSL_3 are not supported anymore, upgrate to TLS set_secure_protocol_to_tls_1_2")
|
||||
err.raise
|
||||
end
|
||||
|
||||
set_secure_protocol_to_tls_1_0
|
||||
@@ -67,7 +74,7 @@ feature -- SSL Helpers
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -4,16 +4,16 @@ setup
|
||||
compile_library = Clib
|
||||
|
||||
project
|
||||
libfcgi = "libfcgi-safe.ecf"
|
||||
libfcgi = "libfcgi.ecf"
|
||||
|
||||
note
|
||||
title: Eiffel libfcgi wrapper
|
||||
description: "[
|
||||
Wrapper on modified libfcgi.
|
||||
(modification: added 64 bits support)
|
||||
It brings implementation for FCGI protocol.
|
||||
]"
|
||||
Wrapper on modified libfcgi.
|
||||
(modification: added 64 bits support)
|
||||
It brings implementation for FCGI protocol.
|
||||
]"
|
||||
|
||||
collection: EWF
|
||||
tags: fcgi,libfcgi,cgi,http,web,ewf
|
||||
copyright: 2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others
|
||||
|
||||
@@ -66,7 +66,7 @@ feature -- Access: connection
|
||||
end
|
||||
|
||||
max_tcp_clients: INTEGER assign set_max_tcp_clients
|
||||
-- Listen on socket for at most `queue' connections.
|
||||
-- Listen on socket for at most `max_tcp_clients' connections.
|
||||
do
|
||||
Result := option_integer_value ("max_tcp_clients", 0)
|
||||
end
|
||||
@@ -104,11 +104,26 @@ feature -- Access: persistent connection
|
||||
-- Maximum number of requests allowed per persistent connection.
|
||||
-- Recommended a high setting.
|
||||
-- To disable KeepAlive, set `max_keep_alive_requests' to 0.
|
||||
-- To have no limit, set `max_keep_alive_requests' to -1.
|
||||
-- By default: {HTTPD_CONFIGURATION_I}.default_max_keep_alive_requests .
|
||||
do
|
||||
Result := option_integer_value ("max_keep_alive_requests", 0)
|
||||
end
|
||||
|
||||
persistent_connection_disabled: BOOLEAN
|
||||
-- Persistent connection disabled?
|
||||
-- (or Keep-Alive disabled).
|
||||
do
|
||||
Result := max_keep_alive_requests = 0
|
||||
end
|
||||
|
||||
has_unlimited_keep_alive_requests: BOOLEAN
|
||||
-- Has unlimited count of keep alive requests.
|
||||
-- i.e no limit of number of requests allowed per persistent connection.
|
||||
do
|
||||
Result := max_keep_alive_requests < 0
|
||||
end
|
||||
|
||||
feature -- Access: SSL
|
||||
|
||||
is_secure: BOOLEAN assign set_is_secure
|
||||
@@ -205,6 +220,16 @@ feature -- Element change
|
||||
set_numeric_option ("max_keep_alive_requests", nb)
|
||||
end
|
||||
|
||||
set_unlimited_keep_alive_requests
|
||||
do
|
||||
set_max_keep_alive_requests (-1)
|
||||
end
|
||||
|
||||
disable_persistent_connection
|
||||
do
|
||||
set_max_keep_alive_requests (0)
|
||||
end
|
||||
|
||||
set_is_secure (b: BOOLEAN)
|
||||
-- Set secured connection enabled to `b'.
|
||||
-- i.e if connection is using SSL/TLS.
|
||||
|
||||
@@ -1,40 +1,32 @@
|
||||
|
||||
package wsf
|
||||
|
||||
project
|
||||
wsf = "wsf-safe.ecf"
|
||||
wsf = "wsf.ecf"
|
||||
wsf_extension = "wsf_extension-safe.ecf"
|
||||
wsf_extension = "wsf_extension.ecf"
|
||||
wsf_policy_driven = "wsf_policy_driven-safe.ecf"
|
||||
wsf_policy_driven = "wsf_policy_driven.ecf"
|
||||
wsf_router_context = "wsf_router_context-safe.ecf"
|
||||
wsf_router_context = "wsf_router_context.ecf"
|
||||
wsf_session = "wsf_session-safe.ecf"
|
||||
wsf_session = "wsf_session.ecf"
|
||||
wsf_cgi = "connector/cgi-safe.ecf"
|
||||
wsf_cgi = "connector/cgi.ecf"
|
||||
wsf_libfcgi = "connector/libfcgi-safe.ecf"
|
||||
wsf_libfcgi = "connector/libfcgi.ecf"
|
||||
wsf_openshift = "connector/openshift-safe.ecf"
|
||||
default_cgi = "default/cgi-safe.ecf"
|
||||
default_cgi = "default/cgi.ecf"
|
||||
default_libfcgi = "default/libfcgi-safe.ecf"
|
||||
default_libfcgi = "default/libfcgi.ecf"
|
||||
default_openshift = "default/openshift-safe.ecf"
|
||||
wsf_standalone = "connector/standalone-safe.ecf"
|
||||
default_openshift = "default/openshift.ecf"
|
||||
wsf_standalone = "connector/standalone.ecf"
|
||||
default_standalone = "default/standalone-safe.ecf"
|
||||
default_standalone = "default/standalone.ecf"
|
||||
|
||||
wsf_all = "connector/all.ecf"
|
||||
wsf_nino = "connector/nino.ecf"
|
||||
wsf_openshift = "connector/openshift.ecf"
|
||||
wsf_standalone_websocket = "connector/standalone_websocket.ecf"
|
||||
default_nino = "default/nino.ecf"
|
||||
|
||||
note
|
||||
title: Web Server Foundation
|
||||
description: "[
|
||||
Core of the Eiffel Web Framework (EWF).
|
||||
Provide the request, response, router, ... interfaces.
|
||||
The foundation to build web server application.
|
||||
]"
|
||||
Core of the Eiffel Web Framework (EWF).
|
||||
Provide the request, response, router, ... interfaces.
|
||||
The foundation to build web server application.
|
||||
]"
|
||||
|
||||
tags: ewf,server,httpd,request,connector,web
|
||||
collection: EWF
|
||||
copyright: 2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others
|
||||
@@ -44,4 +36,3 @@ note
|
||||
link[doc]: "Documentation" http://eiffelwebframework.github.io/EWF/
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Access
|
||||
|
||||
default_value: detachable READABLE_STRING_GENERAL
|
||||
default_value: detachable READABLE_STRING_32
|
||||
|
||||
rows: INTEGER
|
||||
|
||||
@@ -54,9 +54,13 @@ feature -- Element change
|
||||
end
|
||||
end
|
||||
|
||||
set_default_value (v: like default_value)
|
||||
set_default_value (v: detachable READABLE_STRING_GENERAL)
|
||||
do
|
||||
default_value := v
|
||||
if v = Void then
|
||||
default_value := Void
|
||||
else
|
||||
default_value := v.as_string_32
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
description : "Objects containing widget WSF_WIDGET objects, and add specific form support (notion of form fields)."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_FORM_COMPOSITE
|
||||
|
||||
@@ -48,7 +48,9 @@ feature -- Access
|
||||
|
||||
item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE
|
||||
do
|
||||
Result := items.item (a_name.as_string_8)
|
||||
if a_name.is_valid_as_string_8 then
|
||||
Result := items.item (a_name.to_string_8)
|
||||
end
|
||||
end
|
||||
|
||||
string_item (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||
|
||||
@@ -39,7 +39,7 @@ feature -- Element Change
|
||||
set_max (a_val: INTEGER)
|
||||
-- Set `max' with `a_val'.
|
||||
do
|
||||
set_max_string(a_val.out)
|
||||
set_max_string (a_val.out)
|
||||
ensure
|
||||
max_set: attached max as l_max implies l_max.same_string (a_val.out)
|
||||
end
|
||||
@@ -94,7 +94,6 @@ feature -- Element Change
|
||||
step_set: attached step as l_step implies l_step.same_string_general (a_val)
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Conversion
|
||||
|
||||
append_numeric_input_attributes_to (a_target: STRING)
|
||||
@@ -103,7 +102,7 @@ feature {NONE} -- Conversion
|
||||
--min
|
||||
if attached min as l_min then
|
||||
a_target.append (" min=%"")
|
||||
a_target.append(l_min)
|
||||
a_target.append (l_min)
|
||||
a_target.append_character ('%"')
|
||||
end
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ feature {NONE} -- Initialization
|
||||
name := a_name
|
||||
end
|
||||
|
||||
make_with_text (a_name: like name; a_text: READABLE_STRING_32)
|
||||
make_with_text (a_name: like name; a_text: READABLE_STRING_GENERAL)
|
||||
do
|
||||
make (a_name)
|
||||
set_text_value (a_text)
|
||||
@@ -44,7 +44,7 @@ feature -- Access
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_text_value (s: detachable READABLE_STRING_32)
|
||||
set_text_value (s: detachable READABLE_STRING_GENERAL)
|
||||
do
|
||||
set_default_value (s)
|
||||
end
|
||||
@@ -73,9 +73,13 @@ feature -- Element change
|
||||
end
|
||||
end
|
||||
|
||||
set_default_value (v: like default_value)
|
||||
set_default_value (v: detachable READABLE_STRING_GENERAL)
|
||||
do
|
||||
default_value := v
|
||||
if v = Void then
|
||||
default_value := Void
|
||||
else
|
||||
default_value := v.as_string_32
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
@@ -35,12 +35,17 @@ feature -- Access
|
||||
|
||||
feature -- Change element
|
||||
|
||||
set_placeholder (a_placeholder: READABLE_STRING_32)
|
||||
set_placeholder (a_placeholder: detachable READABLE_STRING_GENERAL)
|
||||
-- Set `placeholder' with `a_placeholder'.
|
||||
do
|
||||
placeholder := a_placeholder
|
||||
if a_placeholder = Void then
|
||||
placeholder := Void
|
||||
else
|
||||
placeholder := a_placeholder.as_string_32
|
||||
end
|
||||
ensure
|
||||
placeholder_set: attached placeholder as l_placeholder implies l_placeholder = a_placeholder
|
||||
placeholder_set: (a_placeholder = Void implies placeholder = Void)
|
||||
or (a_placeholder /= Void implies (attached placeholder as l_placeholder and then a_placeholder.same_string (l_placeholder)))
|
||||
end
|
||||
|
||||
enable_autofocus
|
||||
@@ -91,16 +96,21 @@ feature -- Change element
|
||||
required_flase: not required
|
||||
end
|
||||
|
||||
set_pattern (a_pattern: READABLE_STRING_32)
|
||||
set_pattern (a_pattern: READABLE_STRING_GENERAL)
|
||||
-- Set `pattern' with `a_pattern'.
|
||||
-- Example:[0-9][A-Z]{3}
|
||||
-- Check HTML5 patterns site.
|
||||
note
|
||||
EIS: "name=HTML5 Patterns", "src=http://html5pattern.com/"
|
||||
do
|
||||
pattern := a_pattern
|
||||
if a_pattern = Void then
|
||||
pattern := Void
|
||||
else
|
||||
pattern := a_pattern.as_string_32
|
||||
end
|
||||
ensure
|
||||
pattern_set: attached pattern as l_pattern implies l_pattern = a_pattern
|
||||
pattern_set: (a_pattern = Void implies pattern = Void) or
|
||||
a_pattern /= Void implies attached pattern as l_pattern and then a_pattern.same_string (l_pattern)
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ feature -- Access
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
|
||||
set_formnovalidate
|
||||
-- Set formnovalidate to True.
|
||||
do
|
||||
@@ -60,49 +59,69 @@ feature -- Element Change
|
||||
formnovalidate_false: not formnovalidate
|
||||
end
|
||||
|
||||
set_formaction (a_action: READABLE_STRING_GENERAL)
|
||||
set_formaction (a_action: detachable READABLE_STRING_GENERAL)
|
||||
-- Set `formaction' with `a_action'.
|
||||
-- Example:<input type="submit" value="Submit" formaction="/users">
|
||||
require
|
||||
is_valid_as_string_8: a_action.is_valid_as_string_8
|
||||
is_valid_as_string_8: a_action /= Void implies a_action.is_valid_as_string_8
|
||||
do
|
||||
formaction := a_action.to_string_8
|
||||
if a_action = Void then
|
||||
formaction := Void
|
||||
else
|
||||
formaction := a_action.to_string_8
|
||||
end
|
||||
ensure
|
||||
formaction_set: attached formaction as l_action implies l_action = a_action
|
||||
formaction_set: (a_action = Void implies formaction = Void)
|
||||
or (a_action /= Void implies (attached formaction as l_action and then a_action.same_string (l_action)))
|
||||
end
|
||||
|
||||
set_formenctype (a_enctype: READABLE_STRING_GENERAL)
|
||||
set_formenctype (a_enctype: detachable READABLE_STRING_GENERAL)
|
||||
-- Set `formenctype' with `a_enctype'.
|
||||
-- Example: <input type="submit" value="Submit" formenctype="application/x-www-form-urlencoded">
|
||||
require
|
||||
is_valid_as_string_8: a_enctype.is_valid_as_string_8
|
||||
is_valid_as_string_8: a_enctype /= Void implies a_enctype.is_valid_as_string_8
|
||||
do
|
||||
formenctype := a_enctype.to_string_8
|
||||
if a_enctype = Void then
|
||||
formenctype := Void
|
||||
else
|
||||
formenctype := a_enctype.to_string_8
|
||||
end
|
||||
ensure
|
||||
formenctype_set: attached formenctype as l_enctype implies l_enctype = a_enctype
|
||||
formenctype_set: (a_enctype = Void implies formenctype = Void)
|
||||
or (a_enctype /= Void implies (attached formenctype as l_enctype and then a_enctype.same_string (l_enctype)))
|
||||
end
|
||||
|
||||
set_formmethod (a_method: READABLE_STRING_GENERAL)
|
||||
set_formmethod (a_method: detachable READABLE_STRING_GENERAL)
|
||||
-- Set `formmethod' with `a_method'.
|
||||
-- Example: <input type="submit" value="Submit" formmethod="POST">
|
||||
--! require is_valid_method: [PUT, POST, DELETE, GET, ...]
|
||||
require
|
||||
is_valid_as_string_8: a_method.is_valid_as_string_8
|
||||
is_valid_as_string_8: a_method /= Void implies a_method.is_valid_as_string_8
|
||||
do
|
||||
formmethod := a_method.to_string_8
|
||||
if a_method = Void then
|
||||
formmethod := Void
|
||||
else
|
||||
formmethod := a_method.to_string_8
|
||||
end
|
||||
ensure
|
||||
formmethod_set: attached formmethod as l_method implies l_method = a_method
|
||||
formmethod_set: (a_method = Void implies formmethod = Void)
|
||||
or (a_method /= Void implies (attached formmethod as l_method and then a_method.same_string (l_method)))
|
||||
end
|
||||
|
||||
set_formtarget (a_target: READABLE_STRING_GENERAL)
|
||||
set_formtarget (a_target: detachable READABLE_STRING_GENERAL)
|
||||
-- Set `formtarget' with `a_target'.
|
||||
-- Example: <input type="submit" value="Submit" formtarget="_self">
|
||||
require
|
||||
is_valid_as_string_8: a_target.is_valid_as_string_8
|
||||
is_valid_as_string_8: a_target /= Void implies a_target.is_valid_as_string_8
|
||||
do
|
||||
formtarget := a_target.to_string_8
|
||||
if a_target = Void then
|
||||
formtarget := Void
|
||||
else
|
||||
formtarget := a_target.to_string_8
|
||||
end
|
||||
ensure
|
||||
formtarget_set: attached formtarget as l_target implies l_target = a_target
|
||||
formtarget_set: (a_target = Void implies formtarget = Void)
|
||||
or (a_target /= Void implies (attached formtarget as l_target and then a_target.same_string (l_target)))
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
note
|
||||
description : "Objects that ..."
|
||||
author : "$Author$"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
description : "Objects containing WSF_WIDGET objects."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
WSF_WIDGET_COMPOSITE
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
package encoder
|
||||
|
||||
project
|
||||
encoder = "encoder-safe.ecf"
|
||||
encoder = "encoder.ecf"
|
||||
|
||||
note
|
||||
title: Text encoders
|
||||
description: "[
|
||||
Text encoders used in web technologies:
|
||||
- HTML encoder
|
||||
- XML encoder
|
||||
- JSON encoder
|
||||
- UTF8
|
||||
- BASE64
|
||||
]"
|
||||
Text encoders used in web technologies:
|
||||
- HTML encoder
|
||||
- XML encoder
|
||||
- JSON encoder
|
||||
- UTF8
|
||||
- BASE64
|
||||
]"
|
||||
|
||||
collection: EWF
|
||||
tags: html,xml,percent encoding,web,json,utf
|
||||
copyright: 2011-2016, Jocelyn Fiat, Eiffel Software and others
|
||||
@@ -23,4 +23,3 @@ note
|
||||
link[doc]: "Documentation" https://github.com/EiffelWebFramework/EWF/blob/master/library/text/encoder/README.md
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package feed
|
||||
|
||||
project
|
||||
feed = "feed-safe.ecf"
|
||||
feed = "feed.ecf"
|
||||
|
||||
note
|
||||
title: Eiffel FEED parser
|
||||
description: "[
|
||||
RSS2.0 and ATOM feed parser.
|
||||
Feed visitor including HTML generation from FEED Eiffel objects.
|
||||
]"
|
||||
RSS2.0 and ATOM feed parser.
|
||||
Feed visitor including HTML generation from FEED Eiffel objects.
|
||||
]"
|
||||
|
||||
tags: rss,atom,feed,html,generator,parser
|
||||
copyright: 2011-2016, Jocelyn Fiat, Eiffel Software and others
|
||||
license: Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package uri_template
|
||||
|
||||
project
|
||||
uri_template = "uri_template-safe.ecf"
|
||||
uri_template = "uri_template.ecf"
|
||||
|
||||
note
|
||||
title: URI Template
|
||||
description: "[
|
||||
Implement URI Template as described at http://tools.ietf.org/rfc/rfc6570.txt
|
||||
Implement URI Template as described at http://tools.ietf.org/rfc/rfc6570.txt
|
||||
|
||||
Support for URI template string expansion
|
||||
But also partial URI Template matching
|
||||
]"
|
||||
|
||||
Support for URI template string expansion
|
||||
But also partial URI Template matching
|
||||
]"
|
||||
collection: EWF
|
||||
tags: uri template,router,generator,url
|
||||
copyright: 2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others
|
||||
@@ -21,4 +21,3 @@ note
|
||||
link[doc]: "Documentation" https://github.com/EiffelWebFramework/EWF/tree/master/library/text/parser/uri_template/README.md
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
package error
|
||||
|
||||
project
|
||||
error = "error-safe.ecf"
|
||||
error = "error.ecf"
|
||||
|
||||
note
|
||||
title: Error framework
|
||||
description: "[
|
||||
Errors and associated handler, to manage errors and also provides a way to synchronize one or many error handlers.
|
||||
This is convenient to propagate error from a layer to another without adding unwanted dependencies.
|
||||
]"
|
||||
Errors and associated handler, to manage errors and also provides a way to synchronize one or many error handlers.
|
||||
This is convenient to propagate error from a layer to another without adding unwanted dependencies.
|
||||
]"
|
||||
|
||||
collection: EWF
|
||||
tags: error,framework
|
||||
license: Eiffel Forum License v2
|
||||
copyright: Jocelyn Fiat, Eiffel Software and others.
|
||||
link[license]: http://www.eiffel.com/licensing/forum.txt
|
||||
link[source]: "github" https://github.com/EiffelWebFramework/EWF/tree/master/library/utility/general/error
|
||||
link[source]: "github" https://github.com/EiffelWebFramework/EWF/tree/master/library/utility/general/error
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
</option>
|
||||
<library name="default_standalone" location="..\..\library\server\wsf\default\standalone.ecf" readonly="false" use_application_options="true"/>
|
||||
<cluster name="src" location="src\" recursive="true"/>
|
||||
<override name="override" location="override\" recursive="true"/>
|
||||
</target>
|
||||
<target name="hello_cgi" extends="hello_dev">
|
||||
<library name="default_cgi" location="..\..\library\server\wsf\default\cgi.ecf"/>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<capability>
|
||||
<catcall_detection use="none"/>
|
||||
</capability>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
|
||||
<cluster name="src" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
253
tests/standalone/client/test_app.e
Normal file
253
tests/standalone/client/test_app.e
Normal file
@@ -0,0 +1,253 @@
|
||||
note
|
||||
description: "[
|
||||
Enter class description here!
|
||||
]"
|
||||
|
||||
class
|
||||
TEST_APP
|
||||
|
||||
inherit
|
||||
SHARED_EXECUTION_ENVIRONMENT
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Instantiate Current object.
|
||||
local
|
||||
h, res: STRING
|
||||
i: INTEGER
|
||||
l_test_name: detachable READABLE_STRING_GENERAL
|
||||
choices: HASH_TABLE [READABLE_STRING_GENERAL, INTEGER]
|
||||
do
|
||||
create h.make_empty
|
||||
h.append_character ((0).to_character_8)
|
||||
h.append_character ((0).to_character_8)
|
||||
h.append_character ((255).to_character_8)
|
||||
h.append_character ((255).to_character_8)
|
||||
|
||||
i := 0
|
||||
if attached execution_environment.arguments.argument (1) as tn then
|
||||
l_test_name := tn
|
||||
else
|
||||
create choices.make (tests.count)
|
||||
across
|
||||
tests as ic
|
||||
loop
|
||||
i := i + 1
|
||||
choices.force (ic.key, i)
|
||||
print (i.out + " - " + ic.key.out + "%N")
|
||||
end
|
||||
print (" > ")
|
||||
io.read_line
|
||||
res := io.last_string
|
||||
res.adjust
|
||||
if
|
||||
res.is_integer and then
|
||||
attached choices [res.to_integer] as tn
|
||||
then
|
||||
l_test_name := tn
|
||||
end
|
||||
end
|
||||
if
|
||||
l_test_name /= Void and then
|
||||
attached tests [l_test_name] as proc
|
||||
then
|
||||
proc.call ()
|
||||
else
|
||||
print ("Quit...%N")
|
||||
end
|
||||
end
|
||||
|
||||
port_number: INTEGER = 9090
|
||||
|
||||
hostname: STRING = "localhost"
|
||||
|
||||
has_error: BOOLEAN
|
||||
|
||||
tests: STRING_TABLE [PROCEDURE]
|
||||
once
|
||||
create Result.make (10)
|
||||
Result.force (agent cli_execute_get_request, "get_request")
|
||||
Result.force (agent execute_get_request (1, 0), "get_request (1,0)")
|
||||
Result.force (agent execute_get_request (10, 0), "get_request (10,0)")
|
||||
Result.force (agent execute_get_request (1, 10_000), "get_request (1, 10000)")
|
||||
Result.force (agent execute_get_request (10, 10_000), "get_request (10, 10000)")
|
||||
Result.force (agent execute_wait_for_ever, "wait_for_ever")
|
||||
end
|
||||
|
||||
feature -- Execution
|
||||
|
||||
wait_ms (a_delay_ms: INTEGER; m: detachable READABLE_STRING_8)
|
||||
local
|
||||
i64: INTEGER_64
|
||||
do
|
||||
if a_delay_ms > 0 then
|
||||
if has_error then
|
||||
print ("[ERROR/WAIT] Skipped due to previous error%N")
|
||||
else
|
||||
|
||||
i64 := a_delay_ms.as_integer_64 * {INTEGER_64} 1_000_000
|
||||
if m /= Void then
|
||||
print ("[WAIT] " + i64.out + " nanoseconds -> " + m + "%N")
|
||||
else
|
||||
print ("[WAIT] " + i64.out + " nanoseconds.%N")
|
||||
end
|
||||
execution_environment.sleep (i64) -- nanoseconds
|
||||
print ("[WAIT] done.%N")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cli_execute_get_request
|
||||
local
|
||||
i,n: INTEGER
|
||||
rq_nb: INTEGER
|
||||
sl_val: INTEGER
|
||||
do
|
||||
if attached execution_environment.arguments as args then
|
||||
n := args.argument_count
|
||||
rq_nb := 1
|
||||
sl_val := 0
|
||||
i := 1
|
||||
if n > i then
|
||||
if args.argument (i).is_case_insensitive_equal_general ("get_request") then
|
||||
if n >= i + 1 then
|
||||
rq_nb := args.argument (i + 1).to_integer
|
||||
if n >= i + 2 then
|
||||
sl_val := args.argument (i + 2).to_integer
|
||||
end
|
||||
end
|
||||
execute_get_request (rq_nb, sl_val)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
execute_get_request (rq_nb: INTEGER; a_delay_ms: INTEGER)
|
||||
require
|
||||
rq_nb > 0
|
||||
local
|
||||
l_socket: NETWORK_STREAM_SOCKET
|
||||
l_packet: PACKET
|
||||
l_header_done, l_done: BOOLEAN
|
||||
line, txt: READABLE_STRING_8
|
||||
h: STRING
|
||||
len: INTEGER
|
||||
i: INTEGER
|
||||
do
|
||||
create l_socket.make_client_by_port (port_number, hostname)
|
||||
l_socket.connect
|
||||
|
||||
from
|
||||
i := rq_nb
|
||||
until
|
||||
i <= 0
|
||||
loop
|
||||
i := i - 1
|
||||
|
||||
print ("GET /test/"+ i.out +" HTTP/1.1%N")
|
||||
-- socket_put_string (l_socket, "GET /test/"+ i.out +" HTTP/1.1%R%N")
|
||||
|
||||
socket_put_string (l_socket, "GET /test/"+ i.out)
|
||||
wait_ms (a_delay_ms, "inside GET request line")
|
||||
socket_put_string (l_socket, " HTTP/1.1%R%N")
|
||||
wait_ms (a_delay_ms, "before Host")
|
||||
socket_put_string (l_socket, "Host: localhost:9090%R%N")
|
||||
wait_ms (a_delay_ms, "before Accept")
|
||||
socket_put_string (l_socket, "Accept: */*%R%N")
|
||||
wait_ms (a_delay_ms, "before CRNL")
|
||||
socket_put_string (l_socket, "%R%N")
|
||||
wait_ms (a_delay_ms, "before reading!")
|
||||
|
||||
if not has_error then
|
||||
from
|
||||
l_done := False
|
||||
l_header_done := False
|
||||
create h.make_empty
|
||||
until
|
||||
l_done
|
||||
loop
|
||||
if l_header_done then
|
||||
l_socket.read_stream (len)
|
||||
txt := l_socket.last_string
|
||||
print ("BODY:%N")
|
||||
print (txt)
|
||||
print ("%N")
|
||||
if txt.count /= len then
|
||||
print ("BAD len: " + txt.count.out + " /= " + len.out + "%N")
|
||||
end
|
||||
l_done := True
|
||||
else
|
||||
l_socket.read_line
|
||||
line := l_socket.last_string
|
||||
if l_socket.was_error then
|
||||
l_done := True
|
||||
elseif line.is_empty or (line.count = 1 and line[1] = '%R') then
|
||||
l_header_done := True
|
||||
else
|
||||
if line.starts_with_general ("Content-Length:") then
|
||||
len := line.substring (16, line.count).to_integer
|
||||
end
|
||||
h.append (line)
|
||||
h.append ("%R%N")
|
||||
|
||||
print ("HEADER:")
|
||||
print (line)
|
||||
print ("%N")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
execute_wait_for_ever
|
||||
local
|
||||
l_socket: NETWORK_STREAM_SOCKET
|
||||
l_packet: PACKET
|
||||
do
|
||||
create l_socket.make_client_by_port(9090, "localhost")
|
||||
l_socket.connect
|
||||
|
||||
create l_packet.make(1)
|
||||
l_packet.put_element('a', 0)
|
||||
|
||||
l_socket.send(l_packet, 0)
|
||||
|
||||
from
|
||||
|
||||
until
|
||||
not l_socket.is_connected
|
||||
loop
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
socket_put_string (a_socket: NETWORK_STREAM_SOCKET; s: STRING_8)
|
||||
local
|
||||
retried: BOOLEAN
|
||||
t: STRING
|
||||
i: INTEGER
|
||||
do
|
||||
if has_error then
|
||||
create t.make_from_string (s)
|
||||
i := t.index_of ('%N', 1)
|
||||
if i > 0 then
|
||||
t.keep_head (i - 1)
|
||||
end
|
||||
t.adjust
|
||||
print ("[ERROR] Skip put_string ("+ s +"..)%N")
|
||||
elseif retried then
|
||||
has_error := True
|
||||
else
|
||||
a_socket.put_string (s)
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user