2016-08-19 20:55:26 -07:00
|
|
|
import efl_net_http_types;
|
|
|
|
|
|
|
|
enum Efl.Net.Dialer.Http.Primary_Mode {
|
2016-10-25 04:03:46 -07:00
|
|
|
[[Primary HTTP mode]]
|
|
|
|
auto, [[HTTP auto mode]]
|
|
|
|
download, [[HTTP download mode]]
|
|
|
|
upload, [[HTTP upload mode]]
|
2016-08-19 20:55:26 -07:00
|
|
|
}
|
|
|
|
|
2016-09-09 10:53:11 -07:00
|
|
|
class Efl.Net.Dialer.Http (Efl.Loop_User, Efl.Net.Dialer, Efl.Io.Sizer) {
|
2016-08-19 20:55:26 -07:00
|
|
|
[[HTTP Dialer (Client).
|
|
|
|
|
|
|
|
The effective URL in use, if @.allow_redirects is $true will be
|
|
|
|
available as @Efl.Net.Socket.address_remote. The
|
|
|
|
@Efl.Net.Socket.address_local is an IP:PORT pair.
|
|
|
|
|
|
|
|
The dialer can do bi-directional information exchange. It can
|
|
|
|
also do a PUT and upload a file, or GET and download one. Anoter
|
|
|
|
case is to do a POST with some form values, including a file,
|
|
|
|
and retrieve its headers and response body. To make usage more
|
|
|
|
streamlined, choose your primary interest with @.primary_mode
|
|
|
|
then get some properties such as @Efl.Io.Sizer.size to report or
|
|
|
|
use what matters to your use case.
|
|
|
|
|
|
|
|
If @.allow_redirects is $true, multiple "connected" and
|
|
|
|
"resolved" signals will be dispatched, one for each
|
|
|
|
connection. Then @.response_status and @.response_headers_get
|
|
|
|
will keep changing. Using @.response_headers_all_get one can see
|
|
|
|
the whole history of headers and connections.
|
|
|
|
|
|
|
|
To enable debugging use EINA_LOG_LEVELS=ecore_con:4 environment
|
|
|
|
variable.
|
|
|
|
|
2016-09-16 18:19:37 -07:00
|
|
|
If the proxy is NULL (default), then the system proxy will be
|
|
|
|
used. On UNIX that's the environment variable $http_proxy (or
|
|
|
|
'$all_proxy') is used if the given address doesn't match
|
|
|
|
$no_proxy patterns. To disable proxy use an empty string. If
|
|
|
|
provided proxy must be one of the protocols:
|
|
|
|
|
|
|
|
- http://username:password\@proxyserver:port
|
|
|
|
- http://username\@proxyserver:port
|
|
|
|
- http://proxyserver:port
|
|
|
|
- http://proxyserver (default port 1080)
|
|
|
|
- socks5://username:password\@proxyserver:port (SOCKSv5)
|
|
|
|
- socks5h://username\@proxyserver:port (let socks server to resolve domain)
|
|
|
|
- socks5://proxyserver:port
|
|
|
|
- socks5://proxyserver (default port 1080)
|
|
|
|
- socks4a://proxyserver:port (SOCKSv4 and let socks server to resolve domain)
|
|
|
|
- socks4://proxyserver:port (SOCKSv4)
|
|
|
|
|
2016-08-19 20:55:26 -07:00
|
|
|
@since 1.19
|
|
|
|
]]
|
|
|
|
methods {
|
|
|
|
@property method {
|
|
|
|
[[The HTTP method to use.
|
|
|
|
|
|
|
|
A string representing the HTTP method to use, such as
|
|
|
|
GET, POST, HEAD, PUT, DELETE...
|
|
|
|
|
|
|
|
This should be set before dialing.
|
|
|
|
]]
|
|
|
|
get { }
|
|
|
|
set { }
|
|
|
|
values {
|
|
|
|
method: string;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@property primary_mode {
|
|
|
|
[[Is this request primarily a download or upload?
|
|
|
|
|
|
|
|
This property will change the behavior of @Efl.Io.Sizer:
|
|
|
|
|
|
|
|
- if @Efl.Net.Dialer.Http.Primary_Mode.auto, then
|
|
|
|
@Efl.Net.Dialer.Http.Primary_Mode.download or
|
|
|
|
@Efl.Net.Dialer.Http.Primary_Mode.upload will be
|
|
|
|
choosen based on the @.method: if "PUT", then it's
|
|
|
|
upload, otherwise it's download.
|
|
|
|
|
|
|
|
- if @Efl.Net.Dialer.Http.Primary_Mode.upload, applying
|
|
|
|
a new size with @Efl.Io.Sizer.resize or
|
|
|
|
@Efl.Io.Sizer.size.set will specify the
|
|
|
|
"Content-Length" to upload. If no size is previously
|
|
|
|
set, then the upload will happen in
|
|
|
|
"Transfer-encoding: chunked".
|
|
|
|
|
|
|
|
- if @Efl.Net.Dialer.Http.Primary_Mode.download, then
|
|
|
|
@Efl.Io.Sizer.size.get will report the
|
|
|
|
"Content-Length" provided by the server, if any.
|
|
|
|
|
|
|
|
If is worth to mention that one can provide and
|
|
|
|
retrieve these values using @.request_headers_get (to
|
|
|
|
send) and @.response_headers_get (what was received),
|
|
|
|
as well as using the specific properties
|
|
|
|
@.request_content_length (upload) and
|
|
|
|
@.response_content_length (download).
|
|
|
|
]]
|
|
|
|
get {
|
|
|
|
[[The effective primary mode.
|
|
|
|
|
|
|
|
This will return one of
|
|
|
|
@Efl.Net.Dialer.Http.Primary_Mode.download or
|
|
|
|
@Efl.Net.Dialer.Http.Primary_Mode.upload. If "auto"
|
|
|
|
was set (the default), then it will pick the best
|
|
|
|
based on the @.method in use.
|
|
|
|
]]
|
|
|
|
}
|
|
|
|
set { }
|
|
|
|
values {
|
|
|
|
primary_mode: Efl.Net.Dialer.Http.Primary_Mode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@property user_agent {
|
|
|
|
[[The User-Agent to specify.
|
|
|
|
|
|
|
|
This should be set before dialing.
|
|
|
|
]]
|
|
|
|
get { }
|
|
|
|
set { }
|
|
|
|
values {
|
|
|
|
user_agent: string;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@property http_version {
|
|
|
|
[[The HTTP version to use.
|
|
|
|
|
|
|
|
This should be set before dialing.
|
|
|
|
|
|
|
|
Once connected, it will change to the actual connection
|
|
|
|
HTTP version, so check after "connected" event.
|
|
|
|
]]
|
|
|
|
get { }
|
|
|
|
set { }
|
|
|
|
values {
|
|
|
|
http_version: Efl.Net.Http.Version;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@property authentication {
|
|
|
|
[[HTTP authentication to use.
|
|
|
|
|
|
|
|
This should be set before dialing.
|
|
|
|
]]
|
|
|
|
get { }
|
|
|
|
set { }
|
|
|
|
values {
|
|
|
|
username: string;
|
|
|
|
password: string;
|
|
|
|
method: Efl.Net.Http.Authentication_Method @optional; [[authentication method to use, defaults to @Efl.Net.Http.Authentication_Method.basic]]
|
|
|
|
restricted: bool @optional; [[restrict method]]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@property allow_redirects {
|
|
|
|
[[Allow HTTP redirects to be followed.
|
|
|
|
|
|
|
|
This should be set before dialing.
|
|
|
|
]]
|
|
|
|
get { }
|
|
|
|
set { }
|
|
|
|
values {
|
|
|
|
allow_redirects: bool;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
request_header_add {
|
|
|
|
[[Add a request header 'key: value'.
|
|
|
|
|
|
|
|
See @.request_headers_clear
|
|
|
|
|
|
|
|
This should be called before dialing.
|
|
|
|
]]
|
|
|
|
params {
|
|
|
|
@in key: string;
|
|
|
|
@in value: string;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
request_headers_clear {
|
|
|
|
[[Clear all request headers.
|
|
|
|
|
|
|
|
See @.request_header_add
|
|
|
|
|
|
|
|
This should be called before dialing.
|
|
|
|
]]
|
|
|
|
}
|
|
|
|
|
|
|
|
request_headers_get {
|
|
|
|
[[Return an iterator to the key-value pairs for request headers]]
|
|
|
|
return: free(own(iterator<Efl.Net.Http.Header>), eina_iterator_free) @warn_unused;
|
|
|
|
}
|
|
|
|
|
|
|
|
@property request_content_length {
|
|
|
|
[["Content-Length:" Header used for uploading/sending.
|
|
|
|
|
|
|
|
To unset use -1
|
|
|
|
]]
|
|
|
|
get { }
|
|
|
|
set { }
|
|
|
|
values {
|
|
|
|
length: int64;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@property response_content_length {
|
|
|
|
[["Content-Length:" Header used for downloading/receiving.
|
|
|
|
|
|
|
|
If unset is -1.
|
|
|
|
]]
|
|
|
|
get { }
|
|
|
|
set @protected { }
|
|
|
|
values {
|
|
|
|
length: int64;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@property response_content_type {
|
|
|
|
[["Content-Type:" Header used for downloading/receiving]]
|
|
|
|
get { }
|
|
|
|
set @protected { }
|
|
|
|
values {
|
|
|
|
content_type: string;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@property response_status {
|
|
|
|
[[The HTTP response status of this request.
|
|
|
|
|
|
|
|
It will be 0 if not connected, otherwise will be what is
|
|
|
|
returned by the server, such as.
|
|
|
|
|
|
|
|
See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
|
|
|
|
|
|
|
|
This will be usable after "connected" event is dispatched.
|
|
|
|
]]
|
|
|
|
get { }
|
|
|
|
values {
|
|
|
|
status_code: Efl.Net.Http.Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
response_headers_get {
|
|
|
|
[[Return an iterator to the key-value pairs for the last response headers.
|
|
|
|
|
|
|
|
Since multiple requests can happen if @.allow_redirects
|
|
|
|
is true, then all headers will be accumulated. This
|
|
|
|
method returns only the headers for the last request.
|
|
|
|
|
|
|
|
To know all the headers, check @.response_headers_all_get.
|
|
|
|
|
|
|
|
This will be usable after "headers,done" event is dispatched.
|
|
|
|
]]
|
|
|
|
return: free(own(iterator<Efl.Net.Http.Header>), eina_iterator_free) @warn_unused;
|
|
|
|
}
|
|
|
|
|
|
|
|
response_headers_all_get {
|
|
|
|
[[Return an iterator to the key-value pairs for all response headers.
|
|
|
|
|
|
|
|
Since multiple requests can happen if @.allow_redirects
|
|
|
|
is true, then all headers will be accumulated. To know
|
|
|
|
when new request is started, check for headers with keys
|
|
|
|
being NULL, the value will be the "HTTP/VERSION RESPONSE"
|
|
|
|
string received from the host, such as:
|
|
|
|
|
|
|
|
- key=NULL, value="HTTP/1.1 302 Found"
|
|
|
|
- key="Location", value="http://someredirect.com"
|
|
|
|
- key=NULL, value="HTTP/1.1 200 Ok"
|
|
|
|
- key="Content-Type", value="text/html"
|
|
|
|
|
|
|
|
Which mean the original request had a redirect to
|
|
|
|
http://someredirect.com.
|
|
|
|
|
|
|
|
To receive an iterator to just the last request, use
|
|
|
|
@.response_headers_get
|
|
|
|
|
|
|
|
This will be usable after "headers,done" event is dispatched.
|
|
|
|
]]
|
|
|
|
return: free(own(iterator<Efl.Net.Http.Header>), eina_iterator_free) @warn_unused;
|
|
|
|
}
|
|
|
|
|
|
|
|
response_headers_clear {
|
|
|
|
[[Save some memory by disposing the received headers]]
|
|
|
|
}
|
|
|
|
|
|
|
|
@property progress_download {
|
|
|
|
[[How many bytes were downloaded and how much was expected.]]
|
|
|
|
get { }
|
|
|
|
values {
|
|
|
|
downloaded: uint64 @optional;
|
|
|
|
total: uint64 @optional; [[0 if unknown]]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@property progress_upload {
|
|
|
|
[[How many bytes were uploaded and how much was expected.]]
|
|
|
|
get { }
|
|
|
|
values {
|
|
|
|
uploaded: uint64 @optional;
|
|
|
|
total: uint64 @optional; [[0 if unknown]]
|
|
|
|
}
|
|
|
|
}
|
2016-08-22 15:24:13 -07:00
|
|
|
|
|
|
|
@property cookie_jar {
|
|
|
|
[[This property sets the filename where to read and write cookies.
|
|
|
|
|
|
|
|
By setting a file to load and persist cookies to, the
|
|
|
|
internal cookie system will be activated, automatically
|
|
|
|
handling HTTP headers such as 'Set-cookie:' and sending
|
|
|
|
the appropriate cookies for a server.
|
|
|
|
|
|
|
|
If a new, empty session is to be used, start with an
|
|
|
|
empty or non-existent file such as created with
|
|
|
|
mkstemp() or tmpfile(). An alternative is to use an
|
|
|
|
empty string ("") to keep it in memory.
|
|
|
|
|
|
|
|
If it is desired to start from a pre-existent cookie jar
|
|
|
|
but do not want to modify that, first copy that file and
|
|
|
|
then pass the new, temporary file.
|
|
|
|
|
|
|
|
Likewise, if it's desired to fill some cookies to the
|
|
|
|
system, create a cookie jar and pass its path to this
|
|
|
|
property.
|
|
|
|
|
|
|
|
\@note that whenever this property is set, even if to the
|
|
|
|
same value, it will flush all cookies to the previously
|
|
|
|
set file, then erase all known cookies, then use the new
|
|
|
|
file (if any).
|
|
|
|
]]
|
|
|
|
get { }
|
|
|
|
set { }
|
|
|
|
values {
|
|
|
|
path: string;
|
|
|
|
}
|
|
|
|
}
|
2016-08-19 20:55:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
events {
|
|
|
|
headers,done; [[Notifies all headers were parsed and are available.]]
|
|
|
|
}
|
|
|
|
|
|
|
|
implements {
|
|
|
|
Efl.Object.constructor;
|
|
|
|
Efl.Object.destructor;
|
|
|
|
Efl.Net.Dialer.dial;
|
|
|
|
Efl.Net.Dialer.address_dial;
|
|
|
|
Efl.Net.Dialer.connected;
|
2016-08-22 14:51:38 -07:00
|
|
|
Efl.Net.Dialer.proxy;
|
2016-08-19 20:55:26 -07:00
|
|
|
Efl.Net.Dialer.timeout_dial;
|
|
|
|
Efl.Net.Socket.address_local;
|
|
|
|
Efl.Net.Socket.address_remote;
|
|
|
|
Efl.Io.Reader.read;
|
|
|
|
Efl.Io.Reader.can_read.get;
|
|
|
|
Efl.Io.Reader.can_read.set;
|
|
|
|
Efl.Io.Reader.eos.get;
|
|
|
|
Efl.Io.Reader.eos.set;
|
|
|
|
Efl.Io.Writer.write;
|
|
|
|
Efl.Io.Writer.can_write.get;
|
|
|
|
Efl.Io.Writer.can_write.set;
|
|
|
|
Efl.Io.Closer.close;
|
|
|
|
Efl.Io.Closer.closed.get;
|
2016-09-12 08:23:29 -07:00
|
|
|
Efl.Io.Closer.close_on_exec;
|
|
|
|
Efl.Io.Closer.close_on_destructor;
|
2016-08-19 20:55:26 -07:00
|
|
|
Efl.Io.Sizer.resize;
|
|
|
|
Efl.Io.Sizer.size.get;
|
|
|
|
}
|
|
|
|
}
|