Difference between revisions of "WxHTTP"

From WxWiki
Jump to navigation Jump to search
(changed reading char-by-char to wxStringOutputStream)
m (Text replacement - "<source>" to "<syntaxhighlight lang="cpp">")
 
(17 intermediate revisions by 5 users not shown)
Line 1: Line 1:
== wxHTTP Functions Missing from Docs ==
+
== Functions Missing from Docs ==
Functions found in src/common/http.cpp that you need to know about but that arn't documented in <wxref class="wxHTTP" method=""></wxref>.
+
 
----
+
'''Note:''' You might have trouble using cookies - see [http://trac.wxwidgets.org/ticket/10655 this] for a work around.
=== wxHTTP::Abort ===
+
 
==== bool Abort(void) ====
+
Functions found in src/common/http.cpp that you need to know about but that aren't documented in wxHTTP.
 +
 
 +
=== bool Abort(void) ===
 +
 
 
Aborts an active transfer by closing the connection.
 
Aborts an active transfer by closing the connection.
----
 
  
=== wxHTTP::Connect ===
+
=== bool Connect([[wxSockAddress]]& addr, bool WXUNUSED(wait)) ===
==== bool Connect([[wxSockAddress]]& addr, bool WXUNUSED(wait)) ====
+
=== bool Connect(const [[wxString]]& host, unsigned short port) ===
==== bool Connect(const [[wxString]]& host, unsigned short port) ====
+
 
 
These do not make an actual connection to a server but simple tell wxHTTP about the server you want to request pages from.
 
These do not make an actual connection to a server but simple tell wxHTTP about the server you want to request pages from.
----
+
 
=== wxHTTP::SetPostBuffer ===
+
=== void SetPostBuffer(const [[wxString]]& post_buf) ===
==== void SetPostBuffer(const [[wxString]]& post_buf) ====
+
 
 
Set the data to be posted to the server.
 
Set the data to be posted to the server.
----
+
 
=== wxHTTP::GetContentType ===
+
=== [[wxString]] GetContentType() ===
==== [[wxString]] GetContentType() ====
+
 
 
Get the "Content-Type" header returned by the server.
 
Get the "Content-Type" header returned by the server.
----
+
 
=== wxHTTP::SetProxyMode ===
+
=== void SetProxyMode(bool on) ===
==== void SetProxyMode(bool on) ====
+
 
 
Set whether or not to use a proxy.
 
Set whether or not to use a proxy.
----
+
 
=== wxHTTP::ClearHeaders ===
+
=== void ClearHeaders() ===
==== void ClearHeaders() ====
+
 
 
Removes all headers.
 
Removes all headers.
----
+
 
=== wxHTTP::GetInputStream ===
+
=== [[wxInputStream]] *GetInputStream(const [[wxString]]& path) ===
==== [[wxInputStream]] *GetInputStream(const [[wxString]]& path) ====
+
 
 
Get a page from the server specified by the last call to Connect(...). Path is path to a resource on the server not a full URL.
 
Get a page from the server specified by the last call to Connect(...). Path is path to a resource on the server not a full URL.
 +
 
Note: You must call one of the Connect functions at least once before using this function or the result will be NULL.
 
Note: You must call one of the Connect functions at least once before using this function or the result will be NULL.
----
+
 
 
== Basic Usage ==
 
== Basic Usage ==
after:
+
 
 +
<syntaxhighlight lang="cpp" title="wxHTTP Example Code">
 
#include <wx/sstream.h>
 
#include <wx/sstream.h>
 
#include <wx/protocol/http.h>
 
#include <wx/protocol/http.h>
  
<source title="wxHTTP Example Code">
 
 
wxHTTP get;
 
wxHTTP get;
 
get.SetHeader(_T("Content-type"), _T("text/html; charset=utf-8"));
 
get.SetHeader(_T("Content-type"), _T("text/html; charset=utf-8"));
get.Connect(_T("www.google.com")); // only the server, no pages here yet
+
get.SetTimeout(10); // 10 seconds of timeout instead of 10 minutes ...
 +
 
 +
// this will wait until the user connects to the internet. It is important in case of dialup (or ADSL) connections
 +
while (!get.Connect(_T("www.google.com"))// only the server, no pages here yet ...
 +
    wxSleep(5);
  
 
wxApp::IsMainLoopRunning(); // should return true
 
wxApp::IsMainLoopRunning(); // should return true
Line 57: Line 64:
  
 
     wxMessageBox(res);
 
     wxMessageBox(res);
// wxLogVerbose( wxString(_T(" returned document length: ")) << res.Length() );
+
    // wxLogVerbose( wxString(_T(" returned document length: ")) << res.Length() );
 
}
 
}
 
else
 
else
Line 64: Line 71:
 
}
 
}
  
delete httpStream;
+
wxDELETE(httpStream);
 
get.Close();
 
get.Close();
</source>
+
</syntaxhighlight>
  
 
== Known issues ==
 
== Known issues ==
=== CPU used at 100% ===
+
 
Sometimes, when you try to use wxHTTP to get a file and the main loop is not running, your CPU usage comes to 100% and this overhead completely freeze your Windows (This issue doesn't appear under wxGTK). A small clue is in the wxApp documentation : <wxref class="wxApp" method="IsMainLoopRunning"></wxref> : ''"This can be useful to test whether the events can be dispatched. For example, if this function returns false, non-blocking sockets cannot be used because the events from them would never be processed."'' It looks like you can't use wxHTTP even in blocking mode until you are in main loop (at least on Windows platform).<br/>
+
=== 100% CPU Usage ===
 +
 
 +
Sometimes, when you try to use wxHTTP to get a file and the main loop is not running, your CPU usage comes to 100% and this overhead completely freeze your Windows (This issue doesn't appear under wxGTK). A small clue is in the wxApp documentation : [https://docs.wxwidgets.org/stable/classwx_app_console.html#abe34922edd0a98a63de3cc73e95fda35 wxAppConsole::IsMainLoopRunning] : ''"This can be useful to test whether the events can be dispatched. For example, if this function returns false, non-blocking sockets cannot be used because the events from them would never be processed."'' It looks like you can't use wxHTTP even in blocking mode until you are in main loop (at least on Windows platform).
 +
 
 +
 
 
So you should always test for being inside main loop before using wxHTTP (certainly other protocols too).
 
So you should always test for being inside main loop before using wxHTTP (certainly other protocols too).
 +
 +
<blockquote>
 +
I was able to use wxHTTP successfully from a wxThread on Windows XP (wxWidgets 2.8.4).  The important step was to create the wxHTTP object outside the thread and call Initailise() from outside the thread too.  I may have been fortunate as in this application the main thread was not very busy.
 +
</blockquote>
 +
 +
 +
One possible workaround for this issue:
 +
<syntaxhighlight lang="cpp">
 +
BEGIN_EVENT_TABLE(ClassName, wxFrame)
 +
        //[...]
 +
EVT_IDLE(ClassName::OnIdle)
 +
END_EVENT_TABLE()
 +
//[...]
 +
 +
void ClassName::Init()
 +
{
 +
        //[...]
 +
        // initialized in header file as bool firstIdle;
 +
firstIdle = true;
 +
}
 +
//[...]
 +
 +
void ClassName::OnIdle(wxIdleEvent &event)
 +
{
 +
if (firstIdle)
 +
{
 +
[...];
 +
                // if content was changed, show the window after that
 +
Show(true);
 +
 +
firstIdle = false;
 +
}
 +
 +
event.Skip();
 +
}
 +
</syntaxhighlight>

Latest revision as of 19:36, 19 October 2018

Functions Missing from Docs

Note: You might have trouble using cookies - see this for a work around.

Functions found in src/common/http.cpp that you need to know about but that aren't documented in wxHTTP.

bool Abort(void)

Aborts an active transfer by closing the connection.

bool Connect(wxSockAddress& addr, bool WXUNUSED(wait))

bool Connect(const wxString& host, unsigned short port)

These do not make an actual connection to a server but simple tell wxHTTP about the server you want to request pages from.

void SetPostBuffer(const wxString& post_buf)

Set the data to be posted to the server.

wxString GetContentType()

Get the "Content-Type" header returned by the server.

void SetProxyMode(bool on)

Set whether or not to use a proxy.

void ClearHeaders()

Removes all headers.

wxInputStream *GetInputStream(const wxString& path)

Get a page from the server specified by the last call to Connect(...). Path is path to a resource on the server not a full URL.

Note: You must call one of the Connect functions at least once before using this function or the result will be NULL.

Basic Usage

#include <wx/sstream.h>
#include <wx/protocol/http.h>

wxHTTP get;
get.SetHeader(_T("Content-type"), _T("text/html; charset=utf-8"));
get.SetTimeout(10); // 10 seconds of timeout instead of 10 minutes ...

// this will wait until the user connects to the internet. It is important in case of dialup (or ADSL) connections
while (!get.Connect(_T("www.google.com")))  // only the server, no pages here yet ...
    wxSleep(5);

wxApp::IsMainLoopRunning(); // should return true

// use _T("/") for index.html, index.php, default.asp, etc.
wxInputStream *httpStream = get.GetInputStream(_T("/intl/en/about.html"));

// wxLogVerbose( wxString(_T(" GetInputStream: ")) << get.GetResponse() << _T("-") << ((resStream)? _T("OK ") : _T("FAILURE ")) << get.GetError() );

if (get.GetError() == wxPROTO_NOERR)
{
    wxString res;
    wxStringOutputStream out_stream(&res);
    httpStream->Read(out_stream);

    wxMessageBox(res);
    // wxLogVerbose( wxString(_T(" returned document length: ")) << res.Length() );
}
else
{
    wxMessageBox(_T("Unable to connect!"));
}

wxDELETE(httpStream);
get.Close();

Known issues

100% CPU Usage

Sometimes, when you try to use wxHTTP to get a file and the main loop is not running, your CPU usage comes to 100% and this overhead completely freeze your Windows (This issue doesn't appear under wxGTK). A small clue is in the wxApp documentation : wxAppConsole::IsMainLoopRunning : "This can be useful to test whether the events can be dispatched. For example, if this function returns false, non-blocking sockets cannot be used because the events from them would never be processed." It looks like you can't use wxHTTP even in blocking mode until you are in main loop (at least on Windows platform).


So you should always test for being inside main loop before using wxHTTP (certainly other protocols too).

I was able to use wxHTTP successfully from a wxThread on Windows XP (wxWidgets 2.8.4). The important step was to create the wxHTTP object outside the thread and call Initailise() from outside the thread too. I may have been fortunate as in this application the main thread was not very busy.


One possible workaround for this issue:

BEGIN_EVENT_TABLE(ClassName, wxFrame)
        //[...]
	EVT_IDLE(ClassName::OnIdle)
END_EVENT_TABLE()
//[...]

void ClassName::Init()
{
        //[...]
        // initialized in header file as bool firstIdle;
	firstIdle = true;
}
//[...]

void ClassName::OnIdle(wxIdleEvent &event)
{
	if (firstIdle)
	{
		[...];
                // if content was changed, show the window after that
		Show(true);

		firstIdle = false;
	}

	event.Skip();
}