diff --git a/CHANGELOG.md b/CHANGELOG.md index ac78d18..5645508 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,3 @@ -## ArduinoHttpClient 0.4.0 - 2019.04.09 - -* Added URLEncoder helper - -## ArduinoHttpClient 0.3.2 - 2019.02.04 - -* Changed Flush return value resulting in compilation error. Thanks @forGGe - ## ArduinoHttpClient 0.3.1 - 2017.09.25 * Changed examples to support Arduino Create secret tabs diff --git a/README.md b/README.md index 1b95559..9058b28 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,18 @@ ArduinoHttpClient is a library to make it easier to interact with web servers fr Derived from [Adrian McEwen's HttpClient library](https://github.com/amcewen/HttpClient) +## Modified Version +This is a modified version to support the following: +- Only [WiFi101](https://github.com/arduino-libraries/WiFi101) +- SSL Support (`HttpClient http = HttpClient(WIFI, URL, PORT, true)`) + +Tested on Arduino MKR1000 only. Below is the original README. + ## Dependencies - Requires a networking hardware and a library that provides transport specific `Client` instance, such as: - - [WiFiNINA](https://github.com/arduino-libraries/WiFiNINA) - [WiFi101](https://github.com/arduino-libraries/WiFi101) - [Ethernet](https://github.com/arduino-libraries/Ethernet) - - [MKRGSM](https://github.com/arduino-libraries/MKRGSM) - - [MKRNB](https://github.com/arduino-libraries/MKRNB) - [WiFi](https://github.com/arduino-libraries/WiFi) - [GSM](https://github.com/arduino-libraries/GSM) diff --git a/examples/BasicAuthGet/BasicAuthGet.ino b/examples/BasicAuthGet/BasicAuthGet.ino index ca801b7..e793d47 100644 --- a/examples/BasicAuthGet/BasicAuthGet.ino +++ b/examples/BasicAuthGet/BasicAuthGet.ino @@ -2,12 +2,12 @@ GET client with HTTP basic authentication for ArduinoHttpClient library Connects to server once every five seconds, sends a GET request + + created 14 Feb 2016 by Tom Igoe modified 3 Jan 2017 to add HTTP basic authentication by Sandeep Mistry - modified 22 Jan 2019 - by Tom Igoe this example is in the public domain */ @@ -25,6 +25,8 @@ int port = 8080; WiFiClient wifi; HttpClient client = HttpClient(wifi, serverAddress, port); int status = WL_IDLE_STATUS; +String response; +int statusCode = 0; void setup() { Serial.begin(9600); @@ -54,8 +56,8 @@ void loop() { client.endRequest(); // read the status code and body of the response - int statusCode = client.responseStatusCode(); - String response = client.responseBody(); + statusCode = client.responseStatusCode(); + response = client.responseBody(); Serial.print("Status code: "); Serial.println(statusCode); @@ -64,3 +66,4 @@ void loop() { Serial.println("Wait five seconds"); delay(5000); } + diff --git a/examples/CustomHeader/CustomHeader.ino b/examples/CustomHeader/CustomHeader.ino index e2131eb..fa44aca 100644 --- a/examples/CustomHeader/CustomHeader.ino +++ b/examples/CustomHeader/CustomHeader.ino @@ -2,14 +2,18 @@ Custom request header example for the ArduinoHttpClient library. This example sends a GET and a POST request with a custom header every 5 seconds. + note: WiFi SSID and password are stored in config.h file. + If it is not present, add a new tab, call it "config.h" + and add the following variables: + char ssid[] = "ssid"; // your network SSID (name) + char pass[] = "password"; // your network password + based on SimpleGet example by Tom Igoe header modifications by Todd Treece - modified 22 Jan 2019 - by Tom Igoe this example is in the public domain -*/ - + */ + #include #include @@ -25,6 +29,8 @@ int port = 8080; WiFiClient wifi; HttpClient client = HttpClient(wifi, serverAddress, port); int status = WL_IDLE_STATUS; +String response; +int statusCode = 0; void setup() { Serial.begin(9600); @@ -47,6 +53,7 @@ void setup() { } void loop() { + Serial.println("making GET request"); client.beginRequest(); client.get("/"); @@ -54,8 +61,8 @@ void loop() { client.endRequest(); // read the status code and body of the response - int statusCode = client.responseStatusCode(); - String response = client.responseBody(); + statusCode = client.responseStatusCode(); + response = client.responseBody(); Serial.print("GET Status code: "); Serial.println(statusCode); @@ -74,8 +81,6 @@ void loop() { client.sendHeader("X-CUSTOM-HEADER", "custom_value"); client.endRequest(); client.write((const byte*)postData.c_str(), postData.length()); - // note: the above line can also be achieved with the simpler line below: - //client.print(postData); // read the status code and body of the response statusCode = client.responseStatusCode(); diff --git a/examples/DweetGet/DweetGet.ino b/examples/DweetGet/DweetGet.ino index d191285..51abd3f 100644 --- a/examples/DweetGet/DweetGet.ino +++ b/examples/DweetGet/DweetGet.ino @@ -9,8 +9,10 @@ For more on dweet.io, see https://dweet.io/play/ + + created 15 Feb 2016 - updated 22 Jan 2019 + updated 16 Feb 2016 by Tom Igoe this example is in the public domain @@ -31,6 +33,8 @@ String dweetName = "scandalous-cheese-hoarder"; // use your own thing name here WiFiClient wifi; HttpClient client = HttpClient(wifi, serverAddress, port); int status = WL_IDLE_STATUS; +int statusCode = 0; +String response; void setup() { Serial.begin(9600); @@ -62,8 +66,8 @@ void loop() { client.get(path); // read the status code and body of the response - int statusCode = client.responseStatusCode(); - String response = client.responseBody(); + statusCode = client.responseStatusCode(); + response = client.responseBody(); Serial.print("Status code: "); Serial.println(statusCode); Serial.print("Response: "); diff --git a/examples/DweetPost/DweetPost.ino b/examples/DweetPost/DweetPost.ino index f1da2b9..41c6f2f 100644 --- a/examples/DweetPost/DweetPost.ino +++ b/examples/DweetPost/DweetPost.ino @@ -5,8 +5,13 @@ Shows how to use Strings to assemble path and body + note: WiFi SSID and password are stored in config.h file. + If it is not present, add a new tab, call it "config.h" + and add the following variables: + char ssid[] = "ssid"; // your network SSID (name) + char pass[] = "password"; // your network password + created 15 Feb 2016 - modified 22 Jan 2019 by Tom Igoe this example is in the public domain @@ -26,6 +31,8 @@ int port = 80; WiFiClient wifi; HttpClient client = HttpClient(wifi, serverAddress, port); int status = WL_IDLE_STATUS; +int statusCode = 0; +String response; void setup() { Serial.begin(9600); @@ -52,6 +59,7 @@ void loop() { // assemble the path for the POST message: String dweetName = "scandalous-cheese-hoarder"; String path = "/dweet/for/" + dweetName; + String contentType = "application/json"; // assemble the body of the POST message: @@ -66,8 +74,8 @@ void loop() { client.post(path, contentType, postData); // read the status code and body of the response - int statusCode = client.responseStatusCode(); - String response = client.responseBody(); + statusCode = client.responseStatusCode(); + response = client.responseBody(); Serial.print("Status code: "); Serial.println(statusCode); diff --git a/examples/HueBlink/HueBlink.ino b/examples/HueBlink/HueBlink.ino index eab74fe..c18ae47 100644 --- a/examples/HueBlink/HueBlink.ino +++ b/examples/HueBlink/HueBlink.ino @@ -13,6 +13,8 @@ This example shows how to concatenate Strings to assemble the PUT request and the body of the request. + + modified 15 Feb 2016 by Tom Igoe (tigoe) to match new API */ @@ -95,4 +97,6 @@ void sendRequest(int light, String cmd, String value) { Serial.print("Server response: "); Serial.println(response); Serial.println(); -} \ No newline at end of file +} + + diff --git a/examples/PostWithHeaders/PostWithHeaders.ino b/examples/PostWithHeaders/PostWithHeaders.ino index c2b1f0a..835a26f 100644 --- a/examples/PostWithHeaders/PostWithHeaders.ino +++ b/examples/PostWithHeaders/PostWithHeaders.ino @@ -3,12 +3,12 @@ Connects to server once every five seconds, sends a POST request with custome headers and a request body + + created 14 Feb 2016 by Tom Igoe modified 18 Mar 2017 by Sandeep Mistry - modified 22 Jan 2019 - by Tom Igoe this example is in the public domain */ @@ -29,6 +29,8 @@ int port = 8080; WiFiClient wifi; HttpClient client = HttpClient(wifi, serverAddress, port); int status = WL_IDLE_STATUS; +String response; +int statusCode = 0; void setup() { Serial.begin(9600); @@ -64,8 +66,8 @@ void loop() { client.endRequest(); // read the status code and body of the response - int statusCode = client.responseStatusCode(); - String response = client.responseBody(); + statusCode = client.responseStatusCode(); + response = client.responseBody(); Serial.print("Status code: "); Serial.println(statusCode); diff --git a/examples/SimpleDelete/SimpleDelete.ino b/examples/SimpleDelete/SimpleDelete.ino index 120f8d4..374a145 100644 --- a/examples/SimpleDelete/SimpleDelete.ino +++ b/examples/SimpleDelete/SimpleDelete.ino @@ -3,8 +3,9 @@ Connects to server once every five seconds, sends a DELETE request and a request body + + created 14 Feb 2016 - modified 22 Jan 2019 by Tom Igoe this example is in the public domain @@ -26,6 +27,8 @@ int port = 8080; WiFiClient wifi; HttpClient client = HttpClient(wifi, serverAddress, port); int status = WL_IDLE_STATUS; +String response; +int statusCode = 0; void setup() { Serial.begin(9600); @@ -55,8 +58,8 @@ void loop() { client.del("/", contentType, delData); // read the status code and body of the response - int statusCode = client.responseStatusCode(); - String response = client.responseBody(); + statusCode = client.responseStatusCode(); + response = client.responseBody(); Serial.print("Status code: "); Serial.println(statusCode); diff --git a/examples/SimpleGet/SimpleGet.ino b/examples/SimpleGet/SimpleGet.ino index 90d1f68..75db9a7 100644 --- a/examples/SimpleGet/SimpleGet.ino +++ b/examples/SimpleGet/SimpleGet.ino @@ -2,8 +2,9 @@ Simple GET client for ArduinoHttpClient library Connects to server once every five seconds, sends a GET request + + created 14 Feb 2016 - modified 22 Jan 2019 by Tom Igoe this example is in the public domain @@ -18,12 +19,15 @@ char ssid[] = SECRET_SSID; char pass[] = SECRET_PASS; + char serverAddress[] = "192.168.0.3"; // server address int port = 8080; WiFiClient wifi; HttpClient client = HttpClient(wifi, serverAddress, port); int status = WL_IDLE_STATUS; +String response; +int statusCode = 0; void setup() { Serial.begin(9600); @@ -50,8 +54,8 @@ void loop() { client.get("/"); // read the status code and body of the response - int statusCode = client.responseStatusCode(); - String response = client.responseBody(); + statusCode = client.responseStatusCode(); + response = client.responseBody(); Serial.print("Status code: "); Serial.println(statusCode); diff --git a/examples/SimplePost/SimplePost.ino b/examples/SimplePost/SimplePost.ino index a4704e5..6cc3517 100644 --- a/examples/SimplePost/SimplePost.ino +++ b/examples/SimplePost/SimplePost.ino @@ -3,8 +3,9 @@ Connects to server once every five seconds, sends a POST request and a request body + + created 14 Feb 2016 - modified 22 Jan 2019 by Tom Igoe this example is in the public domain @@ -18,12 +19,15 @@ char ssid[] = SECRET_SSID; char pass[] = SECRET_PASS; + char serverAddress[] = "192.168.0.3"; // server address int port = 8080; WiFiClient wifi; HttpClient client = HttpClient(wifi, serverAddress, port); int status = WL_IDLE_STATUS; +String response; +int statusCode = 0; void setup() { Serial.begin(9600); @@ -53,8 +57,8 @@ void loop() { client.post("/", contentType, postData); // read the status code and body of the response - int statusCode = client.responseStatusCode(); - String response = client.responseBody(); + statusCode = client.responseStatusCode(); + response = client.responseBody(); Serial.print("Status code: "); Serial.println(statusCode); diff --git a/examples/SimplePut/SimplePut.ino b/examples/SimplePut/SimplePut.ino index 99af49f..1b06105 100644 --- a/examples/SimplePut/SimplePut.ino +++ b/examples/SimplePut/SimplePut.ino @@ -3,8 +3,9 @@ Connects to server once every five seconds, sends a PUT request and a request body + + created 14 Feb 2016 - modified 22 Jan 2019 by Tom Igoe this example is in the public domain @@ -18,12 +19,15 @@ char ssid[] = SECRET_SSID; char pass[] = SECRET_PASS; + char serverAddress[] = "192.168.0.3"; // server address int port = 8080; WiFiClient wifi; HttpClient client = HttpClient(wifi, serverAddress, port); int status = WL_IDLE_STATUS; +String response; +int statusCode = 0; void setup() { Serial.begin(9600); @@ -53,8 +57,8 @@ void loop() { client.put("/", contentType, putData); // read the status code and body of the response - int statusCode = client.responseStatusCode(); - String response = client.responseBody(); + statusCode = client.responseStatusCode(); + response = client.responseBody(); Serial.print("Status code: "); Serial.println(statusCode); diff --git a/examples/SimpleWebSocket/SimpleWebSocket.ino b/examples/SimpleWebSocket/SimpleWebSocket.ino index b20d74b..baac12f 100644 --- a/examples/SimpleWebSocket/SimpleWebSocket.ino +++ b/examples/SimpleWebSocket/SimpleWebSocket.ino @@ -3,10 +3,9 @@ Connects to the WebSocket server, and sends a hello message every 5 seconds + created 28 Jun 2016 by Sandeep Mistry - modified 22 Jan 2019 - by Tom Igoe this example is in the public domain */ @@ -78,3 +77,4 @@ void loop() { Serial.println("disconnected"); } + diff --git a/keywords.txt b/keywords.txt index 1b4bd2c..27cd516 100644 --- a/keywords.txt +++ b/keywords.txt @@ -9,7 +9,6 @@ ArduinoHttpClient KEYWORD1 HttpClient KEYWORD1 WebSocketClient KEYWORD1 -URLEncoder KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) @@ -48,8 +47,6 @@ isFinal KEYWORD2 readString KEYWORD2 ping KEYWORD2 -encode KEYWORD2 - ####################################### # Constants (LITERAL1) ####################################### diff --git a/library.properties b/library.properties index 632910e..2ac5bb5 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ArduinoHttpClient -version=0.4.0 +version=0.3.1 author=Arduino maintainer=Arduino sentence=[EXPERIMENTAL] Easily interact with web servers from Arduino, using HTTP and WebSocket's. diff --git a/src/ArduinoHttpClient.h b/src/ArduinoHttpClient.h index abb8494..578733f 100644 --- a/src/ArduinoHttpClient.h +++ b/src/ArduinoHttpClient.h @@ -7,6 +7,5 @@ #include "HttpClient.h" #include "WebSocketClient.h" -#include "URLEncoder.h" #endif diff --git a/src/HttpClient.cpp b/src/HttpClient.cpp index 7517eea..daa4d1f 100644 --- a/src/HttpClient.cpp +++ b/src/HttpClient.cpp @@ -10,21 +10,21 @@ const char* HttpClient::kUserAgent = "Arduino/2.2.0"; const char* HttpClient::kContentLengthPrefix = HTTP_HEADER_CONTENT_LENGTH ": "; const char* HttpClient::kTransferEncodingChunked = HTTP_HEADER_TRANSFER_ENCODING ": " HTTP_HEADER_VALUE_CHUNKED; -HttpClient::HttpClient(Client& aClient, const char* aServerName, uint16_t aServerPort) +HttpClient::HttpClient(WiFiClient& aClient, const char* aServerName, uint16_t aServerPort, bool aUseSSL) : iClient(&aClient), iServerName(aServerName), iServerAddress(), iServerPort(aServerPort), - iConnectionClose(true), iSendDefaultRequestHeaders(true) + iConnectionClose(true), iSendDefaultRequestHeaders(true), iUseSSL(aUseSSL) { resetState(); } -HttpClient::HttpClient(Client& aClient, const String& aServerName, uint16_t aServerPort) - : HttpClient(aClient, aServerName.c_str(), aServerPort) +HttpClient::HttpClient(WiFiClient& aClient, const String& aServerName, uint16_t aServerPort, bool aUseSSL) + : HttpClient(aClient, aServerName.c_str(), aServerPort, aUseSSL) { } -HttpClient::HttpClient(Client& aClient, const IPAddress& aServerAddress, uint16_t aServerPort) +HttpClient::HttpClient(WiFiClient& aClient, const IPAddress& aServerAddress, uint16_t aServerPort, bool aUseSSL) : iClient(&aClient), iServerName(NULL), iServerAddress(aServerAddress), iServerPort(aServerPort), - iConnectionClose(true), iSendDefaultRequestHeaders(true) + iConnectionClose(true), iSendDefaultRequestHeaders(true), iUseSSL(aUseSSL) { resetState(); } @@ -84,7 +84,7 @@ int HttpClient::startRequest(const char* aURLPath, const char* aHttpMethod, { if (iServerName) { - if (!iClient->connect(iServerName, iServerPort) > 0) + if (!connectTo(iServerName, iServerPort) > 0) { #ifdef LOGGING Serial.println("Connection failed"); @@ -94,7 +94,7 @@ int HttpClient::startRequest(const char* aURLPath, const char* aHttpMethod, } else { - if (!iClient->connect(iServerAddress, iServerPort) > 0) + if (!connectTo(iServerAddress, iServerPort) > 0) { #ifdef LOGGING Serial.println("Connection failed"); @@ -143,6 +143,25 @@ int HttpClient::startRequest(const char* aURLPath, const char* aHttpMethod, return ret; } +int HttpClient::connectTo(IPAddress ip, uint16_t port) { + if (iUseSSL) { + return iClient->connectSSL(ip, port); + } + else { + return iClient->connect(ip, port); + } +} + + +int HttpClient::connectTo(const char* host, uint16_t port) { + if (iUseSSL) { + return iClient->connectSSL(host, port); + } + else { + return iClient->connect(host, port); + } +} + int HttpClient::sendInitialHeaders(const char* aURLPath, const char* aHttpMethod) { #ifdef LOGGING diff --git a/src/HttpClient.h b/src/HttpClient.h index 38fd799..3c9c81f 100644 --- a/src/HttpClient.h +++ b/src/HttpClient.h @@ -7,7 +7,8 @@ #include #include -#include "Client.h" +#include +// #include "Client.h" static const int HTTP_SUCCESS =0; // The end of the headers has been reached. This consumes the '\n' @@ -38,19 +39,20 @@ static const int HTTP_ERROR_INVALID_RESPONSE =-4; #define HTTP_HEADER_USER_AGENT "User-Agent" #define HTTP_HEADER_VALUE_CHUNKED "chunked" -class HttpClient : public Client +class HttpClient : public WiFiClient { public: static const int kNoContentLengthHeader =-1; static const int kHttpPort =80; + static const bool kUseSSL =false; static const char* kUserAgent; // FIXME Write longer API request, using port and user-agent, example // FIXME Update tempToPachube example to calculate Content-Length correctly - HttpClient(Client& aClient, const char* aServerName, uint16_t aServerPort = kHttpPort); - HttpClient(Client& aClient, const String& aServerName, uint16_t aServerPort = kHttpPort); - HttpClient(Client& aClient, const IPAddress& aServerAddress, uint16_t aServerPort = kHttpPort); + HttpClient(WiFiClient& aClient, const char* aServerName, uint16_t aServerPort = kHttpPort, bool aUseSSL = kUseSSL); + HttpClient(WiFiClient& aClient, const String& aServerName, uint16_t aServerPort = kHttpPort, bool aUseSSL = kUseSSL); + HttpClient(WiFiClient& aClient, const IPAddress& aServerAddress, uint16_t aServerPort = kHttpPort, bool aUseSSL = kUseSSL); /** Start a more complex request. Use this when you need to send additional headers in the request, @@ -166,9 +168,9 @@ class HttpClient : public Client const byte aBody[] = NULL); /** Send an additional header line. This can only be called in between the - calls to beginRequest and endRequest. + calls to startRequest and finishRequest. @param aHeader Header line to send, in its entirety (but without the - trailing CRLF. E.g. "Authorization: Basic YQDDCAIGES" + trailing CRLF. E.g. "Authorization: Basic YQDDCAIGES" */ void sendHeader(const char* aHeader); @@ -211,6 +213,10 @@ class HttpClient : public Client void sendBasicAuth(const String& aUser, const String& aPassword) { sendBasicAuth(aUser.c_str(), aPassword.c_str()); } + /* Connects to server with SSL support */ + int connectTo(IPAddress ip, uint16_t port); + int connectTo(const char* host, uint16_t port); + /** Get the HTTP status code contained in the response. For example, 200 for successful request, 404 for file not found, etc. */ @@ -307,7 +313,7 @@ class HttpClient : public Client virtual int read(); virtual int read(uint8_t *buf, size_t size); virtual int peek() { return iClient->peek(); }; - virtual void flush() { iClient->flush(); }; + virtual void flush() { return iClient->flush(); }; // Inherited from Client virtual int connect(IPAddress ip, uint16_t port) { return iClient->connect(ip, port); }; @@ -361,7 +367,7 @@ class HttpClient : public Client eReadingBodyChunk } tHttpState; // Client we're using - Client* iClient; + WiFiClient* iClient; // Server we are connecting to const char* iServerName; IPAddress iServerAddress; @@ -383,6 +389,8 @@ class HttpClient : public Client bool iIsChunked; // Stores the value of the current chunk length, if present int iChunkLength; + // Uses connectSSL or not + bool iUseSSL; uint32_t iHttpResponseTimeout; bool iConnectionClose; bool iSendDefaultRequestHeaders; diff --git a/src/WebSocketClient.cpp b/src/WebSocketClient.cpp index ab41b0a..269905f 100644 --- a/src/WebSocketClient.cpp +++ b/src/WebSocketClient.cpp @@ -5,21 +5,21 @@ #include "WebSocketClient.h" -WebSocketClient::WebSocketClient(Client& aClient, const char* aServerName, uint16_t aServerPort) +WebSocketClient::WebSocketClient(WiFiClient& aClient, const char* aServerName, uint16_t aServerPort) : HttpClient(aClient, aServerName, aServerPort), iTxStarted(false), iRxSize(0) { } -WebSocketClient::WebSocketClient(Client& aClient, const String& aServerName, uint16_t aServerPort) +WebSocketClient::WebSocketClient(WiFiClient& aClient, const String& aServerName, uint16_t aServerPort) : HttpClient(aClient, aServerName, aServerPort), iTxStarted(false), iRxSize(0) { } -WebSocketClient::WebSocketClient(Client& aClient, const IPAddress& aServerAddress, uint16_t aServerPort) +WebSocketClient::WebSocketClient(WiFiClient& aClient, const IPAddress& aServerAddress, uint16_t aServerPort) : HttpClient(aClient, aServerAddress, aServerPort), iTxStarted(false), iRxSize(0) diff --git a/src/WebSocketClient.h b/src/WebSocketClient.h index 4b009e6..0d18dad 100644 --- a/src/WebSocketClient.h +++ b/src/WebSocketClient.h @@ -18,9 +18,9 @@ static const int TYPE_PONG = 0xa; class WebSocketClient : public HttpClient { public: - WebSocketClient(Client& aClient, const char* aServerName, uint16_t aServerPort = HttpClient::kHttpPort); - WebSocketClient(Client& aClient, const String& aServerName, uint16_t aServerPort = HttpClient::kHttpPort); - WebSocketClient(Client& aClient, const IPAddress& aServerAddress, uint16_t aServerPort = HttpClient::kHttpPort); + WebSocketClient(WiFiClient& aClient, const char* aServerName, uint16_t aServerPort = HttpClient::kHttpPort); + WebSocketClient(WiFiClient& aClient, const String& aServerName, uint16_t aServerPort = HttpClient::kHttpPort); + WebSocketClient(WiFiClient& aClient, const IPAddress& aServerAddress, uint16_t aServerPort = HttpClient::kHttpPort); /** Start the Web Socket connection to the specified path @param aURLPath Path to use in request (optional, "/" is used by default)