diff --git a/HttpClient.cpp b/HttpClient.cpp index 39a9ab7..5a11a45 100644 --- a/HttpClient.cpp +++ b/HttpClient.cpp @@ -7,16 +7,10 @@ #ifdef PROXY_ENABLED // currently disabled as introduces dependency on Dns.h in Ethernet #include #endif -#include -#include // Initialize constants -const char* HttpClient::kUserAgent = "Arduino/2.0"; -const char* HttpClient::kGet = "GET"; -const char* HttpClient::kPost = "POST"; -const char* HttpClient::kPut = "PUT"; -const char* HttpClient::kDelete = "DELETE"; -const char* HttpClient::kContentLengthPrefix = "Content-Length: "; +const char* HttpClient::kUserAgent = "Arduino/2.2.0"; +const char* HttpClient::kContentLengthPrefix = HTTP_HEADER_CONTENT_LENGTH ": "; #ifdef PROXY_ENABLED // currently disabled as introduces dependency on Dns.h in Ethernet HttpClient::HttpClient(Client& aClient, const char* aProxy, uint16_t aProxyPort) @@ -47,7 +41,7 @@ void HttpClient::resetState() iStatusCode = 0; iContentLength = 0; iBodyLengthConsumed = 0; - iContentLengthPtr = 0; + iContentLengthPtr = kContentLengthPrefix; iHttpResponseTimeout = kHttpResponseTimeout; } @@ -70,6 +64,7 @@ int HttpClient::startRequest(const char* aServerName, uint16_t aServerPort, cons return HTTP_ERROR_API; } +#ifdef PROXY_ENABLED if (iProxyPort) { if (!iClient->connect(iProxyAddress, iProxyPort) > 0) @@ -81,6 +76,7 @@ int HttpClient::startRequest(const char* aServerName, uint16_t aServerPort, cons } } else +#endif { if (!iClient->connect(aServerName, aServerPort) > 0) { @@ -111,6 +107,7 @@ int HttpClient::startRequest(const IPAddress& aServerAddress, const char* aServe return HTTP_ERROR_API; } +#ifdef PROXY_ENABLED if (iProxyPort) { if (!iClient->connect(iProxyAddress, iProxyPort) > 0) @@ -122,6 +119,7 @@ int HttpClient::startRequest(const IPAddress& aServerAddress, const char* aServe } } else +#endif { if (!iClient->connect(aServerAddress, aServerPort) > 0) { @@ -152,6 +150,7 @@ int HttpClient::sendInitialHeaders(const char* aServerName, IPAddress aServerIP, // Send the HTTP command, i.e. "GET /somepath/ HTTP/1.0" iClient->print(aHttpMethod); iClient->print(" "); +#ifdef PROXY_ENABLED if (iProxyPort) { // We're going through a proxy, send a full URL @@ -172,6 +171,7 @@ int HttpClient::sendInitialHeaders(const char* aServerName, IPAddress aServerIP, iClient->print(aPort); } } +#endif iClient->print(aURLPath); iClient->println(" HTTP/1.1"); // The host header, if required @@ -187,15 +187,17 @@ int HttpClient::sendInitialHeaders(const char* aServerName, IPAddress aServerIP, iClient->println(); } // And user-agent string - iClient->print("User-Agent: "); if (aUserAgent) { - iClient->println(aUserAgent); + sendHeader(HTTP_HEADER_USER_AGENT, aUserAgent); } else { - iClient->println(kUserAgent); + sendHeader(HTTP_HEADER_USER_AGENT, kUserAgent); } + // We don't support persistent connections, so tell the server to + // close this connection after we're done + sendHeader(HTTP_HEADER_CONNECTION, "close"); // Everything has gone well iState = eRequestStarted; diff --git a/HttpClient.h b/HttpClient.h index e7cb624..b4c3974 100644 --- a/HttpClient.h +++ b/HttpClient.h @@ -23,16 +23,23 @@ static const int HTTP_ERROR_TIMED_OUT =-3; // server? static const int HTTP_ERROR_INVALID_RESPONSE =-4; +// Define some of the common methods and headers here +// That lets other code reuse them without having to declare another copy +// of them, so saves code space and RAM +#define HTTP_METHOD_GET "GET" +#define HTTP_METHOD_POST "POST" +#define HTTP_METHOD_PUT "PUT" +#define HTTP_METHOD_DELETE "DELETE" +#define HTTP_HEADER_CONTENT_LENGTH "Content-Length" +#define HTTP_HEADER_CONNECTION "Connection" +#define HTTP_HEADER_USER_AGENT "User-Agent" + class HttpClient : public Client { public: static const int kNoContentLengthHeader =-1; static const int kHttpPort =80; static const char* kUserAgent; - static const char* kGet; - static const char* kPost; - static const char* kPut; - static const char* kDelete; // FIXME Write longer API request, using port and user-agent, example // FIXME Update tempToPachube example to calculate Content-Length correctly @@ -66,7 +73,7 @@ class HttpClient : public Client */ int get(const char* aServerName, uint16_t aServerPort, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerName, aServerPort, aURLPath, kGet, aUserAgent); } + { return startRequest(aServerName, aServerPort, aURLPath, HTTP_METHOD_GET, aUserAgent); } /** Connect to the server and start to send a GET request. @param aServerName Name of the server being connected to. If NULL, the @@ -77,7 +84,7 @@ class HttpClient : public Client @return 0 if successful, else error */ int get(const char* aServerName, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerName, kHttpPort, aURLPath, kGet, aUserAgent); } + { return startRequest(aServerName, kHttpPort, aURLPath, HTTP_METHOD_GET, aUserAgent); } /** Connect to the server and start to send a GET request. This version connects doesn't perform a DNS lookup and just connects to the given IP address. @@ -95,7 +102,7 @@ class HttpClient : public Client uint16_t aServerPort, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerAddress, aServerName, aServerPort, aURLPath, kGet, aUserAgent); } + { return startRequest(aServerAddress, aServerName, aServerPort, aURLPath, HTTP_METHOD_GET, aUserAgent); } /** Connect to the server and start to send a GET request. This version connects doesn't perform a DNS lookup and just connects to the given IP address. @@ -111,7 +118,7 @@ class HttpClient : public Client const char* aServerName, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerAddress, aServerName, kHttpPort, aURLPath, kGet, aUserAgent); } + { return startRequest(aServerAddress, aServerName, kHttpPort, aURLPath, HTTP_METHOD_GET, aUserAgent); } /** Connect to the server and start to send a POST request. @param aServerName Name of the server being connected to. If NULL, the @@ -126,7 +133,7 @@ class HttpClient : public Client uint16_t aServerPort, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerName, aServerPort, aURLPath, kPost, aUserAgent); } + { return startRequest(aServerName, aServerPort, aURLPath, HTTP_METHOD_POST, aUserAgent); } /** Connect to the server and start to send a POST request. @param aServerName Name of the server being connected to. If NULL, the @@ -139,7 +146,7 @@ class HttpClient : public Client int post(const char* aServerName, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerName, kHttpPort, aURLPath, kPost, aUserAgent); } + { return startRequest(aServerName, kHttpPort, aURLPath, HTTP_METHOD_POST, aUserAgent); } /** Connect to the server and start to send a POST request. This version connects doesn't perform a DNS lookup and just connects to the given IP address. @@ -157,7 +164,7 @@ class HttpClient : public Client uint16_t aServerPort, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerAddress, aServerName, aServerPort, aURLPath, kPost, aUserAgent); } + { return startRequest(aServerAddress, aServerName, aServerPort, aURLPath, HTTP_METHOD_POST, aUserAgent); } /** Connect to the server and start to send a POST request. This version connects doesn't perform a DNS lookup and just connects to the given IP address. @@ -173,7 +180,7 @@ class HttpClient : public Client const char* aServerName, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerAddress, aServerName, kHttpPort, aURLPath, kPost, aUserAgent); } + { return startRequest(aServerAddress, aServerName, kHttpPort, aURLPath, HTTP_METHOD_POST, aUserAgent); } /** Connect to the server and start to send a PUT request. @param aServerName Name of the server being connected to. If NULL, the @@ -188,7 +195,7 @@ class HttpClient : public Client uint16_t aServerPort, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerName, aServerPort, aURLPath, kPut, aUserAgent); } + { return startRequest(aServerName, aServerPort, aURLPath, HTTP_METHOD_PUT, aUserAgent); } /** Connect to the server and start to send a PUT request. @param aServerName Name of the server being connected to. If NULL, the @@ -201,7 +208,7 @@ class HttpClient : public Client int put(const char* aServerName, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerName, kHttpPort, aURLPath, kPut, aUserAgent); } + { return startRequest(aServerName, kHttpPort, aURLPath, HTTP_METHOD_PUT, aUserAgent); } /** Connect to the server and start to send a PUT request. This version connects doesn't perform a DNS lookup and just connects to the given IP address. @@ -219,7 +226,7 @@ class HttpClient : public Client uint16_t aServerPort, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerAddress, aServerName, aServerPort, aURLPath, kPut, aUserAgent); } + { return startRequest(aServerAddress, aServerName, aServerPort, aURLPath, HTTP_METHOD_PUT, aUserAgent); } /** Connect to the server and start to send a PUT request. This version connects doesn't perform a DNS lookup and just connects to the given IP address. @@ -235,7 +242,7 @@ class HttpClient : public Client const char* aServerName, const char* aURLPath, const char* aUserAgent =NULL) - { return startRequest(aServerAddress, aServerName, kHttpPort, aURLPath, kPut, aUserAgent); } + { return startRequest(aServerAddress, aServerName, kHttpPort, aURLPath, HTTP_METHOD_PUT, aUserAgent); } /** Connect to the server and start to send the request. @param aServerName Name of the server being connected to. diff --git a/README b/README deleted file mode 100644 index d223d80..0000000 --- a/README +++ /dev/null @@ -1,8 +0,0 @@ -HttpClient is a library to make it easier to interact with web servers from Arduino. - -Dependencies: -- Requires the new Ethernet library API (with DHCP and DNS) which is in Arduino 1.0. - -In normal usage, handles the outgoing request and Host header. The returned status code is -parsed for you, as is the Content-Length header (if present). - diff --git a/README.md b/README.md new file mode 100644 index 0000000..d55dfa4 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# HttpClient + +HttpClient is a library to make it easier to interact with web servers from Arduino. + +## Dependencies + +- Requires the new Ethernet library API (with DHCP and DNS) which is in Arduino 1.0 and later + +## Installation + +1. Download the latest version of the library from https://github.com/amcewen/HttpClient/releases and save the file somewhere +1. In the Arduino IDE, go to the Sketch -> Import Library -> Add Library... menu option +1. Find the zip file that you saved in the first step, and choose that +1. Check that it has been successfully added by opening the Sketch -> Import Library menu. You should now see HttpClient listed among the available libraries. + +## Usage + +In normal usage, handles the outgoing request and Host header. The returned status code is parsed for you, as is the Content-Length header (if present). + +Because it expects an object of type Client, you can use it with any of the networking classes that derive from that. Which means it will work with EthernetClient, WiFiClient and GSMClient. + +See the examples for more detail on how the library is used. + diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..577c5d9 --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +name=HttpClient +version=2.2.0 +author=Adrian McEwen +maintainer=Adrian McEwen +sentence=Library to easily make HTTP GET, POST and PUT requests to a web server. +paragraph=Works with any class derived from Client - so switching between Ethernet, WiFi and GSMClient requires minimal code changes. +category=Communication +url=http://github.com/amcewen/HttpClient +architectures=*