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
|
273
HttpClient.cpp
273
HttpClient.cpp
@ -4,36 +4,29 @@
|
||||
|
||||
#include "HttpClient.h"
|
||||
#include "b64.h"
|
||||
#ifdef PROXY_ENABLED // currently disabled as introduces dependency on Dns.h in Ethernet
|
||||
#include <Dns.h>
|
||||
#endif
|
||||
|
||||
// Initialize constants
|
||||
const char* HttpClient::kUserAgent = "Arduino/2.2.0";
|
||||
const char* HttpClient::kContentLengthPrefix = HTTP_HEADER_CONTENT_LENGTH ": ";
|
||||
|
||||
#ifdef PROXY_ENABLED // currently disabled as introduces dependency on Dns.h in Ethernet
|
||||
HttpClient::HttpClient(Client& aClient, const char* aProxy, uint16_t aProxyPort)
|
||||
: iClient(&aClient), iProxyPort(aProxyPort)
|
||||
{
|
||||
resetState();
|
||||
if (aProxy)
|
||||
{
|
||||
// Resolve the IP address for the proxy
|
||||
DNSClient dns;
|
||||
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);
|
||||
}
|
||||
}
|
||||
#else
|
||||
HttpClient::HttpClient(Client& aClient)
|
||||
: iClient(&aClient), iProxyPort(0)
|
||||
HttpClient::HttpClient(Client& aClient, const char* aServerName, uint16_t aServerPort)
|
||||
: iClient(&aClient), iServerName(aServerName), iServerAddress(), iServerPort(aServerPort),
|
||||
iConnectionClose(true), iSendDefaultRequestHeaders(true)
|
||||
{
|
||||
resetState();
|
||||
}
|
||||
|
||||
HttpClient::HttpClient(Client& aClient, const String& aServerName, uint16_t aServerPort)
|
||||
: HttpClient(aClient, aServerName.c_str(), aServerPort)
|
||||
{
|
||||
}
|
||||
|
||||
HttpClient::HttpClient(Client& aClient, const IPAddress& aServerAddress, uint16_t aServerPort)
|
||||
: iClient(&aClient), iServerName(NULL), iServerAddress(aServerAddress), iServerPort(aServerPort),
|
||||
iConnectionClose(true), iSendDefaultRequestHeaders(true)
|
||||
{
|
||||
resetState();
|
||||
}
|
||||
#endif
|
||||
|
||||
void HttpClient::resetState()
|
||||
{
|
||||
@ -51,34 +44,49 @@ void HttpClient::stop()
|
||||
resetState();
|
||||
}
|
||||
|
||||
void HttpClient::connectionKeepAlive()
|
||||
{
|
||||
iConnectionClose = false;
|
||||
}
|
||||
|
||||
void HttpClient::noDefaultRequestHeaders()
|
||||
{
|
||||
iSendDefaultRequestHeaders = false;
|
||||
}
|
||||
|
||||
void HttpClient::beginRequest()
|
||||
{
|
||||
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;
|
||||
|
||||
if (!iConnectionClose)
|
||||
{
|
||||
flushClientRx();
|
||||
|
||||
resetState();
|
||||
}
|
||||
|
||||
if ((eIdle != iState) && (eRequestStarted != iState))
|
||||
{
|
||||
return HTTP_ERROR_API;
|
||||
}
|
||||
|
||||
#ifdef PROXY_ENABLED
|
||||
if (iProxyPort)
|
||||
if (iConnectionClose || !iClient->connected())
|
||||
{
|
||||
if (!iClient->connect(iProxyAddress, iProxyPort) > 0)
|
||||
if (iServerName) {
|
||||
if (!iClient->connect(iServerName, iServerPort) > 0)
|
||||
{
|
||||
#ifdef LOGGING
|
||||
Serial.println("Proxy connection failed");
|
||||
Serial.println("Connection failed");
|
||||
#endif
|
||||
return HTTP_ERROR_CONNECTION_FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
if (!iClient->connect(aServerName, aServerPort) > 0)
|
||||
} else {
|
||||
if (!iClient->connect(iServerAddress, iServerPort) > 0)
|
||||
{
|
||||
#ifdef LOGGING
|
||||
Serial.println("Connection failed");
|
||||
@ -86,9 +94,16 @@ int HttpClient::startRequest(const char* aServerName, uint16_t aServerPort, cons
|
||||
return HTTP_ERROR_CONNECTION_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef LOGGING
|
||||
Serial.println("Connection already open");
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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))
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
int HttpClient::startRequest(const IPAddress& aServerAddress, const char* aServerName, uint16_t aServerPort, const char* aURLPath, const char* aHttpMethod, const char* aUserAgent)
|
||||
{
|
||||
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)
|
||||
int HttpClient::sendInitialHeaders(const char* aURLPath, const char* aHttpMethod)
|
||||
{
|
||||
#ifdef LOGGING
|
||||
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"
|
||||
iClient->print(aHttpMethod);
|
||||
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->println(" HTTP/1.1");
|
||||
if (iSendDefaultRequestHeaders)
|
||||
{
|
||||
// The host header, if required
|
||||
if (aServerName)
|
||||
if (iServerName)
|
||||
{
|
||||
iClient->print("Host: ");
|
||||
iClient->print(aServerName);
|
||||
if (aPort != kHttpPort)
|
||||
iClient->print(iServerName);
|
||||
if (iServerPort != kHttpPort)
|
||||
{
|
||||
iClient->print(":");
|
||||
iClient->print(aPort);
|
||||
iClient->print(iServerPort);
|
||||
}
|
||||
iClient->println();
|
||||
}
|
||||
// And user-agent string
|
||||
if (aUserAgent)
|
||||
{
|
||||
sendHeader(HTTP_HEADER_USER_AGENT, aUserAgent);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendHeader(HTTP_HEADER_USER_AGENT, kUserAgent);
|
||||
}
|
||||
// We don't support persistent connections, so tell the server to
|
||||
|
||||
if (iConnectionClose)
|
||||
{
|
||||
// Tell the server to
|
||||
// close this connection after we're done
|
||||
sendHeader(HTTP_HEADER_CONNECTION, "close");
|
||||
}
|
||||
|
||||
// Everything has gone well
|
||||
iState = eRequestStarted;
|
||||
@ -278,6 +229,17 @@ void HttpClient::finishHeaders()
|
||||
iState = eRequestSent;
|
||||
}
|
||||
|
||||
void HttpClient::flushClientRx()
|
||||
{
|
||||
if (iClient->connected())
|
||||
{
|
||||
while (iClient->available())
|
||||
{
|
||||
iClient->read();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HttpClient::endRequest()
|
||||
{
|
||||
if (iState < eRequestSent)
|
||||
@ -299,7 +261,7 @@ int HttpClient::responseStatusCode()
|
||||
// Where HTTP-Version is of the form:
|
||||
// HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
|
||||
|
||||
char c = '\0';
|
||||
int c = '\0';
|
||||
do
|
||||
{
|
||||
// Make sure the status code is reset, and likewise the state. This
|
||||
@ -358,6 +320,9 @@ int HttpClient::responseStatusCode()
|
||||
case eStatusCodeRead:
|
||||
// We're just waiting for the end of the line now
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
// We read something, reset the timeout counter
|
||||
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()
|
||||
{
|
||||
if (endOfHeadersReached() && (contentLength() != kNoContentLengthHeader))
|
||||
@ -443,18 +419,6 @@ bool HttpClient::endOfBodyReached()
|
||||
|
||||
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();
|
||||
if (ret >= 0)
|
||||
{
|
||||
@ -466,7 +430,68 @@ int HttpClient::read()
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
291
HttpClient.h
291
HttpClient.h
@ -44,11 +44,9 @@ public:
|
||||
// FIXME Write longer API request, using port and user-agent, example
|
||||
// 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* aProxy =NULL, uint16_t aProxyPort =0);
|
||||
#else
|
||||
HttpClient(Client& aClient);
|
||||
#endif
|
||||
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);
|
||||
|
||||
/** Start a more complex request.
|
||||
Use this when you need to send additional headers in the request,
|
||||
@ -63,219 +61,42 @@ public:
|
||||
void endRequest();
|
||||
|
||||
/** 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 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, uint16_t aServerPort, const char* aURLPath,
|
||||
const char* aUserAgent =NULL)
|
||||
{ return startRequest(aServerName, aServerPort, aURLPath, HTTP_METHOD_GET, aUserAgent); }
|
||||
int get(const char* aURLPath)
|
||||
{ return startRequest(aURLPath, HTTP_METHOD_GET); }
|
||||
|
||||
/** 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 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); }
|
||||
int get(const String& aURLPath)
|
||||
{ return get(aURLPath.c_str()); }
|
||||
|
||||
/** 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 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,
|
||||
uint16_t aServerPort,
|
||||
const char* aURLPath,
|
||||
const char* aUserAgent =NULL)
|
||||
{ return startRequest(aServerName, aServerPort, aURLPath, HTTP_METHOD_POST, aUserAgent); }
|
||||
int post(const char* aURLPath)
|
||||
{ return startRequest(aURLPath, HTTP_METHOD_POST); }
|
||||
|
||||
/** 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 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); }
|
||||
int post(const String& aURLPath)
|
||||
{ return post(aURLPath.c_str()); }
|
||||
|
||||
/** 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 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,
|
||||
uint16_t aServerPort,
|
||||
const char* aURLPath,
|
||||
const char* aUserAgent =NULL)
|
||||
{ return startRequest(aServerName, aServerPort, aURLPath, HTTP_METHOD_PUT, aUserAgent); }
|
||||
int put(const char* aURLPath)
|
||||
{ return startRequest(aURLPath, HTTP_METHOD_PUT); }
|
||||
|
||||
/** 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 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); }
|
||||
int put(const String& aURLPath)
|
||||
{ return put(aURLPath.c_str()); }
|
||||
|
||||
/** 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 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 char* aServerName,
|
||||
uint16_t aServerPort,
|
||||
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);
|
||||
int startRequest(const char* aURLPath,
|
||||
const char* aHttpMethod);
|
||||
|
||||
/** Send an additional header line. This can only be called in between the
|
||||
calls to startRequest and finishRequest.
|
||||
@ -284,6 +105,9 @@ public:
|
||||
*/
|
||||
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
|
||||
sendHeader() which takes the header name and content as separate strings.
|
||||
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 String& aHeaderName, const String& aHeaderValue)
|
||||
{ sendHeader(aHeaderName.c_str(), aHeaderValue.c_str()); }
|
||||
|
||||
/** Send an additional header line. This is an alternate form of
|
||||
sendHeader() which takes the header name and content separately but where
|
||||
the value is provided as an integer.
|
||||
@ -303,6 +130,9 @@ public:
|
||||
*/
|
||||
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
|
||||
and password, and send them in suitable header line for doing Basic
|
||||
Authentication.
|
||||
@ -311,21 +141,37 @@ public:
|
||||
*/
|
||||
void sendBasicAuth(const char* aUser, const char* aPassword);
|
||||
|
||||
/** Finish sending the HTTP request. This basically just sends the blank
|
||||
line to signify the end of the request
|
||||
*/
|
||||
void finishRequest();
|
||||
void sendBasicAuth(const String& aUser, const String& aPassword)
|
||||
{ sendBasicAuth(aUser.c_str(), aPassword.c_str()); }
|
||||
|
||||
/** Get the HTTP status code contained in the response.
|
||||
For example, 200 for successful request, 404 for file not found, etc.
|
||||
*/
|
||||
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.
|
||||
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
|
||||
been reached by calling endOfHeadersReached(), although after that point
|
||||
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
|
||||
*/
|
||||
int readHeader();
|
||||
@ -335,6 +181,7 @@ public:
|
||||
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 body.
|
||||
MUST be called after responseStatusCode()
|
||||
@return HTTP_SUCCESS if successful, else an error code
|
||||
*/
|
||||
int skipResponseHeaders();
|
||||
@ -353,10 +200,20 @@ public:
|
||||
virtual bool completed() { return endOfBodyReached(); };
|
||||
|
||||
/** 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
|
||||
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
|
||||
// Note: 1st call to these indicates the user is sending the body, so if need
|
||||
@ -387,28 +244,21 @@ protected:
|
||||
void resetState();
|
||||
|
||||
/** 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 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 sendInitialHeaders(const char* aServerName,
|
||||
IPAddress aServerIP,
|
||||
uint16_t aPort,
|
||||
const char* aURLPath,
|
||||
const char* aHttpMethod,
|
||||
const char* aUserAgent);
|
||||
int sendInitialHeaders(const char* aURLPath,
|
||||
const char* aHttpMethod);
|
||||
|
||||
/* Let the server know that we've reached the end of the headers
|
||||
*/
|
||||
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
|
||||
// available to be read (during status code and header processing)
|
||||
static const int kHttpWaitForDataDelay = 1000;
|
||||
@ -428,8 +278,13 @@ protected:
|
||||
eLineStartingCRFound,
|
||||
eReadingBody
|
||||
} tHttpState;
|
||||
// Ethernet client we're using
|
||||
// Client we're using
|
||||
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
|
||||
tHttpState iState;
|
||||
// Stores the status code for the response, once known
|
||||
@ -440,10 +295,10 @@ protected:
|
||||
int iBodyLengthConsumed;
|
||||
// How far through a Content-Length header prefix we are
|
||||
const char* iContentLengthPtr;
|
||||
// Address of the proxy to use, if we're using one
|
||||
IPAddress iProxyAddress;
|
||||
uint16_t iProxyPort;
|
||||
uint32_t iHttpResponseTimeout;
|
||||
bool iConnectionClose;
|
||||
bool iSendDefaultRequestHeaders;
|
||||
String iHeaderLine;
|
||||
};
|
||||
|
||||
#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
|
||||
|
||||
- Requires the new Ethernet library API (with DHCP and DNS) which is in Arduino 1.0 and later
|
||||
|
||||
## Installation
|
||||
|
||||
1. Download the latest version of the library from https://github.com/amcewen/HttpClient/releases and save the file somewhere
|
||||
1. In the Arduino IDE, go to the Sketch -> Import Library -> Add Library... menu option
|
||||
1. Find the zip file that you saved in the first step, and choose that
|
||||
1. Check that it has been successfully added by opening the Sketch -> Import Library menu. You should now see HttpClient listed among the available libraries.
|
||||
- Requires a networking hardware and a library that provides transport specific `Client` instance, such as:
|
||||
- [WiFi101](https://github.com/arduino-libraries/WiFi101)
|
||||
- [Ethernet](https://github.com/arduino-libraries/Ethernet)
|
||||
- [WiFi](https://github.com/arduino-libraries/WiFi)
|
||||
- [GSM](https://github.com/arduino-libraries/GSM)
|
||||
|
||||
## Usage
|
||||
|
||||
In normal usage, handles the outgoing request and Host header. The returned status code is parsed for you, as is the Content-Length header (if present).
|
||||
|
||||
Because it expects an object of type Client, you can use it with any of the networking classes that derive from that. Which means it will work with EthernetClient, WiFiClient and GSMClient.
|
||||
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.
|
||||
|
||||
|
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));
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#include <SPI.h>
|
||||
#include <HttpClient.h>
|
||||
#include <Ethernet.h>
|
||||
#include <EthernetClient.h>
|
||||
#include <WiFi101.h>
|
||||
#include <ArduinoHttpClient.h>
|
||||
|
||||
// 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
|
||||
const char kHostname[] = "arduino.cc";
|
||||
// Path to download (this is the bit after the hostname in the URL
|
||||
// that you want to download
|
||||
const char kPath[] = "/";
|
||||
|
||||
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
|
||||
// Number of milliseconds to wait without receiving any data before we give up
|
||||
const int kNetworkTimeout = 30*1000;
|
||||
// Number of milliseconds to wait if no data is available before trying again
|
||||
const int kNetworkDelay = 1000;
|
||||
|
||||
WiFiClient c;
|
||||
HttpClient http(c, kHostname);
|
||||
|
||||
void setup()
|
||||
{
|
||||
// initialize serial communications at 9600 bps:
|
||||
//Initialize serial and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
|
||||
while (Ethernet.begin(mac) != 1)
|
||||
{
|
||||
Serial.println("Error getting IP address via DHCP, trying again...");
|
||||
delay(15000);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for native USB port only
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
int err =0;
|
||||
|
||||
EthernetClient c;
|
||||
HttpClient http(c);
|
||||
|
||||
err = http.get(kHostname, kPath);
|
||||
err = http.get(kPath);
|
||||
if (err == 0)
|
||||
{
|
||||
Serial.println("startedRequest ok");
|
||||
@ -59,9 +68,14 @@ void loop()
|
||||
// similar "success" code (200-299) before carrying on,
|
||||
// but we'll print out whatever response we get
|
||||
|
||||
err = http.skipResponseHeaders();
|
||||
if (err >= 0)
|
||||
{
|
||||
// If you are interesting in the response headers, you
|
||||
// can read them here:
|
||||
//while(http.headerAvailable())
|
||||
//{
|
||||
// String headerName = http.readHeaderName();
|
||||
// String headerValue = http.readHeaderValue();
|
||||
//}
|
||||
|
||||
int bodyLen = http.contentLength();
|
||||
Serial.print("Content length is: ");
|
||||
Serial.println(bodyLen);
|
||||
@ -73,6 +87,7 @@ void loop()
|
||||
char c;
|
||||
// Whilst we haven't timed out & haven't reached the end of the body
|
||||
while ( (http.connected() || http.available()) &&
|
||||
(!http.endOfBodyReached()) &&
|
||||
((millis() - timeoutStart) < kNetworkTimeout) )
|
||||
{
|
||||
if (http.available())
|
||||
@ -81,7 +96,6 @@ void loop()
|
||||
// Print out this character
|
||||
Serial.print(c);
|
||||
|
||||
bodyLen--;
|
||||
// We read something, reset the timeout counter
|
||||
timeoutStart = millis();
|
||||
}
|
||||
@ -94,12 +108,6 @@ void loop()
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("Failed to skip response headers: ");
|
||||
Serial.println(err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("Getting response failed: ");
|
||||
Serial.println(err);
|
||||
|
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)
|
||||
#######################################
|
||||
|
||||
ArduinoHttpClient KEYWORD1
|
||||
HttpClient KEYWORD1
|
||||
|
||||
#######################################
|
||||
@ -27,6 +28,11 @@ endOfHeadersReached KEYWORD2
|
||||
endOfBodyReached KEYWORD2
|
||||
completed KEYWORD2
|
||||
contentLength KEYWORD2
|
||||
connectionKeepAlive KEYWORD2
|
||||
noDefaultRequestHeaders KEYWORD2
|
||||
headerAvailable KEYWORD2
|
||||
readHeaderName KEYWORD2
|
||||
readHeaderValue KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
|
@ -1,9 +1,9 @@
|
||||
name=HttpClient
|
||||
name=ArduinoHttpClient
|
||||
version=2.2.0
|
||||
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.
|
||||
paragraph=Works with any class derived from Client - so switching between Ethernet, WiFi and GSMClient requires minimal code changes.
|
||||
category=Communication
|
||||
url=http://github.com/amcewen/HttpClient
|
||||
url=https://github.com/arduino-libraries/ArduinoHttpClient
|
||||
architectures=*
|
||||
|
Loading…
x
Reference in New Issue
Block a user