mirror of
https://github.com/arduino-libraries/ArduinoHttpClient.git
synced 2025-04-19 21:22:15 +03:00
commit
4ab54b0a1a
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.development
|
||||||
|
examples/node_test_server/node_modules/
|
10
ArduinoHttpClient.h
Normal file
10
ArduinoHttpClient.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Library to simplify HTTP fetching on Arduino
|
||||||
|
// (c) Copyright Arduino. 2016
|
||||||
|
// Released under Apache License, version 2.0
|
||||||
|
|
||||||
|
#ifndef ArduinoHttpClient_h
|
||||||
|
#define ArduinoHttpClient_h
|
||||||
|
|
||||||
|
#include "HttpClient.h"
|
||||||
|
|
||||||
|
#endif
|
303
HttpClient.cpp
303
HttpClient.cpp
@ -4,36 +4,29 @@
|
|||||||
|
|
||||||
#include "HttpClient.h"
|
#include "HttpClient.h"
|
||||||
#include "b64.h"
|
#include "b64.h"
|
||||||
#ifdef PROXY_ENABLED // currently disabled as introduces dependency on Dns.h in Ethernet
|
|
||||||
#include <Dns.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Initialize constants
|
// Initialize constants
|
||||||
const char* HttpClient::kUserAgent = "Arduino/2.2.0";
|
const char* HttpClient::kUserAgent = "Arduino/2.2.0";
|
||||||
const char* HttpClient::kContentLengthPrefix = HTTP_HEADER_CONTENT_LENGTH ": ";
|
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* aServerName, uint16_t aServerPort)
|
||||||
HttpClient::HttpClient(Client& aClient, const char* aProxy, uint16_t aProxyPort)
|
: iClient(&aClient), iServerName(aServerName), iServerAddress(), iServerPort(aServerPort),
|
||||||
: iClient(&aClient), iProxyPort(aProxyPort)
|
iConnectionClose(true), iSendDefaultRequestHeaders(true)
|
||||||
{
|
{
|
||||||
resetState();
|
resetState();
|
||||||
if (aProxy)
|
}
|
||||||
{
|
|
||||||
// Resolve the IP address for the proxy
|
HttpClient::HttpClient(Client& aClient, const String& aServerName, uint16_t aServerPort)
|
||||||
DNSClient dns;
|
: HttpClient(aClient, aServerName.c_str(), aServerPort)
|
||||||
dns.begin(Ethernet.dnsServerIP());
|
{
|
||||||
// Not ideal that we discard any errors here, but not a lot we can do in the ctor
|
}
|
||||||
// and we'll get a connect error later anyway
|
|
||||||
(void)dns.getHostByName(aProxy, iProxyAddress);
|
HttpClient::HttpClient(Client& aClient, const IPAddress& aServerAddress, uint16_t aServerPort)
|
||||||
}
|
: iClient(&aClient), iServerName(NULL), iServerAddress(aServerAddress), iServerPort(aServerPort),
|
||||||
}
|
iConnectionClose(true), iSendDefaultRequestHeaders(true)
|
||||||
#else
|
|
||||||
HttpClient::HttpClient(Client& aClient)
|
|
||||||
: iClient(&aClient), iProxyPort(0)
|
|
||||||
{
|
{
|
||||||
resetState();
|
resetState();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void HttpClient::resetState()
|
void HttpClient::resetState()
|
||||||
{
|
{
|
||||||
@ -51,44 +44,66 @@ void HttpClient::stop()
|
|||||||
resetState();
|
resetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpClient::connectionKeepAlive()
|
||||||
|
{
|
||||||
|
iConnectionClose = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpClient::noDefaultRequestHeaders()
|
||||||
|
{
|
||||||
|
iSendDefaultRequestHeaders = false;
|
||||||
|
}
|
||||||
|
|
||||||
void HttpClient::beginRequest()
|
void HttpClient::beginRequest()
|
||||||
{
|
{
|
||||||
iState = eRequestStarted;
|
iState = eRequestStarted;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HttpClient::startRequest(const char* aServerName, uint16_t aServerPort, const char* aURLPath, const char* aHttpMethod, const char* aUserAgent)
|
int HttpClient::startRequest(const char* aURLPath, const char* aHttpMethod)
|
||||||
{
|
{
|
||||||
tHttpState initialState = iState;
|
tHttpState initialState = iState;
|
||||||
|
|
||||||
|
if (!iConnectionClose)
|
||||||
|
{
|
||||||
|
flushClientRx();
|
||||||
|
|
||||||
|
resetState();
|
||||||
|
}
|
||||||
|
|
||||||
if ((eIdle != iState) && (eRequestStarted != iState))
|
if ((eIdle != iState) && (eRequestStarted != iState))
|
||||||
{
|
{
|
||||||
return HTTP_ERROR_API;
|
return HTTP_ERROR_API;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PROXY_ENABLED
|
if (iConnectionClose || !iClient->connected())
|
||||||
if (iProxyPort)
|
|
||||||
{
|
{
|
||||||
if (!iClient->connect(iProxyAddress, iProxyPort) > 0)
|
if (iServerName) {
|
||||||
{
|
if (!iClient->connect(iServerName, iServerPort) > 0)
|
||||||
|
{
|
||||||
#ifdef LOGGING
|
#ifdef LOGGING
|
||||||
Serial.println("Proxy connection failed");
|
Serial.println("Connection failed");
|
||||||
#endif
|
#endif
|
||||||
return HTTP_ERROR_CONNECTION_FAILED;
|
return HTTP_ERROR_CONNECTION_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!iClient->connect(iServerAddress, iServerPort) > 0)
|
||||||
|
{
|
||||||
|
#ifdef LOGGING
|
||||||
|
Serial.println("Connection failed");
|
||||||
|
#endif
|
||||||
|
return HTTP_ERROR_CONNECTION_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
if (!iClient->connect(aServerName, aServerPort) > 0)
|
|
||||||
{
|
|
||||||
#ifdef LOGGING
|
#ifdef LOGGING
|
||||||
Serial.println("Connection failed");
|
Serial.println("Connection already open");
|
||||||
#endif
|
#endif
|
||||||
return HTTP_ERROR_CONNECTION_FAILED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we're connected, send the first part of the request
|
// Now we're connected, send the first part of the request
|
||||||
int ret = sendInitialHeaders(aServerName, IPAddress(0,0,0,0), aServerPort, aURLPath, aHttpMethod, aUserAgent);
|
int ret = sendInitialHeaders(aURLPath, aHttpMethod);
|
||||||
if ((initialState == eIdle) && (HTTP_SUCCESS == ret))
|
if ((initialState == eIdle) && (HTTP_SUCCESS == ret))
|
||||||
{
|
{
|
||||||
// This was a simple version of the API, so terminate the headers now
|
// This was a simple version of the API, so terminate the headers now
|
||||||
@ -99,50 +114,7 @@ int HttpClient::startRequest(const char* aServerName, uint16_t aServerPort, cons
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int HttpClient::startRequest(const IPAddress& aServerAddress, const char* aServerName, uint16_t aServerPort, const char* aURLPath, const char* aHttpMethod, const char* aUserAgent)
|
int HttpClient::sendInitialHeaders(const char* aURLPath, const char* aHttpMethod)
|
||||||
{
|
|
||||||
tHttpState initialState = iState;
|
|
||||||
if ((eIdle != iState) && (eRequestStarted != iState))
|
|
||||||
{
|
|
||||||
return HTTP_ERROR_API;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef PROXY_ENABLED
|
|
||||||
if (iProxyPort)
|
|
||||||
{
|
|
||||||
if (!iClient->connect(iProxyAddress, iProxyPort) > 0)
|
|
||||||
{
|
|
||||||
#ifdef LOGGING
|
|
||||||
Serial.println("Proxy connection failed");
|
|
||||||
#endif
|
|
||||||
return HTTP_ERROR_CONNECTION_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (!iClient->connect(aServerAddress, aServerPort) > 0)
|
|
||||||
{
|
|
||||||
#ifdef LOGGING
|
|
||||||
Serial.println("Connection failed");
|
|
||||||
#endif
|
|
||||||
return HTTP_ERROR_CONNECTION_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we're connected, send the first part of the request
|
|
||||||
int ret = sendInitialHeaders(aServerName, aServerAddress, aServerPort, aURLPath, aHttpMethod, aUserAgent);
|
|
||||||
if ((initialState == eIdle) && (HTTP_SUCCESS == ret))
|
|
||||||
{
|
|
||||||
// This was a simple version of the API, so terminate the headers now
|
|
||||||
finishHeaders();
|
|
||||||
}
|
|
||||||
// else we'll call it in endRequest or in the first call to print, etc.
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int HttpClient::sendInitialHeaders(const char* aServerName, IPAddress aServerIP, uint16_t aPort, const char* aURLPath, const char* aHttpMethod, const char* aUserAgent)
|
|
||||||
{
|
{
|
||||||
#ifdef LOGGING
|
#ifdef LOGGING
|
||||||
Serial.println("Connected");
|
Serial.println("Connected");
|
||||||
@ -150,54 +122,33 @@ int HttpClient::sendInitialHeaders(const char* aServerName, IPAddress aServerIP,
|
|||||||
// Send the HTTP command, i.e. "GET /somepath/ HTTP/1.0"
|
// Send the HTTP command, i.e. "GET /somepath/ HTTP/1.0"
|
||||||
iClient->print(aHttpMethod);
|
iClient->print(aHttpMethod);
|
||||||
iClient->print(" ");
|
iClient->print(" ");
|
||||||
#ifdef PROXY_ENABLED
|
|
||||||
if (iProxyPort)
|
|
||||||
{
|
|
||||||
// We're going through a proxy, send a full URL
|
|
||||||
iClient->print("http://");
|
|
||||||
if (aServerName)
|
|
||||||
{
|
|
||||||
// We've got a server name, so use it
|
|
||||||
iClient->print(aServerName);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We'll have to use the IP address
|
|
||||||
iClient->print(aServerIP);
|
|
||||||
}
|
|
||||||
if (aPort != kHttpPort)
|
|
||||||
{
|
|
||||||
iClient->print(":");
|
|
||||||
iClient->print(aPort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
iClient->print(aURLPath);
|
iClient->print(aURLPath);
|
||||||
iClient->println(" HTTP/1.1");
|
iClient->println(" HTTP/1.1");
|
||||||
// The host header, if required
|
if (iSendDefaultRequestHeaders)
|
||||||
if (aServerName)
|
|
||||||
{
|
{
|
||||||
iClient->print("Host: ");
|
// The host header, if required
|
||||||
iClient->print(aServerName);
|
if (iServerName)
|
||||||
if (aPort != kHttpPort)
|
|
||||||
{
|
{
|
||||||
iClient->print(":");
|
iClient->print("Host: ");
|
||||||
iClient->print(aPort);
|
iClient->print(iServerName);
|
||||||
|
if (iServerPort != kHttpPort)
|
||||||
|
{
|
||||||
|
iClient->print(":");
|
||||||
|
iClient->print(iServerPort);
|
||||||
|
}
|
||||||
|
iClient->println();
|
||||||
}
|
}
|
||||||
iClient->println();
|
// And user-agent string
|
||||||
}
|
|
||||||
// And user-agent string
|
|
||||||
if (aUserAgent)
|
|
||||||
{
|
|
||||||
sendHeader(HTTP_HEADER_USER_AGENT, aUserAgent);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sendHeader(HTTP_HEADER_USER_AGENT, 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
|
if (iConnectionClose)
|
||||||
sendHeader(HTTP_HEADER_CONNECTION, "close");
|
{
|
||||||
|
// Tell the server to
|
||||||
|
// close this connection after we're done
|
||||||
|
sendHeader(HTTP_HEADER_CONNECTION, "close");
|
||||||
|
}
|
||||||
|
|
||||||
// Everything has gone well
|
// Everything has gone well
|
||||||
iState = eRequestStarted;
|
iState = eRequestStarted;
|
||||||
@ -278,6 +229,17 @@ void HttpClient::finishHeaders()
|
|||||||
iState = eRequestSent;
|
iState = eRequestSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpClient::flushClientRx()
|
||||||
|
{
|
||||||
|
if (iClient->connected())
|
||||||
|
{
|
||||||
|
while (iClient->available())
|
||||||
|
{
|
||||||
|
iClient->read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HttpClient::endRequest()
|
void HttpClient::endRequest()
|
||||||
{
|
{
|
||||||
if (iState < eRequestSent)
|
if (iState < eRequestSent)
|
||||||
@ -299,7 +261,7 @@ int HttpClient::responseStatusCode()
|
|||||||
// Where HTTP-Version is of the form:
|
// Where HTTP-Version is of the form:
|
||||||
// HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
|
// HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
|
||||||
|
|
||||||
char c = '\0';
|
int c = '\0';
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Make sure the status code is reset, and likewise the state. This
|
// Make sure the status code is reset, and likewise the state. This
|
||||||
@ -358,6 +320,9 @@ int HttpClient::responseStatusCode()
|
|||||||
case eStatusCodeRead:
|
case eStatusCodeRead:
|
||||||
// We're just waiting for the end of the line now
|
// We're just waiting for the end of the line now
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
// We read something, reset the timeout counter
|
// We read something, reset the timeout counter
|
||||||
timeoutStart = millis();
|
timeoutStart = millis();
|
||||||
@ -431,6 +396,17 @@ int HttpClient::skipResponseHeaders()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int HttpClient::contentLength()
|
||||||
|
{
|
||||||
|
// skip the response headers, if they haven't been read already
|
||||||
|
if (!endOfHeadersReached())
|
||||||
|
{
|
||||||
|
skipResponseHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
return iContentLength;
|
||||||
|
}
|
||||||
|
|
||||||
bool HttpClient::endOfBodyReached()
|
bool HttpClient::endOfBodyReached()
|
||||||
{
|
{
|
||||||
if (endOfHeadersReached() && (contentLength() != kNoContentLengthHeader))
|
if (endOfHeadersReached() && (contentLength() != kNoContentLengthHeader))
|
||||||
@ -443,30 +419,79 @@ bool HttpClient::endOfBodyReached()
|
|||||||
|
|
||||||
int HttpClient::read()
|
int HttpClient::read()
|
||||||
{
|
{
|
||||||
#if 0 // Fails on WiFi because multi-byte read seems to be broken
|
|
||||||
uint8_t b[1];
|
|
||||||
int ret = read(b, 1);
|
|
||||||
if (ret == 1)
|
|
||||||
{
|
|
||||||
return b[0];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
int ret = iClient->read();
|
int ret = iClient->read();
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
if (endOfHeadersReached() && iContentLength > 0)
|
if (endOfHeadersReached() && iContentLength > 0)
|
||||||
{
|
{
|
||||||
// We're outputting the body now and we've seen a Content-Length header
|
// We're outputting the body now and we've seen a Content-Length header
|
||||||
// So keep track of how many bytes are left
|
// So keep track of how many bytes are left
|
||||||
iBodyLengthConsumed++;
|
iBodyLengthConsumed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
bool HttpClient::headerAvailable()
|
||||||
|
{
|
||||||
|
// clear the currently store header line
|
||||||
|
iHeaderLine = "";
|
||||||
|
|
||||||
|
while (!endOfHeadersReached())
|
||||||
|
{
|
||||||
|
// read a byte from the header
|
||||||
|
int c = readHeader();
|
||||||
|
|
||||||
|
if (c == '\r' || c == '\n')
|
||||||
|
{
|
||||||
|
if (iHeaderLine.length())
|
||||||
|
{
|
||||||
|
// end of the line, all done
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ignore any CR or LF characters
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// append byte to header line
|
||||||
|
iHeaderLine += (char)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (iHeaderLine.length() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
String HttpClient::readHeaderName()
|
||||||
|
{
|
||||||
|
int colonIndex = iHeaderLine.indexOf(':');
|
||||||
|
|
||||||
|
if (colonIndex == -1)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return iHeaderLine.substring(0, colonIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
String HttpClient::readHeaderValue()
|
||||||
|
{
|
||||||
|
int colonIndex = iHeaderLine.indexOf(':');
|
||||||
|
int startIndex = colonIndex + 1;
|
||||||
|
|
||||||
|
if (colonIndex == -1)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim any leading whitespace
|
||||||
|
while (startIndex < (int)iHeaderLine.length() && isSpace(iHeaderLine[startIndex]))
|
||||||
|
{
|
||||||
|
startIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iHeaderLine.substring(startIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
int HttpClient::read(uint8_t *buf, size_t size)
|
int HttpClient::read(uint8_t *buf, size_t size)
|
||||||
@ -477,9 +502,9 @@ int HttpClient::read(uint8_t *buf, size_t size)
|
|||||||
// We're outputting the body now and we've seen a Content-Length header
|
// We're outputting the body now and we've seen a Content-Length header
|
||||||
// So keep track of how many bytes are left
|
// So keep track of how many bytes are left
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
{
|
{
|
||||||
iBodyLengthConsumed += ret;
|
iBodyLengthConsumed += ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
291
HttpClient.h
291
HttpClient.h
@ -44,11 +44,9 @@ public:
|
|||||||
// FIXME Write longer API request, using port and user-agent, example
|
// FIXME Write longer API request, using port and user-agent, example
|
||||||
// FIXME Update tempToPachube example to calculate Content-Length correctly
|
// FIXME Update tempToPachube example to calculate Content-Length correctly
|
||||||
|
|
||||||
#ifdef PROXY_ENABLED // currently disabled as introduces dependency on Dns.h in Ethernet
|
HttpClient(Client& aClient, const char* aServerName, uint16_t aServerPort = kHttpPort);
|
||||||
HttpClient(Client& aClient, const char* aProxy =NULL, uint16_t aProxyPort =0);
|
HttpClient(Client& aClient, const String& aServerName, uint16_t aServerPort = kHttpPort);
|
||||||
#else
|
HttpClient(Client& aClient, const IPAddress& aServerAddress, uint16_t aServerPort = kHttpPort);
|
||||||
HttpClient(Client& aClient);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Start a more complex request.
|
/** Start a more complex request.
|
||||||
Use this when you need to send additional headers in the request,
|
Use this when you need to send additional headers in the request,
|
||||||
@ -63,219 +61,42 @@ public:
|
|||||||
void endRequest();
|
void endRequest();
|
||||||
|
|
||||||
/** Connect to the server and start to send a GET request.
|
/** Connect to the server and start to send a GET request.
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aServerPort Port to connect to on the server
|
|
||||||
@param aURLPath Url to request
|
@param aURLPath Url to request
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
@return 0 if successful, else error
|
||||||
*/
|
*/
|
||||||
int get(const char* aServerName, uint16_t aServerPort, const char* aURLPath,
|
int get(const char* aURLPath)
|
||||||
const char* aUserAgent =NULL)
|
{ return startRequest(aURLPath, HTTP_METHOD_GET); }
|
||||||
{ return startRequest(aServerName, aServerPort, aURLPath, HTTP_METHOD_GET, aUserAgent); }
|
|
||||||
|
|
||||||
/** Connect to the server and start to send a GET request.
|
int get(const String& aURLPath)
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
{ return get(aURLPath.c_str()); }
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aURLPath Url to request
|
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
|
||||||
*/
|
|
||||||
int get(const char* aServerName, const char* aURLPath, const char* aUserAgent =NULL)
|
|
||||||
{ 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.
|
|
||||||
@param aServerAddress IP address of the server to connect to
|
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aServerPort Port to connect to on the server
|
|
||||||
@param aURLPath Url to request
|
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
|
||||||
*/
|
|
||||||
int get(const IPAddress& aServerAddress,
|
|
||||||
const char* aServerName,
|
|
||||||
uint16_t aServerPort,
|
|
||||||
const char* aURLPath,
|
|
||||||
const char* aUserAgent =NULL)
|
|
||||||
{ 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.
|
|
||||||
@param aServerAddress IP address of the server to connect to
|
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aURLPath Url to request
|
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
|
||||||
*/
|
|
||||||
int get(const IPAddress& aServerAddress,
|
|
||||||
const char* aServerName,
|
|
||||||
const char* aURLPath,
|
|
||||||
const char* aUserAgent =NULL)
|
|
||||||
{ return startRequest(aServerAddress, aServerName, kHttpPort, aURLPath, HTTP_METHOD_GET, aUserAgent); }
|
|
||||||
|
|
||||||
/** Connect to the server and start to send a POST request.
|
/** Connect to the server and start to send a POST request.
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aServerPort Port to connect to on the server
|
|
||||||
@param aURLPath Url to request
|
@param aURLPath Url to request
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
@return 0 if successful, else error
|
||||||
*/
|
*/
|
||||||
int post(const char* aServerName,
|
int post(const char* aURLPath)
|
||||||
uint16_t aServerPort,
|
{ return startRequest(aURLPath, HTTP_METHOD_POST); }
|
||||||
const char* aURLPath,
|
|
||||||
const char* aUserAgent =NULL)
|
|
||||||
{ return startRequest(aServerName, aServerPort, aURLPath, HTTP_METHOD_POST, aUserAgent); }
|
|
||||||
|
|
||||||
/** Connect to the server and start to send a POST request.
|
int post(const String& aURLPath)
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
{ return post(aURLPath.c_str()); }
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aURLPath Url to request
|
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
|
||||||
*/
|
|
||||||
int post(const char* aServerName,
|
|
||||||
const char* aURLPath,
|
|
||||||
const char* aUserAgent =NULL)
|
|
||||||
{ 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.
|
|
||||||
@param aServerAddress IP address of the server to connect to
|
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aServerPort Port to connect to on the server
|
|
||||||
@param aURLPath Url to request
|
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
|
||||||
*/
|
|
||||||
int post(const IPAddress& aServerAddress,
|
|
||||||
const char* aServerName,
|
|
||||||
uint16_t aServerPort,
|
|
||||||
const char* aURLPath,
|
|
||||||
const char* aUserAgent =NULL)
|
|
||||||
{ 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.
|
|
||||||
@param aServerAddress IP address of the server to connect to
|
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aURLPath Url to request
|
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
|
||||||
*/
|
|
||||||
int post(const IPAddress& aServerAddress,
|
|
||||||
const char* aServerName,
|
|
||||||
const char* aURLPath,
|
|
||||||
const char* aUserAgent =NULL)
|
|
||||||
{ return startRequest(aServerAddress, aServerName, kHttpPort, aURLPath, HTTP_METHOD_POST, aUserAgent); }
|
|
||||||
|
|
||||||
/** Connect to the server and start to send a PUT request.
|
/** Connect to the server and start to send a PUT request.
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aServerPort Port to connect to on the server
|
|
||||||
@param aURLPath Url to request
|
@param aURLPath Url to request
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
@return 0 if successful, else error
|
||||||
*/
|
*/
|
||||||
int put(const char* aServerName,
|
int put(const char* aURLPath)
|
||||||
uint16_t aServerPort,
|
{ return startRequest(aURLPath, HTTP_METHOD_PUT); }
|
||||||
const char* aURLPath,
|
|
||||||
const char* aUserAgent =NULL)
|
|
||||||
{ return startRequest(aServerName, aServerPort, aURLPath, HTTP_METHOD_PUT, aUserAgent); }
|
|
||||||
|
|
||||||
/** Connect to the server and start to send a PUT request.
|
int put(const String& aURLPath)
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
{ return put(aURLPath.c_str()); }
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aURLPath Url to request
|
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
|
||||||
*/
|
|
||||||
int put(const char* aServerName,
|
|
||||||
const char* aURLPath,
|
|
||||||
const char* aUserAgent =NULL)
|
|
||||||
{ 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.
|
|
||||||
@param aServerAddress IP address of the server to connect to
|
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aServerPort Port to connect to on the server
|
|
||||||
@param aURLPath Url to request
|
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
|
||||||
*/
|
|
||||||
int put(const IPAddress& aServerAddress,
|
|
||||||
const char* aServerName,
|
|
||||||
uint16_t aServerPort,
|
|
||||||
const char* aURLPath,
|
|
||||||
const char* aUserAgent =NULL)
|
|
||||||
{ 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.
|
|
||||||
@param aServerAddress IP address of the server to connect to
|
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aURLPath Url to request
|
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
|
||||||
*/
|
|
||||||
int put(const IPAddress& aServerAddress,
|
|
||||||
const char* aServerName,
|
|
||||||
const char* aURLPath,
|
|
||||||
const char* aUserAgent =NULL)
|
|
||||||
{ return startRequest(aServerAddress, aServerName, kHttpPort, aURLPath, HTTP_METHOD_PUT, aUserAgent); }
|
|
||||||
|
|
||||||
/** Connect to the server and start to send the request.
|
/** Connect to the server and start to send the request.
|
||||||
@param aServerName Name of the server being connected to.
|
|
||||||
@param aServerPort Port to connect to on the server
|
|
||||||
@param aURLPath Url to request
|
@param aURLPath Url to request
|
||||||
@param aHttpMethod Type of HTTP request to make, e.g. "GET", "POST", etc.
|
@param aHttpMethod Type of HTTP request to make, e.g. "GET", "POST", etc.
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
@return 0 if successful, else error
|
||||||
*/
|
*/
|
||||||
int startRequest(const char* aServerName,
|
int startRequest(const char* aURLPath,
|
||||||
uint16_t aServerPort,
|
const char* aHttpMethod);
|
||||||
const char* aURLPath,
|
|
||||||
const char* aHttpMethod,
|
|
||||||
const char* aUserAgent);
|
|
||||||
|
|
||||||
/** Connect to the server and start to send the request.
|
|
||||||
@param aServerAddress IP address of the server to connect to.
|
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aServerPort Port to connect to on the server
|
|
||||||
@param aURLPath Url to request
|
|
||||||
@param aHttpMethod Type of HTTP request to make, e.g. "GET", "POST", etc.
|
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
|
||||||
*/
|
|
||||||
int startRequest(const IPAddress& aServerAddress,
|
|
||||||
const char* aServerName,
|
|
||||||
uint16_t aServerPort,
|
|
||||||
const char* aURLPath,
|
|
||||||
const char* aHttpMethod,
|
|
||||||
const char* aUserAgent);
|
|
||||||
|
|
||||||
/** Send an additional header line. This can only be called in between the
|
/** Send an additional header line. This can only be called in between the
|
||||||
calls to startRequest and finishRequest.
|
calls to startRequest and finishRequest.
|
||||||
@ -284,6 +105,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
void sendHeader(const char* aHeader);
|
void sendHeader(const char* aHeader);
|
||||||
|
|
||||||
|
void sendHeader(const String& aHeader)
|
||||||
|
{ sendHeader(aHeader.c_str()); }
|
||||||
|
|
||||||
/** Send an additional header line. This is an alternate form of
|
/** Send an additional header line. This is an alternate form of
|
||||||
sendHeader() which takes the header name and content as separate strings.
|
sendHeader() which takes the header name and content as separate strings.
|
||||||
The call will add the ": " to separate the header, so for example, to
|
The call will add the ": " to separate the header, so for example, to
|
||||||
@ -293,6 +117,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
void sendHeader(const char* aHeaderName, const char* aHeaderValue);
|
void sendHeader(const char* aHeaderName, const char* aHeaderValue);
|
||||||
|
|
||||||
|
void sendHeader(const String& aHeaderName, const String& aHeaderValue)
|
||||||
|
{ sendHeader(aHeaderName.c_str(), aHeaderValue.c_str()); }
|
||||||
|
|
||||||
/** Send an additional header line. This is an alternate form of
|
/** Send an additional header line. This is an alternate form of
|
||||||
sendHeader() which takes the header name and content separately but where
|
sendHeader() which takes the header name and content separately but where
|
||||||
the value is provided as an integer.
|
the value is provided as an integer.
|
||||||
@ -303,6 +130,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
void sendHeader(const char* aHeaderName, const int aHeaderValue);
|
void sendHeader(const char* aHeaderName, const int aHeaderValue);
|
||||||
|
|
||||||
|
void sendHeader(const String& aHeaderName, const int aHeaderValue)
|
||||||
|
{ sendHeader(aHeaderName.c_str(), aHeaderValue); }
|
||||||
|
|
||||||
/** Send a basic authentication header. This will encode the given username
|
/** Send a basic authentication header. This will encode the given username
|
||||||
and password, and send them in suitable header line for doing Basic
|
and password, and send them in suitable header line for doing Basic
|
||||||
Authentication.
|
Authentication.
|
||||||
@ -311,21 +141,37 @@ public:
|
|||||||
*/
|
*/
|
||||||
void sendBasicAuth(const char* aUser, const char* aPassword);
|
void sendBasicAuth(const char* aUser, const char* aPassword);
|
||||||
|
|
||||||
/** Finish sending the HTTP request. This basically just sends the blank
|
void sendBasicAuth(const String& aUser, const String& aPassword)
|
||||||
line to signify the end of the request
|
{ sendBasicAuth(aUser.c_str(), aPassword.c_str()); }
|
||||||
*/
|
|
||||||
void finishRequest();
|
|
||||||
|
|
||||||
/** Get the HTTP status code contained in the response.
|
/** Get the HTTP status code contained in the response.
|
||||||
For example, 200 for successful request, 404 for file not found, etc.
|
For example, 200 for successful request, 404 for file not found, etc.
|
||||||
*/
|
*/
|
||||||
int responseStatusCode();
|
int responseStatusCode();
|
||||||
|
|
||||||
|
/** Check if a header is available to be read.
|
||||||
|
Use readHeaderName() to read header name, and readHeaderValue() to
|
||||||
|
read the header value
|
||||||
|
MUST be called after responseStatusCode() and before contentLength()
|
||||||
|
*/
|
||||||
|
bool headerAvailable();
|
||||||
|
|
||||||
|
/** Read the name of the current response header.
|
||||||
|
Returns empty string if a header is not available.
|
||||||
|
*/
|
||||||
|
String readHeaderName();
|
||||||
|
|
||||||
|
/** Read the vallue of the current response header.
|
||||||
|
Returns empty string if a header is not available.
|
||||||
|
*/
|
||||||
|
String readHeaderValue();
|
||||||
|
|
||||||
/** Read the next character of the response headers.
|
/** Read the next character of the response headers.
|
||||||
This functions in the same way as read() but to be used when reading
|
This functions in the same way as read() but to be used when reading
|
||||||
through the headers. Check whether or not the end of the headers has
|
through the headers. Check whether or not the end of the headers has
|
||||||
been reached by calling endOfHeadersReached(), although after that point
|
been reached by calling endOfHeadersReached(), although after that point
|
||||||
this will still return data as read() would, but slightly less efficiently
|
this will still return data as read() would, but slightly less efficiently
|
||||||
|
MUST be called after responseStatusCode() and before contentLength()
|
||||||
@return The next character of the response headers
|
@return The next character of the response headers
|
||||||
*/
|
*/
|
||||||
int readHeader();
|
int readHeader();
|
||||||
@ -335,6 +181,7 @@ public:
|
|||||||
returned in the response. You can also use it after you've found all of
|
returned in the response. You can also use it after you've found all of
|
||||||
the headers you're interested in, and just want to get on with processing
|
the headers you're interested in, and just want to get on with processing
|
||||||
the body.
|
the body.
|
||||||
|
MUST be called after responseStatusCode()
|
||||||
@return HTTP_SUCCESS if successful, else an error code
|
@return HTTP_SUCCESS if successful, else an error code
|
||||||
*/
|
*/
|
||||||
int skipResponseHeaders();
|
int skipResponseHeaders();
|
||||||
@ -353,10 +200,20 @@ public:
|
|||||||
virtual bool completed() { return endOfBodyReached(); };
|
virtual bool completed() { return endOfBodyReached(); };
|
||||||
|
|
||||||
/** Return the length of the body.
|
/** Return the length of the body.
|
||||||
|
Also skips response headers if they have not been read already
|
||||||
|
MUST be called after responseStatusCode()
|
||||||
@return Length of the body, in bytes, or kNoContentLengthHeader if no
|
@return Length of the body, in bytes, or kNoContentLengthHeader if no
|
||||||
Content-Length header was returned by the server
|
Content-Length header was returned by the server
|
||||||
*/
|
*/
|
||||||
int contentLength() { return iContentLength; };
|
int contentLength();
|
||||||
|
|
||||||
|
/** Enables connection keep-alive mode
|
||||||
|
*/
|
||||||
|
void connectionKeepAlive();
|
||||||
|
|
||||||
|
/** Disables sending the default request headers (Host and User Agent)
|
||||||
|
*/
|
||||||
|
void noDefaultRequestHeaders();
|
||||||
|
|
||||||
// Inherited from Print
|
// Inherited from Print
|
||||||
// Note: 1st call to these indicates the user is sending the body, so if need
|
// Note: 1st call to these indicates the user is sending the body, so if need
|
||||||
@ -387,28 +244,21 @@ protected:
|
|||||||
void resetState();
|
void resetState();
|
||||||
|
|
||||||
/** Send the first part of the request and the initial headers.
|
/** Send the first part of the request and the initial headers.
|
||||||
@param aServerName Name of the server being connected to. If NULL, the
|
|
||||||
"Host" header line won't be sent
|
|
||||||
@param aServerIP IP address of the server (only used if we're going through a
|
|
||||||
proxy and aServerName is NULL
|
|
||||||
@param aServerPort Port of the server being connected to.
|
|
||||||
@param aURLPath Url to request
|
@param aURLPath Url to request
|
||||||
@param aHttpMethod Type of HTTP request to make, e.g. "GET", "POST", etc.
|
@param aHttpMethod Type of HTTP request to make, e.g. "GET", "POST", etc.
|
||||||
@param aUserAgent User-Agent string to send. If NULL the default
|
|
||||||
user-agent kUserAgent will be sent
|
|
||||||
@return 0 if successful, else error
|
@return 0 if successful, else error
|
||||||
*/
|
*/
|
||||||
int sendInitialHeaders(const char* aServerName,
|
int sendInitialHeaders(const char* aURLPath,
|
||||||
IPAddress aServerIP,
|
const char* aHttpMethod);
|
||||||
uint16_t aPort,
|
|
||||||
const char* aURLPath,
|
|
||||||
const char* aHttpMethod,
|
|
||||||
const char* aUserAgent);
|
|
||||||
|
|
||||||
/* Let the server know that we've reached the end of the headers
|
/* Let the server know that we've reached the end of the headers
|
||||||
*/
|
*/
|
||||||
void finishHeaders();
|
void finishHeaders();
|
||||||
|
|
||||||
|
/** Reading any pending data from the client (used in connection keep alive mode)
|
||||||
|
*/
|
||||||
|
void flushClientRx();
|
||||||
|
|
||||||
// Number of milliseconds that we wait each time there isn't any data
|
// Number of milliseconds that we wait each time there isn't any data
|
||||||
// available to be read (during status code and header processing)
|
// available to be read (during status code and header processing)
|
||||||
static const int kHttpWaitForDataDelay = 1000;
|
static const int kHttpWaitForDataDelay = 1000;
|
||||||
@ -428,8 +278,13 @@ protected:
|
|||||||
eLineStartingCRFound,
|
eLineStartingCRFound,
|
||||||
eReadingBody
|
eReadingBody
|
||||||
} tHttpState;
|
} tHttpState;
|
||||||
// Ethernet client we're using
|
// Client we're using
|
||||||
Client* iClient;
|
Client* iClient;
|
||||||
|
// Server we are connecting to
|
||||||
|
const char* iServerName;
|
||||||
|
IPAddress iServerAddress;
|
||||||
|
// Port of server we are connecting to
|
||||||
|
uint16_t iServerPort;
|
||||||
// Current state of the finite-state-machine
|
// Current state of the finite-state-machine
|
||||||
tHttpState iState;
|
tHttpState iState;
|
||||||
// Stores the status code for the response, once known
|
// Stores the status code for the response, once known
|
||||||
@ -440,10 +295,10 @@ protected:
|
|||||||
int iBodyLengthConsumed;
|
int iBodyLengthConsumed;
|
||||||
// How far through a Content-Length header prefix we are
|
// How far through a Content-Length header prefix we are
|
||||||
const char* iContentLengthPtr;
|
const char* iContentLengthPtr;
|
||||||
// Address of the proxy to use, if we're using one
|
|
||||||
IPAddress iProxyAddress;
|
|
||||||
uint16_t iProxyPort;
|
|
||||||
uint32_t iHttpResponseTimeout;
|
uint32_t iHttpResponseTimeout;
|
||||||
|
bool iConnectionClose;
|
||||||
|
bool iSendDefaultRequestHeaders;
|
||||||
|
String iHeaderLine;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
21
README.md
21
README.md
@ -1,23 +1,22 @@
|
|||||||
# HttpClient
|
# ArduinoHttpClient
|
||||||
|
|
||||||
HttpClient is a library to make it easier to interact with web servers from Arduino.
|
ArduinoHttpClient is a library to make it easier to interact with web servers from Arduino.
|
||||||
|
|
||||||
|
Derived from [Adrian McEwen's HttpClient library](https://github.com/amcewen/HttpClient)
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- Requires the new Ethernet library API (with DHCP and DNS) which is in Arduino 1.0 and later
|
- Requires a networking hardware and a library that provides transport specific `Client` instance, such as:
|
||||||
|
- [WiFi101](https://github.com/arduino-libraries/WiFi101)
|
||||||
## Installation
|
- [Ethernet](https://github.com/arduino-libraries/Ethernet)
|
||||||
|
- [WiFi](https://github.com/arduino-libraries/WiFi)
|
||||||
1. Download the latest version of the library from https://github.com/amcewen/HttpClient/releases and save the file somewhere
|
- [GSM](https://github.com/arduino-libraries/GSM)
|
||||||
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
|
## 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).
|
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.
|
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 WiFiClient, EthernetClient and GSMClient.
|
||||||
|
|
||||||
See the examples for more detail on how the library is used.
|
See the examples for more detail on how the library is used.
|
||||||
|
|
||||||
|
2
b64.cpp
2
b64.cpp
@ -66,5 +66,7 @@ int b64_encode(const unsigned char* aInput, int aInputLen, unsigned char* aOutpu
|
|||||||
b64_encode(&aInput[i*3], aInputLen % 3, &aOutput[i*4], aOutputLen - (i*4));
|
b64_encode(&aInput[i*3], aInputLen % 3, &aOutput[i*4], aOutputLen - (i*4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ((aInputLen+2)/3)*4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
121
examples/DweetGet/DweetGet.ino
Normal file
121
examples/DweetGet/DweetGet.ino
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
Dweet.io GET client for ArduinoHttpClient library
|
||||||
|
Connects to dweet.io once every ten seconds,
|
||||||
|
sends a GET request and a request body. Uses SSL
|
||||||
|
|
||||||
|
Shows how to use Strings to assemble path and parse content
|
||||||
|
from response. dweet.io expects:
|
||||||
|
https://dweet.io/get/latest/dweet/for/thingName
|
||||||
|
|
||||||
|
For more on dweet.io, see https://dweet.io/play/
|
||||||
|
|
||||||
|
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
|
||||||
|
updated 16 Feb 2016
|
||||||
|
by Tom Igoe
|
||||||
|
|
||||||
|
this example is in the public domain
|
||||||
|
*/
|
||||||
|
#include <ArduinoHttpClient.h>
|
||||||
|
#include <WiFi101.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
const char serverAddress[] = "dweet.io"; // server address
|
||||||
|
int port = 80;
|
||||||
|
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;
|
||||||
|
int contentLength = 0;
|
||||||
|
String response;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
while (!Serial);
|
||||||
|
while ( status != WL_CONNECTED) {
|
||||||
|
Serial.print("Attempting to connect to Network named: ");
|
||||||
|
Serial.println(ssid); // print the network name (SSID);
|
||||||
|
|
||||||
|
// Connect to WPA/WPA2 network:
|
||||||
|
status = WiFi.begin(ssid, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the SSID of the network you're attached to:
|
||||||
|
Serial.print("SSID: ");
|
||||||
|
Serial.println(WiFi.SSID());
|
||||||
|
|
||||||
|
// print your WiFi shield's IP address:
|
||||||
|
IPAddress ip = WiFi.localIP();
|
||||||
|
Serial.print("IP Address: ");
|
||||||
|
Serial.println(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// assemble the path for the GET message:
|
||||||
|
String path = "/get/latest/dweet/for/" + dweetName;
|
||||||
|
|
||||||
|
// send the GET request
|
||||||
|
Serial.println("making GET request");
|
||||||
|
client.beginRequest();
|
||||||
|
client.get(path);
|
||||||
|
client.endRequest();
|
||||||
|
|
||||||
|
// read the status code of the response
|
||||||
|
statusCode = client.responseStatusCode();
|
||||||
|
Serial.print("Status code: ");
|
||||||
|
Serial.println(statusCode);
|
||||||
|
|
||||||
|
// read the content length of the response
|
||||||
|
contentLength = client.contentLength();
|
||||||
|
Serial.print("Content Length: ");
|
||||||
|
Serial.println(contentLength);
|
||||||
|
|
||||||
|
// read the response body
|
||||||
|
response = "";
|
||||||
|
response.reserve(contentLength);
|
||||||
|
while (client.available()) {
|
||||||
|
response += (char)client.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print("Response: ");
|
||||||
|
Serial.println(response);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Typical response is:
|
||||||
|
{"this":"succeeded",
|
||||||
|
"by":"getting",
|
||||||
|
"the":"dweets",
|
||||||
|
"with":[{"thing":"my-thing-name",
|
||||||
|
"created":"2016-02-16T05:10:36.589Z",
|
||||||
|
"content":{"sensorValue":456}}]}
|
||||||
|
|
||||||
|
You want "content": numberValue
|
||||||
|
*/
|
||||||
|
// now parse the response looking for "content":
|
||||||
|
int labelStart = response.indexOf("content\":");
|
||||||
|
// find the first { after "content":
|
||||||
|
int contentStart = response.indexOf("{", labelStart);
|
||||||
|
// find the following } and get what's between the braces:
|
||||||
|
int contentEnd = response.indexOf("}", labelStart);
|
||||||
|
String content = response.substring(contentStart + 1, contentEnd);
|
||||||
|
Serial.println(content);
|
||||||
|
|
||||||
|
// now get the value after the colon, and convert to an int:
|
||||||
|
int valueStart = content.indexOf(":");
|
||||||
|
String valueString = content.substring(valueStart + 1);
|
||||||
|
int number = valueString.toInt();
|
||||||
|
Serial.print("Value string: ");
|
||||||
|
Serial.println(valueString);
|
||||||
|
Serial.print("Actual value: ");
|
||||||
|
Serial.println(number);
|
||||||
|
|
||||||
|
Serial.println("Wait ten seconds\n");
|
||||||
|
delay(10000);
|
||||||
|
}
|
2
examples/DweetGet/config.h
Normal file
2
examples/DweetGet/config.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
char ssid[] = "ssid"; // your network SSID (name)
|
||||||
|
char pass[] = "password"; // your network password
|
93
examples/DweetPost/DweetPost.ino
Normal file
93
examples/DweetPost/DweetPost.ino
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
Dweet.io POST client for ArduinoHttpClient library
|
||||||
|
Connects to dweet.io once every ten seconds,
|
||||||
|
sends a POST request and a request body.
|
||||||
|
|
||||||
|
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
|
||||||
|
by Tom Igoe
|
||||||
|
|
||||||
|
this example is in the public domain
|
||||||
|
*/
|
||||||
|
#include <ArduinoHttpClient.h>
|
||||||
|
#include <WiFi101.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
const char serverAddress[] = "dweet.io"; // server address
|
||||||
|
int port = 80;
|
||||||
|
|
||||||
|
WiFiClient wifi;
|
||||||
|
HttpClient client = HttpClient(wifi, serverAddress, port);
|
||||||
|
int status = WL_IDLE_STATUS;
|
||||||
|
int statusCode = 0;
|
||||||
|
int contentLength = 0;
|
||||||
|
String response;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
while(!Serial);
|
||||||
|
while ( status != WL_CONNECTED) {
|
||||||
|
Serial.print("Attempting to connect to Network named: ");
|
||||||
|
Serial.println(ssid); // print the network name (SSID);
|
||||||
|
|
||||||
|
// Connect to WPA/WPA2 network:
|
||||||
|
status = WiFi.begin(ssid, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the SSID of the network you're attached to:
|
||||||
|
Serial.print("SSID: ");
|
||||||
|
Serial.println(WiFi.SSID());
|
||||||
|
|
||||||
|
// print your WiFi shield's IP address:
|
||||||
|
IPAddress ip = WiFi.localIP();
|
||||||
|
Serial.print("IP Address: ");
|
||||||
|
Serial.println(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// assemble the path for the POST message:
|
||||||
|
String dweetName = "scandalous-cheese-hoarder";
|
||||||
|
String path = "/dweet/for/" + dweetName;
|
||||||
|
|
||||||
|
// assemble the body of the POST message:
|
||||||
|
int sensorValue = analogRead(A0);
|
||||||
|
String postData = "{\"sensorValue\":\"";
|
||||||
|
postData += sensorValue;
|
||||||
|
postData += "\"}";
|
||||||
|
|
||||||
|
Serial.println("making POST request");
|
||||||
|
|
||||||
|
// send the POST request
|
||||||
|
client.beginRequest();
|
||||||
|
client.post(path);
|
||||||
|
client.sendHeader("Content-Type", "application/json");
|
||||||
|
client.sendHeader("Content-Length", postData.length());
|
||||||
|
client.endRequest();
|
||||||
|
client.write((const byte*)postData.c_str(), postData.length());
|
||||||
|
|
||||||
|
// read the status code and content length of the response
|
||||||
|
statusCode = client.responseStatusCode();
|
||||||
|
contentLength = client.contentLength();
|
||||||
|
|
||||||
|
// read the response body
|
||||||
|
response = "";
|
||||||
|
response.reserve(contentLength);
|
||||||
|
while (client.available()) {
|
||||||
|
response += (char)client.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print("Status code: ");
|
||||||
|
Serial.println(statusCode);
|
||||||
|
Serial.print("Response: ");
|
||||||
|
Serial.println(response);
|
||||||
|
|
||||||
|
Serial.println("Wait ten seconds\n");
|
||||||
|
delay(10000);
|
||||||
|
}
|
2
examples/DweetPost/config.h
Normal file
2
examples/DweetPost/config.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
char ssid[] = "ssid"; // your network SSID (name)
|
||||||
|
char pass[] = "password"; // your network password
|
110
examples/HueBlink/HueBlink.ino
Normal file
110
examples/HueBlink/HueBlink.ino
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/* HueBlink example for ArduinoHttpClient library
|
||||||
|
|
||||||
|
Uses ArduinoHttpClient library to control Philips Hue
|
||||||
|
For more on Hue developer API see http://developer.meethue.com
|
||||||
|
|
||||||
|
To control a light, the Hue expects a HTTP PUT request to:
|
||||||
|
|
||||||
|
http://hue.hub.address/api/hueUserName/lights/lightNumber/state
|
||||||
|
|
||||||
|
The body of the PUT request looks like this:
|
||||||
|
{"on": true} or {"on":false}
|
||||||
|
|
||||||
|
This example shows how to concatenate Strings to assemble the
|
||||||
|
PUT request and the body of the request.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
modified 15 Feb 2016
|
||||||
|
by Tom Igoe (tigoe) to match new API
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <WiFi101.h>
|
||||||
|
#include <ArduinoHttpClient.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
int status = WL_IDLE_STATUS; // the Wifi radio's status
|
||||||
|
char hueHubIP[] = "192.168.0.3"; // IP address of the HUE bridge
|
||||||
|
String hueUserName = "huebridgeusername"; // hue bridge username
|
||||||
|
|
||||||
|
// make a wifi instance and a HttpClient instance:
|
||||||
|
WiFiClient wifi;
|
||||||
|
HttpClient httpClient = HttpClient(wifi, hueHubIP);
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
//Initialize serial and wait for port to open:
|
||||||
|
Serial.begin(9600);
|
||||||
|
while (!Serial); // wait for serial port to connect.
|
||||||
|
|
||||||
|
// attempt to connect to Wifi network:
|
||||||
|
while ( status != WL_CONNECTED) {
|
||||||
|
Serial.print("Attempting to connect to WPA SSID: ");
|
||||||
|
Serial.println(ssid);
|
||||||
|
// Connect to WPA/WPA2 network:
|
||||||
|
status = WiFi.begin(ssid, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// you're connected now, so print out the data:
|
||||||
|
Serial.print("You're connected to the network IP = ");
|
||||||
|
IPAddress ip = WiFi.localIP();
|
||||||
|
Serial.println(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
sendRequest(3, "on", "true"); // turn light on
|
||||||
|
delay(2000); // wait 2 seconds
|
||||||
|
sendRequest(3, "on", "false"); // turn light off
|
||||||
|
delay(2000); // wait 2 seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendRequest(int light, String cmd, String value) {
|
||||||
|
// make a String for the HTTP request path:
|
||||||
|
String request = "/api/" + hueUserName;
|
||||||
|
request += "/lights/";
|
||||||
|
request += light;
|
||||||
|
request += "/state/";
|
||||||
|
|
||||||
|
// make a string for the JSON command:
|
||||||
|
String hueCmd = "{\"" + cmd;
|
||||||
|
hueCmd += "\":";
|
||||||
|
hueCmd += value;
|
||||||
|
hueCmd += "}";
|
||||||
|
// see what you assembled to send:
|
||||||
|
Serial.print("PUT request to server: ");
|
||||||
|
Serial.println(request);
|
||||||
|
Serial.print("JSON command to server: ");
|
||||||
|
|
||||||
|
// make the PUT request to the hub:
|
||||||
|
httpClient.beginRequest();
|
||||||
|
httpClient.put(request);
|
||||||
|
httpClient.sendHeader("Content-Type", "application/json");
|
||||||
|
httpClient.sendHeader("Content-Length", hueCmd.length());
|
||||||
|
httpClient.endRequest();
|
||||||
|
httpClient.write((const byte*)hueCmd.c_str(), hueCmd.length());
|
||||||
|
|
||||||
|
// read the status code and content length of the response
|
||||||
|
int statusCode = httpClient.responseStatusCode();
|
||||||
|
int contentLength = httpClient.contentLength();
|
||||||
|
|
||||||
|
// read the response body
|
||||||
|
String response = "";
|
||||||
|
response.reserve(contentLength);
|
||||||
|
while (httpClient.available()) {
|
||||||
|
response += (char)httpClient.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println(hueCmd);
|
||||||
|
Serial.print("Status code from server: ");
|
||||||
|
Serial.println(statusCode);
|
||||||
|
Serial.print("Server response: ");
|
||||||
|
Serial.println(response);
|
||||||
|
Serial.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
2
examples/HueBlink/config.h
Normal file
2
examples/HueBlink/config.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
char ssid[] = "ssid"; // your network SSID (name)
|
||||||
|
char pass[] = "password"; // your network password
|
80
examples/SimpleDelete/SimpleDelete.ino
Normal file
80
examples/SimpleDelete/SimpleDelete.ino
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
Simple DELETE client for ArduinoHttpClient library
|
||||||
|
Connects to server once every five seconds, sends a DELETE request
|
||||||
|
and a request 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 14 Feb 2016
|
||||||
|
by Tom Igoe
|
||||||
|
|
||||||
|
this example is in the public domain
|
||||||
|
*/
|
||||||
|
#include <ArduinoHttpClient.h>
|
||||||
|
#include <WiFi101.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
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;
|
||||||
|
int contentLength = 0;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
while ( status != WL_CONNECTED) {
|
||||||
|
Serial.print("Attempting to connect to Network named: ");
|
||||||
|
Serial.println(ssid); // print the network name (SSID);
|
||||||
|
|
||||||
|
// Connect to WPA/WPA2 network:
|
||||||
|
status = WiFi.begin(ssid, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the SSID of the network you're attached to:
|
||||||
|
Serial.print("SSID: ");
|
||||||
|
Serial.println(WiFi.SSID());
|
||||||
|
|
||||||
|
// print your WiFi shield's IP address:
|
||||||
|
IPAddress ip = WiFi.localIP();
|
||||||
|
Serial.print("IP Address: ");
|
||||||
|
Serial.println(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Serial.println("making DELETE request");
|
||||||
|
String delData = "name=light&age=46";
|
||||||
|
|
||||||
|
client.beginRequest();
|
||||||
|
client.startRequest("/", HTTP_METHOD_DELETE);
|
||||||
|
client.sendHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||||
|
client.sendHeader("Content-Length", delData.length());
|
||||||
|
client.endRequest();
|
||||||
|
client.write((const byte*)delData.c_str(), delData.length());
|
||||||
|
|
||||||
|
// read the status code and content length of the response
|
||||||
|
statusCode = client.responseStatusCode();
|
||||||
|
contentLength = client.contentLength();
|
||||||
|
|
||||||
|
// read the response body
|
||||||
|
response = "";
|
||||||
|
response.reserve(contentLength);
|
||||||
|
while (client.available()) {
|
||||||
|
response += (char)client.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print("Status code: ");
|
||||||
|
Serial.println(statusCode);
|
||||||
|
Serial.print("Response: ");
|
||||||
|
Serial.println(response);
|
||||||
|
|
||||||
|
Serial.println("Wait five seconds");
|
||||||
|
delay(5000);
|
||||||
|
}
|
2
examples/SimpleDelete/config.h
Normal file
2
examples/SimpleDelete/config.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
char ssid[] = "ssid"; // your network SSID (name)
|
||||||
|
char pass[] = "password"; // your network password
|
74
examples/SimpleGet/SimpleGet.ino
Normal file
74
examples/SimpleGet/SimpleGet.ino
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
Simple GET client for ArduinoHttpClient library
|
||||||
|
Connects to server once every five seconds, sends a GET request
|
||||||
|
|
||||||
|
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 14 Feb 2016
|
||||||
|
by Tom Igoe
|
||||||
|
|
||||||
|
this example is in the public domain
|
||||||
|
*/
|
||||||
|
#include <ArduinoHttpClient.h>
|
||||||
|
#include <WiFi101.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
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;
|
||||||
|
int contentLength = 0;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
while ( status != WL_CONNECTED) {
|
||||||
|
Serial.print("Attempting to connect to Network named: ");
|
||||||
|
Serial.println(ssid); // print the network name (SSID);
|
||||||
|
|
||||||
|
// Connect to WPA/WPA2 network:
|
||||||
|
status = WiFi.begin(ssid, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the SSID of the network you're attached to:
|
||||||
|
Serial.print("SSID: ");
|
||||||
|
Serial.println(WiFi.SSID());
|
||||||
|
|
||||||
|
// print your WiFi shield's IP address:
|
||||||
|
IPAddress ip = WiFi.localIP();
|
||||||
|
Serial.print("IP Address: ");
|
||||||
|
Serial.println(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Serial.println("making GET request");
|
||||||
|
|
||||||
|
// read the status code and content length of the response
|
||||||
|
client.beginRequest();
|
||||||
|
client.get("/");
|
||||||
|
client.endRequest();
|
||||||
|
|
||||||
|
statusCode = client.responseStatusCode();
|
||||||
|
contentLength = client.contentLength();
|
||||||
|
|
||||||
|
// read the response body
|
||||||
|
response = "";
|
||||||
|
response.reserve(contentLength);
|
||||||
|
while (client.available()) {
|
||||||
|
response += (char)client.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print("Status code: ");
|
||||||
|
Serial.println(statusCode);
|
||||||
|
Serial.print("Response: ");
|
||||||
|
Serial.println(response);
|
||||||
|
Serial.println("Wait five seconds");
|
||||||
|
delay(5000);
|
||||||
|
}
|
2
examples/SimpleGet/config.h
Normal file
2
examples/SimpleGet/config.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
char ssid[] = "ssid"; // your network SSID (name)
|
||||||
|
char pass[] = "password"; // your network password
|
@ -6,45 +6,54 @@
|
|||||||
// outputs the content to the serial port
|
// outputs the content to the serial port
|
||||||
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <HttpClient.h>
|
#include <WiFi101.h>
|
||||||
#include <Ethernet.h>
|
#include <ArduinoHttpClient.h>
|
||||||
#include <EthernetClient.h>
|
|
||||||
|
|
||||||
// This example downloads the URL "http://arduino.cc/"
|
// This example downloads the URL "http://arduino.cc/"
|
||||||
|
|
||||||
|
char ssid[] = "yourNetwork"; // your network SSID (name)
|
||||||
|
char pass[] = "secretPassword"; // your network password
|
||||||
|
|
||||||
// Name of the server we want to connect to
|
// Name of the server we want to connect to
|
||||||
const char kHostname[] = "arduino.cc";
|
const char kHostname[] = "arduino.cc";
|
||||||
// Path to download (this is the bit after the hostname in the URL
|
// Path to download (this is the bit after the hostname in the URL
|
||||||
// that you want to download
|
// that you want to download
|
||||||
const char kPath[] = "/";
|
const char kPath[] = "/";
|
||||||
|
|
||||||
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
|
||||||
|
|
||||||
// Number of milliseconds to wait without receiving any data before we give up
|
// Number of milliseconds to wait without receiving any data before we give up
|
||||||
const int kNetworkTimeout = 30*1000;
|
const int kNetworkTimeout = 30*1000;
|
||||||
// Number of milliseconds to wait if no data is available before trying again
|
// Number of milliseconds to wait if no data is available before trying again
|
||||||
const int kNetworkDelay = 1000;
|
const int kNetworkDelay = 1000;
|
||||||
|
|
||||||
|
WiFiClient c;
|
||||||
|
HttpClient http(c, kHostname);
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
// initialize serial communications at 9600 bps:
|
//Initialize serial and wait for port to open:
|
||||||
Serial.begin(9600);
|
Serial.begin(9600);
|
||||||
|
while (!Serial) {
|
||||||
while (Ethernet.begin(mac) != 1)
|
; // wait for serial port to connect. Needed for native USB port only
|
||||||
{
|
|
||||||
Serial.println("Error getting IP address via DHCP, trying again...");
|
|
||||||
delay(15000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// attempt to connect to Wifi network:
|
||||||
|
Serial.print("Attempting to connect to WPA SSID: ");
|
||||||
|
Serial.println(ssid);
|
||||||
|
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
|
||||||
|
// unsuccessful, retry in 4 seconds
|
||||||
|
Serial.print("failed ... ");
|
||||||
|
delay(4000);
|
||||||
|
Serial.print("retrying ... ");
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("connected");
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
int err =0;
|
int err =0;
|
||||||
|
|
||||||
EthernetClient c;
|
err = http.get(kPath);
|
||||||
HttpClient http(c);
|
|
||||||
|
|
||||||
err = http.get(kHostname, kPath);
|
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
{
|
{
|
||||||
Serial.println("startedRequest ok");
|
Serial.println("startedRequest ok");
|
||||||
@ -59,44 +68,43 @@ void loop()
|
|||||||
// similar "success" code (200-299) before carrying on,
|
// similar "success" code (200-299) before carrying on,
|
||||||
// but we'll print out whatever response we get
|
// but we'll print out whatever response we get
|
||||||
|
|
||||||
err = http.skipResponseHeaders();
|
// If you are interesting in the response headers, you
|
||||||
if (err >= 0)
|
// can read them here:
|
||||||
{
|
//while(http.headerAvailable())
|
||||||
int bodyLen = http.contentLength();
|
//{
|
||||||
Serial.print("Content length is: ");
|
// String headerName = http.readHeaderName();
|
||||||
Serial.println(bodyLen);
|
// String headerValue = http.readHeaderValue();
|
||||||
Serial.println();
|
//}
|
||||||
Serial.println("Body returned follows:");
|
|
||||||
|
|
||||||
// Now we've got to the body, so we can print it out
|
int bodyLen = http.contentLength();
|
||||||
unsigned long timeoutStart = millis();
|
Serial.print("Content length is: ");
|
||||||
char c;
|
Serial.println(bodyLen);
|
||||||
// Whilst we haven't timed out & haven't reached the end of the body
|
Serial.println();
|
||||||
while ( (http.connected() || http.available()) &&
|
Serial.println("Body returned follows:");
|
||||||
((millis() - timeoutStart) < kNetworkTimeout) )
|
|
||||||
{
|
|
||||||
if (http.available())
|
|
||||||
{
|
|
||||||
c = http.read();
|
|
||||||
// Print out this character
|
|
||||||
Serial.print(c);
|
|
||||||
|
|
||||||
bodyLen--;
|
// Now we've got to the body, so we can print it out
|
||||||
// We read something, reset the timeout counter
|
unsigned long timeoutStart = millis();
|
||||||
timeoutStart = millis();
|
char c;
|
||||||
}
|
// Whilst we haven't timed out & haven't reached the end of the body
|
||||||
else
|
while ( (http.connected() || http.available()) &&
|
||||||
{
|
(!http.endOfBodyReached()) &&
|
||||||
// We haven't got any data, so let's pause to allow some to
|
((millis() - timeoutStart) < kNetworkTimeout) )
|
||||||
// arrive
|
|
||||||
delay(kNetworkDelay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
Serial.print("Failed to skip response headers: ");
|
if (http.available())
|
||||||
Serial.println(err);
|
{
|
||||||
|
c = http.read();
|
||||||
|
// Print out this character
|
||||||
|
Serial.print(c);
|
||||||
|
|
||||||
|
// We read something, reset the timeout counter
|
||||||
|
timeoutStart = millis();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We haven't got any data, so let's pause to allow some to
|
||||||
|
// arrive
|
||||||
|
delay(kNetworkDelay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
80
examples/SimplePost/SimplePost.ino
Normal file
80
examples/SimplePost/SimplePost.ino
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
Simple POST client for ArduinoHttpClient library
|
||||||
|
Connects to server once every five seconds, sends a POST request
|
||||||
|
and a request 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 14 Feb 2016
|
||||||
|
by Tom Igoe
|
||||||
|
|
||||||
|
this example is in the public domain
|
||||||
|
*/
|
||||||
|
#include <ArduinoHttpClient.h>
|
||||||
|
#include <WiFi101.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
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;
|
||||||
|
int contentLength = 0;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
while ( status != WL_CONNECTED) {
|
||||||
|
Serial.print("Attempting to connect to Network named: ");
|
||||||
|
Serial.println(ssid); // print the network name (SSID);
|
||||||
|
|
||||||
|
// Connect to WPA/WPA2 network:
|
||||||
|
status = WiFi.begin(ssid, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the SSID of the network you're attached to:
|
||||||
|
Serial.print("SSID: ");
|
||||||
|
Serial.println(WiFi.SSID());
|
||||||
|
|
||||||
|
// print your WiFi shield's IP address:
|
||||||
|
IPAddress ip = WiFi.localIP();
|
||||||
|
Serial.print("IP Address: ");
|
||||||
|
Serial.println(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Serial.println("making POST request");
|
||||||
|
String postData = "name=Alice&age=12";
|
||||||
|
|
||||||
|
client.beginRequest();
|
||||||
|
client.post("/");
|
||||||
|
client.sendHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||||
|
client.sendHeader("Content-Length", postData.length());
|
||||||
|
client.endRequest();
|
||||||
|
client.write((const byte*)postData.c_str(), postData.length());
|
||||||
|
|
||||||
|
// read the status code and content length of the response
|
||||||
|
statusCode = client.responseStatusCode();
|
||||||
|
contentLength = client.contentLength();
|
||||||
|
|
||||||
|
// read the response body
|
||||||
|
response = "";
|
||||||
|
response.reserve(contentLength);
|
||||||
|
while (client.available()) {
|
||||||
|
response += (char)client.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print("Status code: ");
|
||||||
|
Serial.println(statusCode);
|
||||||
|
Serial.print("Response: ");
|
||||||
|
Serial.println(response);
|
||||||
|
|
||||||
|
Serial.println("Wait five seconds");
|
||||||
|
delay(5000);
|
||||||
|
}
|
2
examples/SimplePost/config.h
Normal file
2
examples/SimplePost/config.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
char ssid[] = "ssid"; // your network SSID (name)
|
||||||
|
char pass[] = "password"; // your network password
|
80
examples/SimplePut/SimplePut.ino
Normal file
80
examples/SimplePut/SimplePut.ino
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
Simple PUT client for ArduinoHttpClient library
|
||||||
|
Connects to server once every five seconds, sends a PUT request
|
||||||
|
and a request 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 14 Feb 2016
|
||||||
|
by Tom Igoe
|
||||||
|
|
||||||
|
this example is in the public domain
|
||||||
|
*/
|
||||||
|
#include <ArduinoHttpClient.h>
|
||||||
|
#include <WiFi101.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
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;
|
||||||
|
int contentLength = 0;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
while ( status != WL_CONNECTED) {
|
||||||
|
Serial.print("Attempting to connect to Network named: ");
|
||||||
|
Serial.println(ssid); // print the network name (SSID);
|
||||||
|
|
||||||
|
// Connect to WPA/WPA2 network:
|
||||||
|
status = WiFi.begin(ssid, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the SSID of the network you're attached to:
|
||||||
|
Serial.print("SSID: ");
|
||||||
|
Serial.println(WiFi.SSID());
|
||||||
|
|
||||||
|
// print your WiFi shield's IP address:
|
||||||
|
IPAddress ip = WiFi.localIP();
|
||||||
|
Serial.print("IP Address: ");
|
||||||
|
Serial.println(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
Serial.println("making PUT request");
|
||||||
|
String putData = "name=light&age=46";
|
||||||
|
|
||||||
|
client.beginRequest();
|
||||||
|
client.put("/");
|
||||||
|
client.sendHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||||
|
client.sendHeader("Content-Length", putData.length());
|
||||||
|
client.endRequest();
|
||||||
|
client.write((const byte*)putData.c_str(), putData.length());
|
||||||
|
|
||||||
|
// read the status code and content length of the response
|
||||||
|
statusCode = client.responseStatusCode();
|
||||||
|
contentLength = client.contentLength();
|
||||||
|
|
||||||
|
// read the response body
|
||||||
|
response = "";
|
||||||
|
response.reserve(contentLength);
|
||||||
|
while (client.available()) {
|
||||||
|
response += (char)client.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print("Status code: ");
|
||||||
|
Serial.println(statusCode);
|
||||||
|
Serial.print("Response: ");
|
||||||
|
Serial.println(response);
|
||||||
|
|
||||||
|
Serial.println("Wait five seconds");
|
||||||
|
delay(5000);
|
||||||
|
}
|
2
examples/SimplePut/config.h
Normal file
2
examples/SimplePut/config.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
char ssid[] = "ssid"; // your network SSID (name)
|
||||||
|
char pass[] = "password"; // your network password
|
42
examples/node_test_server/getPostPutDelete.js
Normal file
42
examples/node_test_server/getPostPutDelete.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
Express.js GET/POST example
|
||||||
|
Shows how handle GET, POST, PUT, DELETE
|
||||||
|
in Express.js 4.0
|
||||||
|
|
||||||
|
created 14 Feb 2016
|
||||||
|
by Tom Igoe
|
||||||
|
*/
|
||||||
|
|
||||||
|
var express = require('express'); // include express.js
|
||||||
|
var app = express(); // a local instance of it
|
||||||
|
var bodyParser = require('body-parser'); // include body-parser
|
||||||
|
|
||||||
|
// you need a body parser:
|
||||||
|
app.use(bodyParser.urlencoded({extended: false})); // for application/x-www-form-urlencoded
|
||||||
|
|
||||||
|
// this runs after the server successfully starts:
|
||||||
|
function serverStart() {
|
||||||
|
var port = server.address().port;
|
||||||
|
console.log('Server listening on port '+ port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is the POST handler:
|
||||||
|
app.all('/*', function (request, response) {
|
||||||
|
console.log('Got a ' + request.method + ' request');
|
||||||
|
// the parameters of a GET request are passed in
|
||||||
|
// request.body. Pass that to formatResponse()
|
||||||
|
// for formatting:
|
||||||
|
console.log(request.headers);
|
||||||
|
if (request.method == 'GET') {
|
||||||
|
console.log(request.query);
|
||||||
|
} else {
|
||||||
|
console.log(request.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the response:
|
||||||
|
response.send('OK');
|
||||||
|
response.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
// start the server:
|
||||||
|
var server = app.listen(8080, serverStart);
|
16
examples/node_test_server/package.json
Normal file
16
examples/node_test_server/package.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "node_test_server",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"author": {
|
||||||
|
"name":"Tom Igoe"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"express": ">=4.0.0",
|
||||||
|
"body-parser" : ">=1.11.0",
|
||||||
|
"multer" : "*"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "0.10.x",
|
||||||
|
"npm": "1.3.x"
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@
|
|||||||
# Datatypes (KEYWORD1)
|
# Datatypes (KEYWORD1)
|
||||||
#######################################
|
#######################################
|
||||||
|
|
||||||
|
ArduinoHttpClient KEYWORD1
|
||||||
HttpClient KEYWORD1
|
HttpClient KEYWORD1
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
@ -27,6 +28,11 @@ endOfHeadersReached KEYWORD2
|
|||||||
endOfBodyReached KEYWORD2
|
endOfBodyReached KEYWORD2
|
||||||
completed KEYWORD2
|
completed KEYWORD2
|
||||||
contentLength KEYWORD2
|
contentLength KEYWORD2
|
||||||
|
connectionKeepAlive KEYWORD2
|
||||||
|
noDefaultRequestHeaders KEYWORD2
|
||||||
|
headerAvailable KEYWORD2
|
||||||
|
readHeaderName KEYWORD2
|
||||||
|
readHeaderValue KEYWORD2
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Constants (LITERAL1)
|
# Constants (LITERAL1)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
name=HttpClient
|
name=ArduinoHttpClient
|
||||||
version=2.2.0
|
version=2.2.0
|
||||||
author=Adrian McEwen <adrianm@mcqn.com>
|
author=Adrian McEwen <adrianm@mcqn.com>
|
||||||
maintainer=Adrian McEwen <adrianm@mcqn.com>
|
maintainer=Arduino <info@arduino.cc>
|
||||||
sentence=Library to easily make HTTP GET, POST and PUT requests to a web server.
|
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.
|
paragraph=Works with any class derived from Client - so switching between Ethernet, WiFi and GSMClient requires minimal code changes.
|
||||||
category=Communication
|
category=Communication
|
||||||
url=http://github.com/amcewen/HttpClient
|
url=https://github.com/arduino-libraries/ArduinoHttpClient
|
||||||
architectures=*
|
architectures=*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user