A simple web service over HTTP library. Calls a HTTP server via GET, and returns the response wrapped in a XML parser. All calls are synchronous. Needs the NetServicesMin, DNSResolver, TcpLineStream and spxml libraries. The code for URL handling has been copied directly from the original NetServices library (Thanks to Donatien!).

Files at this revision

API Documentation at this revision

Comitter:
hlipka
Date:
Sat Jan 29 23:29:41 2011 +0000
Parent:
0:5e8527b638e1
Child:
2:687430e7f63a
Commit message:
Changed to use the TcpLineStream library. This makes the code much simpler.

Changed in this revision

webservice.cpp Show annotated file Show diff for this revision Revisions of this file
webservice.h Show annotated file Show diff for this revision Revisions of this file
--- a/webservice.cpp	Tue Jan 11 23:00:09 2011 +0000
+++ b/webservice.cpp	Sat Jan 29 23:29:41 2011 +0000
@@ -1,200 +1,61 @@
-#include "Timer.h"
-
-#include "webservice.h"
-
-#include "spxmlnode.hpp"
-#include "spxmlhandle.hpp"
-
-#include "dnsresolve.h"
-
-void WebService::onTCPSocketEvent(TCPSocketEvent e) {
-//    printf("New TCPSocketEvent: %d\n",e);
-    switch (e) {
-        case TCPSOCKET_CONNECTED:
-            _connected = true;
-            _connecting=false;
-            break;
-
-        case TCPSOCKET_READABLE:
-            break;
-        case TCPSOCKET_WRITEABLE:
-            break;
-
-        case TCPSOCKET_CONTIMEOUT:
-        case TCPSOCKET_CONRST:
-        case TCPSOCKET_CONABRT:
-        case TCPSOCKET_ERROR:
-        case TCPSOCKET_DISCONNECTED: {
-            // don't close the real socket here, as this may skip the already received data
-            _connected = false;
-            _connecting=false;
-        }
-        break;
-    }
-}
-
-WebService::WebService(const char* url):_url(url) {
-    _closed=false;
-    _readpos=0;
-    _readlen=0;
-    _readpos=0;
-    _readlen=0;
-
-    _socket.setOnEvent(this,&WebService::onTCPSocketEvent);
-}
-
-SP_XmlDomParser* WebService::callService() {
-    Url url;
-    url.fromString(_url);
-
-    string request=string("GET ").append(_url).append(" HTTP/1.0\r\n\r\n");
-
-    IpAddr addr;
-    if (!url.getHostIp(&addr)) {
-        DNSResolver dr;
-        addr=dr.resolveName(url.getHost().c_str());
-    }
-//    printf("host ip=%i.%i.%i.%i\n",addr[0],addr[1],addr[2],addr[3]);
-
-    int port=0==url.getPort()?80:url.getPort();
-
-    Host host(addr, port);
-
-    TCPSocketErr bindErr = _socket.connect(host);
-
-    if (bindErr != 0) {
-        printf("connection error %i\n", bindErr);
-        return false;
-    }
-
-    // wait for connection established
-    _connecting=true;
-    mbed::Timer tmr;
-    tmr.start();
-
-    while (_connecting) {
-        Net::poll();
-        wait(0.1);
-        if (tmr.read()>10) {
-            printf("reached timeout\n");
-            break;
-        }
-    }
-
-    if (!_connected) {
-        printf("error - could not connect (timeout)\n");
-        return NULL;
-    }
-//    printf("send request[%s]\n",request.c_str());
-    _socket.send(request.c_str(),request.length());
-    Net::poll();
-
-    if (!_connected)
-        return NULL;
-
-    string firstLine=readResponseLine();
-    // todo: parse for HTTP response
-    // response must be for HTTP/1.0, and be 200
-    if (0!=firstLine.compare("HTTP/1.0 200 OK"))
-    {
-        printf("call not sucessfull, response=%s\n",firstLine.c_str());
-        return NULL;
-    }    
-    // skip headers    
-    while (true) {
-        string line=readResponseLine();
-//        printf("header=[%s]\n",line.c_str());
-        if (0==line.length())
-            break;
-    }
-    SP_XmlDomParser *parser=new SP_XmlDomParser();
-    while (true) {
-        string line=readResponseLine();
-//        printf("content=[%s]\n",line.c_str());
-        parser->append(line.c_str(),line.length());
-        if (0==line.length())
-            break;
-    }
-
-    return parser;
-}
-
-void WebService::close() {
-    if (_closed)
-        return;
-
-    while (_connected) {
-        Net::poll();
-        // read remaining data
-        int err=_socket.recv(_readbuf,BUFSIZE-1);
-        if (err<=0)
-            break;
-    }
-
-    while (true) {
-        Net::poll();
-        // read remaining data
-        int err=_socket.recv(_readbuf,BUFSIZE-1);
-        if (err<=0)
-            break;
-    }
-
-    _socket.resetOnEvent();
-    _socket.close();
-
-    _closed=true;
-}
-
-
-
-string WebService::readResponseLine() {
-    string r;
-    bool got_r=false;
-    
-    int emptyCount=0;
-    while (true) {
-        Net::poll();
-        if (_readlen>_readpos) {
-            while (_readbuf[_readpos]!=0 && _readpos<_readlen) {
-                char c=_readbuf[_readpos++];
-                if (!got_r) {
-                    if (c=='\r') {
-                        got_r=true;
-                    } else {
-                        r.push_back(c);
-                    }
-                } else {
-                    if (c=='\n') {
-                        return r;
-                    } else {
-                        r.push_back('\r'); // push missed \r also, so push it to string
-                        r.push_back(c);
-                        got_r=false;
-                    }
-                }
-            }
-        } else {
-            int err=_socket.recv(_readbuf,BUFSIZE-1);
-            if (err < 0) {
-                printf("error while receiving data: %i!\n",err);
-                break;
-            } else if (err>0) {
-                emptyCount=0;
-                _readbuf[err]=0;
-                _readlen=err;
-                _readpos=0;
-//                printf("r=%s\n",_readbuf);
-            }
-            else
-            {
-                // when we don't receive any data, and are not connected
-                // we stop because there isn't anything left
-                if (emptyCount++>2)
-                    if (!_connected)
-                        break;
-            }
-        }
-        wait(0.1);
-    }
-    return r;
-}
\ No newline at end of file
+#include "Timer.h"
+
+#include "webservice.h"
+
+#include "spxmlnode.hpp"
+#include "spxmlhandle.hpp"
+
+WebService::WebService(const char* urlStr) {
+    Url *url=new Url();
+    url->fromString(urlStr);
+    
+//    printf("host name from URL=%s\n",url->getHost().c_str());
+
+    _stream=new TCPLineStream(url->getHost().c_str(),0==url->getPort()?80:url->getPort(),"\r\n");
+    delete url;
+
+    _request=string("GET ").append(urlStr).append(" HTTP/1.0\r\n");
+//    printf("request=[%s]\n",_request.c_str());
+}
+
+SP_XmlDomParser* WebService::callService() {
+    if (!_stream->open())
+        return NULL;
+
+//    printf("send request[%s]\n",request.c_str());
+    _stream->sendLine(_request);
+
+    string firstLine=_stream->readLine();
+    // todo: parse for HTTP response
+    // response must be for HTTP/1.0, and be 200
+    if (0!=firstLine.compare("HTTP/1.0 200 OK")) {
+        printf("call not sucessfull, response=%s\n",firstLine.c_str());
+        return NULL;
+    }
+    // skip headers
+    while (true) {
+        string line=_stream->readLine();
+//        printf("header=[%s]\n",line.c_str());
+        if (0==line.length())
+            break;
+    }
+    SP_XmlDomParser *parser=new SP_XmlDomParser();
+    while (true) {
+        string line=_stream->readLine(1500);
+//        printf("content=[%s]\n",line.c_str());
+        parser->append(line.c_str(),line.length());
+        if (0==line.length())
+            break;
+    }
+    _stream->close();
+    return parser;
+}
+
+void WebService::close() {
+    if (NULL!=_stream) {
+        _stream->close();
+        delete _stream;
+        _stream=NULL;
+    }
+}
+
--- a/webservice.h	Tue Jan 11 23:00:09 2011 +0000
+++ b/webservice.h	Sat Jan 29 23:29:41 2011 +0000
@@ -1,58 +1,48 @@
-#ifndef __WEBSERVICE_H__
-#define __WEBSERVICE_H__
-
-#include "spdomparser.hpp"
-
-#include "TCPSocket.h"
-
-#include "url.h"
-
-#define BUFSIZE 256
-
-/**
-A simple web service over HTTP library. Calls a HTTP server via GET, and returns the response wrapped in a XML parser. All calls are synchronous.
-Needs the NetServicesMin and DNSResolver library
-The code for URL handling has been copied directly from the original NetServices library (Thanks to Donatien!).
-
-*/
-class WebService
-{
-    public:
-        /**
-            create the web service instance.
-            @params url the URL to call via GET
-        */
-        WebService(const char* url);
-        /**
-            Execute the web service call. Note that the caller is responsible for freeing the return parser instance.
-            @return the XML parser, or NULL if an error occured
-        */
-        SP_XmlDomParser *callService();
-        /**
-            close all resources
-        */
-        ~WebService(){close();};
-        /**
-            close all resources
-        */
-        void close();
-        
-    private:
-        void onTCPSocketEvent(TCPSocketEvent e);
-        string readResponseLine();
-        
-        const char* _url;
-        bool _connecting;
-        bool _connected;
-        bool _closed;
-        TCPSocket _socket;
-
-        char _readbuf[BUFSIZE];
-        int _readpos;
-        int _readlen;
-        
-};
-
-
-
+#ifndef __WEBSERVICE_H__
+#define __WEBSERVICE_H__
+
+#include "spdomparser.hpp"
+
+#include "url.h"
+
+#include "tcplinestream.h"
+
+/**
+A simple web service over HTTP library. Calls a HTTP server via GET, and returns the response wrapped in a XML parser. All calls are synchronous.
+Needs the NetServicesMin and DNSResolver library
+The code for URL handling has been copied directly from the original NetServices library (Thanks to Donatien!).
+
+*/
+class WebService
+{
+    public:
+        /**
+            create the web service instance.
+            @params urlStr the URL to call via GET
+        */
+        WebService(const char* urlStr);
+        /**
+            Execute the web service call. Note that the caller is responsible for freeing the return parser instance.
+            @return the XML parser, or NULL if an error occured
+        */
+        SP_XmlDomParser *callService();
+        /**
+            close all resources
+        */
+        ~WebService(){close();};
+        /**
+            close all resources
+        */
+        void close();
+        
+    private:
+        void init();
+        
+        string _request;
+        
+        TCPLineStream *_stream;
+};
+
+
+
 #endif
\ No newline at end of file