| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,9 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | 5 | #include "HttpClient.h" | |
| 6 | 6 | #include <../b64/b64.h> | |
| 7 | + #include <Dns.h> | ||
| 7 | 8 | #include <string.h> | |
| 8 | 9 | #include <ctype.h> | |
| 9 | - #include "wiring.h" | ||
| 10 | 10 | ||
| 11 | 11 | // Initialize constants | |
| 12 | 12 | const char* HttpClient::kUserAgent = "Arduino/2.0"; | |
@@ -16,10 +16,19 @@ const char* HttpClient::kPut = "PUT"; | |||
| 16 | 16 | const char* HttpClient::kDelete = "DELETE"; | |
| 17 | 17 | const char* HttpClient::kContentLengthPrefix = "Content-Length: "; | |
| 18 | 18 | ||
| 19 | - HttpClient::HttpClient(Client& aClient) | ||
| 20 | - : iClient(&aClient) | ||
| 19 | + HttpClient::HttpClient(Client& aClient, const char* aProxy, uint16_t aProxyPort) | ||
| 20 | + : iClient(&aClient), iProxyPort(aProxyPort) | ||
| 21 | 21 | { | |
| 22 | 22 | resetState(); | |
| 23 | + if (aProxy) | ||
| 24 | + { | ||
| 25 | + // Resolve the IP address for the proxy | ||
| 26 | + DNSClient dns; | ||
| 27 | + dns.begin(Ethernet.dnsServerIP()); | ||
| 28 | + // Not ideal that we discard any errors here, but not a lot we can do in the ctor | ||
| 29 | + // and we'll get a connect error later anyway | ||
| 30 | + (void)dns.getHostByName(aProxy, iProxyAddress); | ||
| 31 | + } | ||
| 23 | 32 | } | |
| 24 | 33 | ||
| 25 | 34 | void HttpClient::resetState() | |
@@ -44,16 +53,29 @@ int HttpClient::startRequest(const char* aServerName, uint16_t aServerPort, cons | |||
| 44 | 53 | return HttpErrAPI; | |
| 45 | 54 | } | |
| 46 | 55 | ||
| 47 | - if (!iClient->connect(aServerName, aServerPort)) | ||
| 56 | + if (iProxyPort) | ||
| 48 | 57 | { | |
| 58 | + if (!iClient->connect(iProxyAddress, iProxyPort)) | ||
| 59 | + { | ||
| 60 | + #ifdef LOGGING | ||
| 61 | + Serial.println("Proxy connection failed"); | ||
| 62 | + #endif | ||
| 63 | + return HttpErrConnectionFailed; | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + else | ||
| 67 | + { | ||
| 68 | + if (!iClient->connect(aServerName, aServerPort)) | ||
| 69 | + { | ||
| 49 | 70 | #ifdef LOGGING | |
| 50 | - Serial.println("Connection failed"); | ||
| 71 | + Serial.println("Connection failed"); | ||
| 51 | 72 | #endif | |
| 52 | - return HttpErrConnectionFailed; | ||
| 73 | + return HttpErrConnectionFailed; | ||
| 74 | + } | ||
| 53 | 75 | } | |
| 54 | 76 | ||
| 55 | 77 | // Now we're connected, send the first part of the request | |
| 56 | - return sendInitialHeaders(aServerName, aURLPath, aHttpMethod, aUserAgent, aAcceptList); | ||
| 78 | + return sendInitialHeaders(aServerName, IPAddress(0,0,0,0), aServerPort, aURLPath, aHttpMethod, aUserAgent, aAcceptList); | ||
| 57 | 79 | } | |
| 58 | 80 | ||
| 59 | 81 | int HttpClient::startRequest(const IPAddress& aServerAddress, uint16_t aServerPort, const char* aServerName, const char* aURLPath, const char* aHttpMethod, const char* aUserAgent, const char* aAcceptList) | |
@@ -63,33 +85,66 @@ int HttpClient::startRequest(const IPAddress& aServerAddress, uint16_t aServerPo | |||
| 63 | 85 | return HttpErrAPI; | |
| 64 | 86 | } | |
| 65 | 87 | ||
| 66 | - if (!iClient->connect(aServerAddress, aServerPort)) | ||
| 88 | + if (iProxyPort) | ||
| 89 | + { | ||
| 90 | + if (!iClient->connect(iProxyAddress, iProxyPort)) | ||
| 91 | + { | ||
| 92 | + #ifdef LOGGING | ||
| 93 | + Serial.println("Proxy connection failed"); | ||
| 94 | + #endif | ||
| 95 | + return HttpErrConnectionFailed; | ||
| 96 | + } | ||
| 97 | + } | ||
| 98 | + else | ||
| 67 | 99 | { | |
| 100 | + if (!iClient->connect(aServerAddress, aServerPort)) | ||
| 101 | + { | ||
| 68 | 102 | #ifdef LOGGING | |
| 69 | - Serial.println("Connection failed"); | ||
| 103 | + Serial.println("Connection failed"); | ||
| 70 | 104 | #endif | |
| 71 | - return HttpErrConnectionFailed; | ||
| 105 | + return HttpErrConnectionFailed; | ||
| 106 | + } | ||
| 72 | 107 | } | |
| 73 | 108 | ||
| 74 | 109 | // Now we're connected, send the first part of the request | |
| 75 | - return sendInitialHeaders(aServerName, aURLPath, aHttpMethod, aUserAgent, aAcceptList); | ||
| 110 | + return sendInitialHeaders(aServerName, aServerAddress, aServerPort, aURLPath, aHttpMethod, aUserAgent, aAcceptList); | ||
| 76 | 111 | } | |
| 77 | 112 | ||
| 78 | - int HttpClient::sendInitialHeaders(const char* aServerName, const char* aURLPath, const char* aHttpMethod, const char* aUserAgent, const char* aAcceptList) | ||
| 113 | + int HttpClient::sendInitialHeaders(const char* aServerName, IPAddress aServerIP, uint16_t aPort, const char* aURLPath, const char* aHttpMethod, const char* aUserAgent, const char* aAcceptList) | ||
| 79 | 114 | { | |
| 80 | 115 | #ifdef LOGGING | |
| 81 | 116 | Serial.println("Connected"); | |
| 82 | 117 | #endif | |
| 83 | 118 | // Send the HTTP command, i.e. "GET /somepath/ HTTP/1.0" | |
| 84 | 119 | print(aHttpMethod); | |
| 85 | 120 | print(" "); | |
| 121 | + if (iProxyPort) | ||
| 122 | + { | ||
| 123 | + // We're going through a proxy, send a full URL | ||
| 124 | + print("http://"); | ||
| 125 | + if (aServerName) | ||
| 126 | + { | ||
| 127 | + // We've got a server name, so use it | ||
| 128 | + print(aServerName); | ||
| 129 | + } | ||
| 130 | + else | ||
| 131 | + { | ||
| 132 | + // We'll have to use the IP address | ||
| 133 | + print(aServerIP); | ||
| 134 | + } | ||
| 135 | + if (aPort != kHttpPort) | ||
| 136 | + { | ||
| 137 | + print(":"); | ||
| 138 | + print(aPort); | ||
| 139 | + } | ||
| 140 | + } | ||
| 86 | 141 | print(aURLPath); | |
| 87 | 142 | println(" HTTP/1.0"); | |
| 88 | 143 | // The host header, if required | |
| 89 | 144 | if (aServerName) | |
| 90 | 145 | { | |
| 91 | - print("Host: "); | ||
| 92 | - println(aServerName); | ||
| 146 | + // print("Host: "); | ||
| 147 | + // println(aServerName); | ||
| 93 | 148 | } | |
| 94 | 149 | // And user-agent string | |
| 95 | 150 | print("User-Agent: "); | |
@@ -339,14 +394,28 @@ bool HttpClient::endOfBodyReached() | |||
| 339 | 394 | ||
| 340 | 395 | int HttpClient::read() | |
| 341 | 396 | { | |
| 342 | - int ret =iClient->read(); | ||
| 397 | + uint8_t b[1]; | ||
| 398 | + int ret = read(b, 1); | ||
| 399 | + if (ret == 1) | ||
| 400 | + { | ||
| 401 | + return b[0]; | ||
| 402 | + } | ||
| 403 | + else | ||
| 404 | + { | ||
| 405 | + return -1; | ||
| 406 | + } | ||
| 407 | + } | ||
| 408 | + | ||
| 409 | + int HttpClient::read(uint8_t *buf, size_t size) | ||
| 410 | + { | ||
| 411 | + int ret =iClient->read(buf, size); | ||
| 343 | 412 | if (endOfHeadersReached() && iContentLength > 0) | |
| 344 | 413 | { | |
| 345 | 414 | // We're outputting the body now and we've seen a Content-Length header | |
| 346 | 415 | // So keep track of how many bytes are left | |
| 347 | 416 | if (ret >= 0) | |
| 348 | 417 | { | |
| 349 | - iBodyLengthConsumed++; | ||
| 418 | + iBodyLengthConsumed += ret; | ||
| 350 | 419 | } | |
| 351 | 420 | } | |
| 352 | 421 | return ret; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,10 +5,11 @@ | |||
| 5 | 5 | #ifndef HttpClient_h | |
| 6 | 6 | #define HttpClient_h | |
| 7 | 7 | ||
| 8 | + #include <Arduino.h> | ||
| 8 | 9 | #include <IPAddress.h> | |
| 9 | 10 | #include "Ethernet.h" | |
| 10 | 11 | #include "Client.h" | |
| 11 | - #include <../b64.h> | ||
| 12 | + #include <b64.h> | ||
| 12 | 13 | ||
| 13 | 14 | class HttpClient : public Client | |
| 14 | 15 | { | |
@@ -31,13 +32,14 @@ class HttpClient : public Client | |||
| 31 | 32 | }; | |
| 32 | 33 | ||
| 33 | 34 | static const int kNoContentLengthHeader =-1; | |
| 35 | + static const int kHttpPort =80; | ||
| 34 | 36 | static const char* kUserAgent; | |
| 35 | 37 | static const char* kGet; | |
| 36 | 38 | static const char* kPost; | |
| 37 | 39 | static const char* kPut; | |
| 38 | 40 | static const char* kDelete; | |
| 39 | 41 | ||
| 40 | - HttpClient(Client& aClient); | ||
| 42 | + HttpClient(Client& aClient, const char* aProxy =NULL, uint16_t aProxyPort =0); | ||
| 41 | 43 | ||
| 42 | 44 | /** Connect to the server and start to send a GET request. | |
| 43 | 45 | @param aServerName Name of the server being connected to. If NULL, the | |
@@ -274,15 +276,16 @@ class HttpClient : public Client | |||
| 274 | 276 | int contentLength() { return iContentLength; }; | |
| 275 | 277 | ||
| 276 | 278 | // Inherited from Print | |
| 277 | - virtual void write(uint8_t aByte) { iClient-> write(aByte); }; | ||
| 278 | - virtual void write(const char *aStr) { iClient->write(aStr); }; | ||
| 279 | - virtual void write(const uint8_t *aBuffer, size_t aSize) { iClient->write(aBuffer, aSize); }; | ||
| 279 | + virtual size_t write(uint8_t aByte) { return iClient-> write(aByte); }; | ||
| 280 | + virtual size_t write(const char *aStr) { return iClient->write(aStr); }; | ||
| 281 | + virtual size_t write(const uint8_t *aBuffer, size_t aSize) { return iClient->write(aBuffer, aSize); }; | ||
| 280 | 282 | // Inherited from Stream | |
| 281 | 283 | virtual int available() { return iClient->available(); }; | |
| 282 | 284 | /** Read the next byte from the server. | |
| 283 | 285 | @return Byte read or -1 if there are no bytes available. | |
| 284 | 286 | */ | |
| 285 | 287 | virtual int read(); | |
| 288 | + virtual int read(uint8_t *buf, size_t size); | ||
| 286 | 289 | virtual int peek() { return iClient->peek(); }; | |
| 287 | 290 | virtual void flush() { return iClient->flush(); }; | |
| 288 | 291 | ||
@@ -291,13 +294,17 @@ class HttpClient : public Client | |||
| 291 | 294 | virtual int connect(const char *host, uint16_t port) { return iClient->connect(host, port); }; | |
| 292 | 295 | virtual void stop(); | |
| 293 | 296 | virtual uint8_t connected() { iClient->connected(); }; | |
| 297 | + virtual operator bool() { return bool(iClient); }; | ||
| 294 | 298 | protected: | |
| 295 | 299 | /** Reset internal state data back to the "just initialised" state | |
| 296 | 300 | */ | |
| 297 | 301 | void resetState(); | |
| 298 | 302 | /** Send the first part of the request and the initial headers. | |
| 299 | 303 | @param aServerName Name of the server being connected to. If NULL, the | |
| 300 | 304 | "Host" header line won't be sent | |
| 305 | + @param aServerIP IP address of the server (only used if we're going through a | ||
| 306 | + proxy and aServerName is NULL | ||
| 307 | + @param aServerPort Port of the server being connected to. | ||
| 301 | 308 | @param aURLPath Url to request | |
| 302 | 309 | @param aHttpMethod Type of HTTP request to make, e.g. "GET", "POST", etc. | |
| 303 | 310 | @param aUserAgent User-Agent string to send. If NULL the default | |
@@ -307,6 +314,8 @@ class HttpClient : public Client | |||
| 307 | 314 | @return 0 if successful, else error | |
| 308 | 315 | */ | |
| 309 | 316 | int sendInitialHeaders(const char* aServerName, | |
| 317 | + IPAddress aServerIP, | ||
| 318 | + uint16_t aPort, | ||
| 310 | 319 | const char* aURLPath, | |
| 311 | 320 | const char* aHttpMethod, | |
| 312 | 321 | const char* aUserAgent, | |
@@ -343,6 +352,9 @@ class HttpClient : public Client | |||
| 343 | 352 | int iBodyLengthConsumed; | |
| 344 | 353 | // How far through a Content-Length header prefix we are | |
| 345 | 354 | const char* iContentLengthPtr; | |
| 355 | + // Address of the proxy to use, if we're using one | ||
| 356 | + IPAddress iProxyAddress; | ||
| 357 | + uint16_t iProxyPort; | ||
| 346 | 358 | }; | |
| 347 | 359 | ||
| 348 | 360 | #endif | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -9,7 +9,7 @@ | |||
| 9 | 9 | #include <HttpClient.h> | |
| 10 | 10 | #include <b64.h> | |
| 11 | 11 | #include <Ethernet.h> | |
| 12 | - #include <Client.h> | ||
| 12 | + #include <EthernetClient.h> | ||
| 13 | 13 | ||
| 14 | 14 | // This example downloads the URL "http://arduino.cc/" | |
| 15 | 15 | ||
@@ -44,7 +44,7 @@ void loop() | |||
| 44 | 44 | { | |
| 45 | 45 | int err =0; | |
| 46 | 46 | ||
| 47 | - Client c; | ||
| 47 | + EthernetClient c; | ||
| 48 | 48 | HttpClient http(c); | |
| 49 | 49 | ||
| 50 | 50 | err = http.get(kHostname, 80, kPath); | |
@@ -77,8 +77,8 @@ void loop() | |||
| 77 | 77 | unsigned long timeoutStart = millis(); | |
| 78 | 78 | char c; | |
| 79 | 79 | // Whilst we haven't timed out & haven't reached the end of the body | |
| 80 | - while (http.connected() && | ||
| 81 | - ( (millis() - timeoutStart) < kNetworkTimeout )) | ||
| 80 | + while ( (http.connected() || http.available()) && | ||
| 81 | + ((millis() - timeoutStart) < kNetworkTimeout) ) | ||
| 82 | 82 | { | |
| 83 | 83 | if (http.available()) | |
| 84 | 84 | { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments