Basic initial Eiffel NET implementation.

This commit is contained in:
2015-06-17 10:32:07 +02:00
parent 29b55f36cf
commit 98e92ee0fe
5 changed files with 215 additions and 11 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-12-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-12-0 http://www.eiffel.com/developers/xml/configuration-1-12-0.xsd" name="http_client" uuid="628F5A96-021B-4191-926B-B3BF49272866" library_target="http_client">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-14-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-14-0 http://www.eiffel.com/developers/xml/configuration-1-14-0.xsd" name="http_client" uuid="628F5A96-021B-4191-926B-B3BF49272866" library_target="http_client">
<target name="http_client">
<root all_classes="true"/>
<file_rule>
@@ -11,8 +11,9 @@
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="curl" location="$ISE_LIBRARY\library\cURL\cURL-safe.ecf"/>
<library name="encoder" location="../../web/framework/ewf/text/encoder/encoder-safe.ecf"/>
<library name="encoder" location="..\..\text\encoder\encoder-safe.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri-safe.ecf"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -13,7 +13,7 @@ create
feature {NONE} -- Initialization
make (a_url: like url)
make (a_url: READABLE_STRING_8)
-- Initialize `Current'.
do
--| Default values
@@ -115,7 +115,7 @@ feature -- Access
loop
l_start := pos
--| Left justify
from until not h[l_start].is_space loop
from until not h [l_start].is_space loop
l_start := l_start + 1
end
pos := h.index_of ('%N', l_start)
@@ -129,7 +129,7 @@ feature -- Access
end
if l_end > 0 then
--| Right justify
from until not h[l_end].is_space loop
from until not h [l_end].is_space loop
l_end := l_end - 1
end
c := h.index_of (':', l_start)
@@ -308,7 +308,7 @@ feature {NONE} -- Implementation
-- Internal cached value for the headers
;note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -14,6 +14,11 @@ inherit
session
end
TRANSFER_COMMAND_CONSTANTS
undefine
is_equal
end
REFACTORING_HELPER
create
@@ -27,11 +32,162 @@ feature -- Access
response: HTTP_CLIENT_RESPONSE
-- <Precursor>
local
l_uri: URI
l_host: READABLE_STRING_8
l_request_uri: STRING
l_url: HTTP_URL
socket: NETWORK_STREAM_SOCKET
s: STRING
l_message: STRING
i,j: INTEGER
l_content_length: INTEGER
l_location: detachable READABLE_STRING_8
l_port: INTEGER
do
to_implement ("implementation based on EiffelNET")
(create {EXCEPTIONS}).die (0)
end
create Result.make (url)
-- Get URL data
create l_uri.make_from_string (url)
l_port := l_uri.port
if l_port = 0 then
if url.starts_with_general ("https://") then
l_port := 443
else
l_port := 80
end
end
if attached l_uri.host as h then
l_host := h
else
create l_url.make (url)
l_host := l_url.host
end
if attached l_uri.userinfo as l_userinfo then
-- TODO: Add support for HTTP Authorization
-- See {HTTP_AUTHORIZATION} from http_authorization EWF library.
end
create l_request_uri.make_from_string (l_uri.path)
if attached l_uri.query as l_query then
l_request_uri.append_character ('?')
l_request_uri.append (l_query)
end
-- Connect
create socket.make_client_by_port (l_port, l_host)
socket.set_timeout (timeout)
socket.set_connect_timeout (connect_timeout)
socket.connect
if socket.is_connected then
create s.make_from_string (request_method.as_upper)
s.append_character (' ')
s.append (l_request_uri)
s.append_character (' ')
s.append (Http_version)
s.append (Http_end_of_header_line)
s.append (Http_host_header)
s.append (": ")
s.append (l_host)
if headers.is_empty then
s.append (Http_end_of_command)
else
across
headers as ic
loop
s.append (ic.key)
s.append (": ")
s.append (ic.item)
s.append (Http_end_of_header_line)
end
s.append (Http_end_of_header_line)
end
socket.put_string (s)
-- Get header message
from
l_content_length := -1
create l_message.make_empty
socket.read_line
s := socket.last_string
until
s.same_string ("%R") or not socket.is_readable
loop
l_message.append (s)
l_message.append_character ('%N')
-- Search for Content-Length is not yet set.
if
l_content_length = -1 and then -- Content-Length is not yet found.
s.starts_with_general ("Content-Length:")
then
i := s.index_of (':', 1)
check has_colon: i > 0 end
s.remove_head (i)
s.right_adjust -- Remove trailing %R
if s.is_integer then
l_content_length := s.to_integer
end
elseif
l_location = Void and then
s.starts_with_general ("Location:")
then
i := s.index_of (':', 1)
check has_colon: i > 0 end
s.remove_head (i)
s.left_adjust -- Remove startung spaces
s.right_adjust -- Remove trailing %R
l_location := s
end
-- Next iteration
socket.read_line
s := socket.last_string
end
l_message.append (http_end_of_header_line)
-- Get content if any.
if
l_content_length > 0 and
socket.is_readable
then
socket.read_stream_thread_aware (l_content_length)
if socket.bytes_read /= l_content_length then
check full_content_read: False end
end
l_message.append (socket.last_string)
end
Result.set_response_message (l_message, context)
-- Get status code.
if attached Result.status_line as l_status_line then
if l_status_line.starts_with ("HTTP/") then
i := l_status_line.index_of (' ', 1)
if i > 0 then
i := i + 1
end
else
i := 1
end
-- Get status code token.
if i > 0 then
j := l_status_line.index_of (' ', i)
if j > i then
s := l_status_line.substring (i, j - 1)
if s.is_integer then
Result.set_status (s.to_integer)
end
end
end
end
if l_location /= Void then
-- TODO: add redirection support.
-- See if it could be similar to libcurl implementation
-- otherwise, maybe update the class HTTP_CLIENT_RESPONSE.
end
else
Result.set_error_message ("Could not connect")
end
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="test_http_client" uuid="920E5C50-41E1-4DAC-8D48-D9C860E49228">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-14-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-14-0 http://www.eiffel.com/developers/xml/configuration-1-14-0.xsd" name="test_http_client" uuid="920E5C50-41E1-4DAC-8D48-D9C860E49228">
<target name="test_http_client">
<root class="TEST" feature="make"/>
<file_rule>

View File

@@ -15,7 +15,7 @@ inherit
feature -- Test routines
test_http_client
test_libcurl_http_client
-- New test routine
local
sess: LIBCURL_HTTP_CLIENT_SESSION
@@ -42,6 +42,53 @@ feature -- Test routines
assert ("Not found", False)
end
end
test_socket_http_client
-- New test routine
local
sess: NET_HTTP_CLIENT_SESSION
h: STRING_8
do
create sess.make ("http://www.google.com")
if attached sess.get ("/search?q=eiffel", Void) as res then
assert ("Get returned without error", not res.error_occurred)
create h.make_empty
if attached res.headers as hds then
across
hds as c
loop
h.append (c.item.name + ": " + c.item.value + "%R%N")
end
end
if attached res.body as l_body then
assert ("body not empty", not l_body.is_empty)
else
assert ("missing body", False)
end
assert ("same headers", h.same_string (res.raw_header))
else
assert ("Not found", False)
end
end
test_socket_http_client_requestbin
local
sess: NET_HTTP_CLIENT_SESSION
h: STRING_8
do
--| Add your code here
create sess.make("http://requestb.in")
create h.make_empty
if attached sess.get ("/1a0q2h61", Void).headers as hds then
across
hds as c
loop
h.append (c.item.name + ": " + c.item.value + "%R%N")
end
end
print (h)
end
test_headers
local