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;
0 commit comments