PrevNextUpHome BREW C++ Class Library & GUI Framework & XML Middleware : SophiaFramework 4.1

16.2. HTTP Connection

16.2.1. HTTP Connection Class

SFXHTTPConnection is the class that deals with the HTTP/HTTPS protocols, and data can be sent or received through the SFXHTTPConnection using the stream as described in the following procedure.

  1. Create the HTTP/HTTPS connection(instance of SFXHTTPConnection class).
  2. Open the HTTP/HTTPS connection using the SFXHTTPConnection::Open function.
  3. set the HTTP request method(default: GET method) using the SFXHTTPConnection::SetMethod function. And set data to the HTTP request body through the output stream obtained by the SFXHTTPConnection::GetStreamWriter function. ( Set the HTTP request header using the SFXHTTPConnection::SetRequestHeader function, if necessary.)
  4. In case of the HTTPS connection, set the trust mode(default: SSL_TRUST_MODE_FAIL) using the SFXHTTPConnection::SetTrustMode function.
  5. Connect to the Web server using the SFXHTTPConnection::Connect function, in which set the URL to be connected to and register the callback function that will receive the notification of connecting to the Web server.
  6. The callback function above will be called after notified of connecting to the Web server. * The execution result(error code) of connecting to the Web server will be passed to the callback function through the 1st argument. If the error code is "SFERR_NO_ERROR", connecting to the Web server is succeeded and the HTTP response is obtained.
  7. After checking the value of HTTP status code using the SFXHTTPConnection::GetResultCode function, read the HTTP response body through the input stream obtained by the SFXHTTPConnection::GetStreamReader function. * The HTTP response header can be gotten using the SFXHTTPConnection::GetResponseHeader function.
  8. Repeat the above steps from 2. to 7. until no other data needs to be sent or received.
  9. Finally, close HTTP/HTTPS connection using the SFXHTTPConnection::Close function.
[Caution] About MIF File Setting

Never forget to turn on the Web Access or Network option in the MIF file setting of privilege level.

16.2.2. Receiving Text Data Using the GET Method

Example 16.5. Recieve text data using the GET method

// SFXHTTPConnection instance is defined as class member variable for the callback function
class MyClass {
private:
    SFXHTTPConnection _http;
    SFXAnsiStringStreamReader _reader;
    SFXAnsiString _receivedString;
public:
    Void Start(Void);
    Void SaveToFile(SFXPathConstRef path, SFXAnsiStringConstRef string);
    CALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    CALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // HTTP/HTTPS connection using GET method
    if ((error = _http.Open()) == SFERR_NO_ERROR) {

        // start to connect
#if 1
        // when HTTP connection
        // connection establishment will be notified to OnConnect function
        if ((error = _http.Connect("http://www.example.com/",
                         CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#else
        // when HTTPS connection
        // set verification mode if necessary
        // connection establishment will be notified to OnConnect function
        _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
        if ((error = _http.Connect("https://www.example.com/",
                         CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#endif
            TRACE("> connecting...");
        }
    }

    if (error != SFERR_NO_ERROR) {
        // if error occurs
        _http.Close();
    }
    return;
}

// callback function notified of connection establishment
CALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE("> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // check response code
        TRACE("> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // get stream for receiving data
            if ((error = _http.GetStreamReader(1024, &_reader))
                == SFERR_NO_ERROR) {

                // receive data using stream
                // completion of receiving data will be notified to OnFetch function
                if ((error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch)))
                    == SFERR_NO_ERROR) {
                    TRACE("> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }

    if (error != SFERR_NO_ERROR) {
        // if error occurs
       _http.Close();
    }
    return;
}

// callback function notified of completion of receiving data
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    TRACE("> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // receive data from stream
        if ((error = _reader.ReadSFXAnsiString(&string)) == SFERR_NO_ERROR) {

            // combine fragmented data
            if ((error = _receivedString.Add(string)) == SFERR_NO_ERROR) {

                // check remaining data
                if (_reader.Ends()) {

                    // since all data have been received, display them
                    TRACE("--------");
                    TRACE("%s", _receivedString.GetCString()); // *
                    TRACE("--------");

                    // explicitly release resource
                    _reader.Release();
                    _http.Close();
                }
                else {

                    // receive next data
                    // completion of receiving data will be notified to OnFetch function
                    error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch));
                }
            }
        }
    }

    if (error != SFERR_NO_ERROR) {
        // if error occurs
        _reader.Release();
        _http.Close();
    }
    return;
}

To save the data in the file, call the following function at the "*" position of above code.

Example 16.6. Save received data in the file

// save string in file (path : file path)
Void MyClass::SaveToFile(SFXPathConstRef path, SFXAnsiStringConstRef string)
{
    SFCError error;

    SFXFile file;                     // file to save data
    SFXAnsiStringStreamWriter writer; // output stream

    // open file in read/write mode
    if ((error = file.OpenReadWrite(path))
        == SFERR_NO_ERROR) {

        // get output stream
        if ((error = file.GetStreamWriter(string.GetLength(), &writer))
            == SFERR_NO_ERROR) {

            // write string
            writer.WriteSFXAnsiString(string);

            // write string into file actually
            // string will not be written if Flush function is not called explicitly
            error = writer.Flush();

            // release stream
            writer.Release();
        }

        // close file
        file.Close();
    }

    if (error != SFERR_NO_ERROR) {
        // error handling

    }
}
[Caution] SFXHTTPConnection Instance

If the SFXHTTPConnection instance is released before the callback function is called, program will not work correctly.

16.2.3. Receiving Text Data Using the Post Method

Example 16.7. Receive text data using the Post method

// SFXHTTPConnection instance is defined as class member variable for the callback function
class MyClass {
private:
    SFXHTTPConnection _http;
    SFXAnsiStringStreamReader _reader;
    SFXAnsiString _receivedString;
public:
    Void Start(Void);
    CALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    CALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFXAnsiStringStreamWriter writer;
    SFXAnsiString send;
    SFCError error(SFERR_NO_ERROR);

    unused(environment);

    // HTTP/HTTPS connection using POST method
    if ((error = _http.Open()) == SFERR_NO_ERROR) {

        // prepare data to send
        send = "abcdefghijklmnopqrstuvwxyz";

        // get stream for writing data
        if ((error = _http.GetStreamWriter(send.GetLength(), &writer))
            == SFERR_NO_ERROR) {

            // write data using stream
            if ((error = writer.WriteSFXAnsiString(send)) == SFERR_NO_ERROR) {

                // send data actually
                // data will not be sent if Flush function is not called explicitly
                if ((error = writer.Flush()) == SFERR_NO_ERROR) {

                    // set request method to POST
                    if ((error = _http.SetMethod("POST")) == SFERR_NO_ERROR) {

                        // start to connect
#if 1
                        // when HTTP connection
                        // connection establishment will be notified to OnConnect function
                        if ((error = _http.Connect("http://www.example.com",
                            CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#else
                        // when HTTPS connection
                        // set notification mode if necessary
                        // connection establishment will be notified to OnConnect function
                        _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
                        if ((error = _http.Connect("https://www.example.com",
                            CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#endif
                            TRACE("> connecting...");
                        }
                    }
                }
            }
        }
    }

    if (error != SFERR_NO_ERROR) {
        // if error occurs
       _http.Close();
    }
    return;
}

// callback function notified of connection establishment
CALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE("> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // examine response code
        TRACE("> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // get stream for receiving data
            if ((error = _http.GetStreamReader(1024, &_reader))
                == SFERR_NO_ERROR) {

                // receive data using stream
                // completion of receiving data will be notified to OnFetch function
                if ((error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch)))
                    == SFERR_NO_ERROR) {
                    TRACE("> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }

    if (error != SFERR_NO_ERROR) {
        // if error occurs
        _http.Close();
    }
    return;
}

// callback function notified of completion of receiving data
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    TRACE("> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // receive data from stream
        if ((error = _reader.ReadSFXAnsiString(&string)) == SFERR_NO_ERROR) {

            // combine fragmented data
            if ((error = _receivedString.Add(string)) == SFERR_NO_ERROR) {

                // check remaining data
                if (_reader.Ends()) {

                    // since all data have been received, display them
                    TRACE("--------");
                    TRACE("%s", _receivedString.GetCString());
                    TRACE("--------");

                    // explicitly release resource
                    _reader.Release();
                    _http.Close();
                }
                else {

                    // receive next data
                    // completion of receiving data will be notified to OnFetch function
                    error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch));
                }
            }
        }
    }
	
    if (error != SFERR_NO_ERROR) {
        // if error occurs
        _reader.Release();
        _http.Close();
    }
    return;
}

16.2.4. Receiving the Binary Data

Example 16.8. Receive the binary data

// SFXHTTPConnection instance is defined as class member variable for the callback function
class MyClass {
private:
    SFXHTTPConnection _http;
    SFXFile _file;
    SFXBinaryStreamReader _reader; // input stream for receiving data through HTTP communication
    SFXBinaryStreamWriter _writer; // output stream for writing data in file 
    SFXBuffer _receivedBuffer;     // variable for storing received data
    SFXBuffer _tempBuffer;         // variable for storing received data temporarily
    UInt32 _bufferSize;            // buffer size of output stream for writing data in file
public:
    Void Start(Void);
    CALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    CALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // set buffer size
    _bufferSize = 1024;

    // reserve buffer
    if ((error = _tempBuffer.SetSize(_bufferSize)) == SFERR_NO_ERROR) {

        // open file in read/write modeく
        if ((error = _file.OpenReadWrite(SFXPath("/example.dat")))
            == SFERR_NO_ERROR) {

            // get output stream
            if ((error = _file.GetStreamWriter(_bufferSize, &_writer))
                == SFERR_NO_ERROR) {

                // HTTP/HTTPS connection using GET method
                if ((error = _http.Open()) == SFERR_NO_ERROR) {
				
if 1
                    //when HTTP connection
                    // connection establishment will be notified to OnConnect function
                    if ((error = _http.Connect("http://www.example.com",
                                 CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#else
                    // when HTTPS connection
                    // set notification mode if necessary
                    // connection establishment will be notified to OnConnect function
                    _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
                    if ((error = _http.Connect("https://www.example.com",
                                 CALLBACK_FUNCTION(OnConnect))) == SFERR_NO_ERROR) {
#endif
                       TRACE("> connecting...");
                    }
                }

                if (error != SFERR_NO_ERROR) {
                    // if error occurs
                    _http.Close();
                    _writer.Release();
                }
            }
            if (error != SFERR_NO_ERROR) {
               // if error occurs
               _file.Close();
            }
        }
    }
    return;
}

// callback function notified of connection establishment
CALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE("> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // check response code
        TRACE("> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // get stream for receiving data
            if ((error = _http.GetStreamReader(_bufferSize, &_reader))
                == SFERR_NO_ERROR) {

                // receive data using stream
                // completion of receiving data will be notified to OnFetch function
                if ((error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch)))
                    == SFERR_NO_ERROR) {
                    TRACE("> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }

    if (error != SFERR_NO_ERROR) {
        // if error occurs
        _http.Close();
        _writer.Release();
        _file.Close();
    }
    return;
}

// callback function notified of completion of receiving data
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    TRACE("> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // set temp buffer size again
        _tempBuffer.SetSize(_reader.GetReadableSize());

        // receive data from stream
        if ((error = _reader.Read(&_tempBuffer)) == SFERR_NO_ERROR) {

            // write data onto file
            // ( in fact, it is writtem to stream buffer)
            if ((error = _writer.Write(_tempBuffer)) == SFERR_NO_ERROR) {

                // write data into file actually
                // data will not be written into file if Flush function is not called explicitly

                if ((error = _writer.Flush()) == SFERR_NO_ERROR) {

                    // combine fragmented data
                    if ((error = _receivedBuffer.Add(_tempBuffer))
                        == SFERR_NO_ERROR) {

                        // check remaining data
                        if (_reader.Ends()) {

                            // since all data have been received, display them
                            TRACE("--------");
                            TRACE("%s", _receivedBuffer.GetBuffer());
                            TRACE("--------");

                            // explicitly release resource
                            _reader.Release();
                            _http.Close();
                            _writer.Release();
                            _file.Close();
                        }
                        else {
                           // receive next data
                           // completion of receiving data will be notified to OnFetch function
                           error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch));
                        }
                    }
                }
            }
        }
    }
	
    if (error != SFERR_NO_ERROR) {
        // if error occurs
        _reader.Release();
        _http.Close();
        _writer.Release();
        _file.Close();
    }
    return;
}

Data is saved to the file at the same it is received. (support both text and binary data)

16.2.5. Uploading the File through the HTTP Communication

Upload the file to the HTTP server using the code below.

[Caution] Limitation on File Size

Big files (more than 100KB) cannot be uploaded by the code below.

Example 16.9. Upload the file through the HTTP communication

// SFXHTTPConnection instance is defined as class member variable for the callback function
class MyClass {
private:
    SFXHTTPConnection _http;
    SFXAnsiStringStreamReader _reader;
    SFXAnsiString _receivedString;
public:
    Void Start(Void);
    CALLBACK_DECLARE_SFXHTTPCONNECTION(OnConnect)
    CALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};

Void MyClass::Start(Void)
{
    SFXFile file;
    SFXBinaryStreamReader reader;
    SFXBinaryStreamWriter writer;
    SFXBuffer buffer;
    SFCError error(SFERR_NO_ERROR);

    // open SFXHTTPConnection
    if ((error = _http.Open()) == SFERR_NO_ERROR) {

        // open file in read only mode
        if ((error = file.OpenReadOnly(SFXPath("/data.txt"))) == SFERR_NO_ERROR) {

            // get HTTP stream writer
            if ((error = _http.GetStreamWriter(1024, &writer))
                == SFERR_NO_ERROR) {

                // get file stream reader
                if ((error = file.GetStreamReader(1024, &reader))
                    == SFERR_NO_ERROR) {

                    // copy data from file to HTTP
                    while (error == SFERR_NO_ERROR) {
                        if ((error = reader.Fetch()) == SFERR_NO_ERROR) {
                        
                            // reserve buffer to read data from stream
                            if ((error = buffer.SetSize(
                                reader.GetReadableSize())) == SFERR_NO_ERROR) {

                                // read data from file stream 
                                if ((error = reader.Read(&buffer))
                                    == SFERR_NO_ERROR) {
                                    
                                    // write data into HTTP stream
                                    if ((error = writer.Write(buffer))
                                        == SFERR_NO_ERROR) {
                                        // send data actually
                                        // data will not be sent if Flush function is not called explicitly
                                        if ((error = writer.Flush())
                                            == SFERR_NO_ERROR) {
                                            
                                            // exit loop if reaching at end of stream
                                            if (reader.Ends()) {
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // if it is possible to copy normally
                    if (error == SFERR_NO_ERROR) {

                        // set request method to POST
                        if ((error = _http.SetMethod("POST")) == SFERR_NO_ERROR) {

                            // start to connect
#if 1
                            // when HTTP connection
                            // connection establishment will be notified to OnConnect function
                            if ((error = _http.Connect("http://www.example.com",
                                CALLBACK_FUNCTION(OnConnect)))
                                == SFERR_NO_ERROR) {
#else
                            // when HTTPS connection
                            // set notification mode if necessary
                            // connection establishment will be notified to OnConnect function
                            _http.SetTrustMode(SSL_TRUST_MODE_FAIL);
                            if ((error = _http.Connect("https://www.example.com",
                                CALLBACK_FUNCTION(OnConnect)))
                                == SFERR_NO_ERROR) {
#endif
                                TRACE("> connecting...");
                            }
                        }
                    }
                }
            }
        }
    }
	
    if (error != SFERR_NO_ERROR) {
        // if error occurs
        _http.Close();
    }
}

// callback function notified of connection establishment
CALLBACK_IMPLEMENT_SFXHTTPCONNECTION(MyClass, OnConnect, error)
{
    TRACE("> connected... : %d", error);

    if (error == SFERR_NO_ERROR) {

        // check response code
        TRACE("> result code : %d", _http.GetResultCode());

        if (_http.GetResultCode() == 200) {

            // get stream for receiving data
            if ((error = _http.GetStreamReader(1024, &_reader))
                == SFERR_NO_ERROR) {

               // receive data using stream
               // completion of receiving data will be notified to OnFetch function
               if ((error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch)))
                    == SFERR_NO_ERROR) {
                    TRACE("> fetching...");
                }
            }
        }
        else {
            error = SFERR_INVALID_STATE;
        }
    }
	
    if (error != SFERR_NO_ERROR) {
       // If error occurs
       _http.Close();
    }
    return;
}

// callback function notified of completion of receiving data
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
    SFXAnsiString string;

    TRACE("> fetched... : %d", error);

    if (error == SFERR_NO_ERROR) {
        // get received data from stream
        if ((error = _reader.ReadSFXAnsiString(&string)) == SFERR_NO_ERROR) {

            // combine fragmented data
            if ((error = _receivedString.Add(string)) == SFERR_NO_ERROR) {

                // check remaining data
                if (_reader.Ends()) {

                    // since all data have been received, display them
                    TRACE("--------");
                    TRACE("%s", _receivedString.GetCString());
                    TRACE("--------");

                    // release resource explicitly
                    _reader.Release();
                    _http.Close();
                }
                else {

                    // receive next data
                    // completion of receiving data will be notified to OnFetch function
                    error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch));
                }
            }
        }
    }
	
    if (error != SFERR_NO_ERROR) {
        // if error occurs
        _reader.Release();
        _http.Close();
    }
    return;
}