Skip to content

Commit 98e1375

Browse files
committed
Re-connect to git
0 parents  commit 98e1375

File tree

4 files changed

+291
-0
lines changed

4 files changed

+291
-0
lines changed

ESPAsyncHTTPClient.cpp

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#include <ESPAsyncHTTPClient.h>
2+
3+
#define DEBUG(...) {}
4+
5+
String& ByteString::copy(const void *data, unsigned int length) {
6+
if (!reserve(length)) {
7+
invalidate();
8+
return *this;
9+
}
10+
#if defined (ESP32) || defined (NEW_WSTRING)
11+
setLen(length);
12+
memcpy(wbuffer(), data, length);
13+
wbuffer()[length] = 0;
14+
#else
15+
len = length;
16+
memcpy(buffer, data, length);
17+
buffer[length] = 0;
18+
#endif
19+
return *this;
20+
}
21+
22+
void AsyncHTTPClient::initialize(String url) {
23+
// check for : (http: or https:
24+
int index = url.indexOf(':');
25+
if (index < 0) {
26+
initialized = false; // This is not a URL
27+
}
28+
29+
protocol = url.substring(0, index);
30+
DEBUG(protocol);
31+
port = 80; //Default
32+
if (index == 5) {
33+
port = 443;
34+
}
35+
36+
url.remove(0, (index + 3)); // remove http:// or https://
37+
38+
index = url.indexOf('/');
39+
String hostPart = url.substring(0, index);
40+
DEBUG(hostPart);
41+
url.remove(0, index); // remove hostPart part
42+
43+
// get Authorization
44+
index = hostPart.indexOf('@');
45+
46+
if (index >= 0) {
47+
// auth info
48+
String auth = hostPart.substring(0, index);
49+
hostPart.remove(0, index + 1); // remove auth part including @
50+
base64Authorization = base64::encode(auth);
51+
}
52+
53+
// get port
54+
index = hostPart.indexOf(':');
55+
if (index >= 0) {
56+
host = hostPart.substring(0, index); // hostname
57+
host.remove(0, (index + 1)); // remove hostname + :
58+
DEBUG(host);
59+
port = host.toInt(); // get port
60+
DEBUG(port);
61+
} else {
62+
host = hostPart;
63+
DEBUG(host);
64+
}
65+
uri = url;
66+
#if ASYNC_TCP_SSL_ENABLED
67+
initialized = protocol == "http" || protocol == "https";
68+
#else
69+
initialized = protocol == "http";
70+
#endif
71+
72+
DEBUG(initialized);
73+
request = "GET " + uri + " HTTP/1.1\r\nHost: " + host + "\r\n\r\n";
74+
75+
DEBUG(request);
76+
initialized = true;
77+
}
78+
79+
String AsyncHTTPClient::getBody() {
80+
if (statusCode == 200) {
81+
// This is not a good check for chunked transfer encoding - it should ignore case and spaces
82+
int chunkedIndex = response.indexOf("Transfer-Encoding: chunked");
83+
int bodyStart = response.indexOf("\r\n\r\n") + 4;
84+
if (bodyStart <= 3) {
85+
return "";
86+
}
87+
if (chunkedIndex != -1) {
88+
String body;
89+
const char *buf = response.c_str();
90+
int chunkSize = strtol(buf + bodyStart, 0, 16);
91+
while (chunkSize) {
92+
// Move past chunk size
93+
bodyStart = response.indexOf("\r\n", bodyStart) + 2;
94+
body += response.substring(bodyStart, bodyStart + chunkSize);
95+
96+
// Move past chunk
97+
bodyStart = response.indexOf("\r\n", bodyStart + chunkSize) + 2;
98+
chunkSize = strtol(buf + bodyStart, 0, 16);
99+
}
100+
101+
return body;
102+
} else {
103+
return response.substring(bodyStart);
104+
}
105+
} else {
106+
return "";
107+
}
108+
}
109+
110+
void AsyncHTTPClient::clientError(void *arg, AsyncClient *client,
111+
err_t error) {
112+
DEBUG("Connect Error");
113+
AsyncHTTPClient *self = (AsyncHTTPClient*) arg;
114+
self->onFail("Connection error");
115+
self->aClient = NULL;
116+
delete client;
117+
}
118+
119+
void AsyncHTTPClient::clientDisconnect(void *arg, AsyncClient *client) {
120+
DEBUG("Disconnected");
121+
AsyncHTTPClient *self = (AsyncHTTPClient*) arg;
122+
self->aClient = NULL;
123+
delete client;
124+
}
125+
126+
void AsyncHTTPClient::clientData(void *arg, AsyncClient *client, void *data, size_t len) {
127+
DEBUG("Got response");
128+
129+
AsyncHTTPClient *self = (AsyncHTTPClient*) arg;
130+
self->response = ByteString(data, len);
131+
String status = self->response.substring(9, 12);
132+
self->statusCode = atoi(status.c_str());
133+
DEBUG(status.c_str());
134+
135+
if (self->statusCode == 200) {
136+
self->onSuccess();
137+
} else {
138+
self->onFail("Failed with code " + status);
139+
}
140+
}
141+
142+
void AsyncHTTPClient::clientConnect(void *arg, AsyncClient *client) {
143+
DEBUG("Connected");
144+
145+
AsyncHTTPClient *self = (AsyncHTTPClient*) arg;
146+
147+
self->response.copy("", 0);
148+
self->statusCode = -1;
149+
150+
// Clear oneError handler
151+
self->aClient->onError(NULL, NULL);
152+
153+
// Set disconnect handler
154+
client->onDisconnect(clientDisconnect, self);
155+
156+
client->onData(clientData, self);
157+
158+
//send the request
159+
client->write(self->request.c_str());
160+
}
161+
162+
void AsyncHTTPClient::makeRequest(void (*success)(), void (*fail)(String msg)) {
163+
onFail = fail;
164+
165+
if (!initialized) {
166+
fail("Not initialized");
167+
return;
168+
}
169+
170+
if (aClient) { //client already exists
171+
fail("Call taking forever");
172+
return;
173+
}
174+
175+
aClient = new AsyncClient();
176+
if (!aClient) { //could not allocate client
177+
fail("Out of memory");
178+
return;
179+
}
180+
181+
onSuccess = success;
182+
183+
aClient->onError(clientError, this);
184+
185+
aClient->onConnect(clientConnect, this);
186+
bool connected = false;
187+
#if ASYNC_TCP_SSL_ENABLED
188+
if (protocol == "https") {
189+
DEBUG("Creating secure connection");
190+
connected = aClient->connect(host.c_str(), port, true);
191+
} else {
192+
connected = aClient->connect(host.c_str(), port, false);
193+
}
194+
#else
195+
connected = aClient->connect(host.c_str(), port);
196+
#endif
197+
if (!connected) {
198+
DEBUG("Connect Fail");
199+
fail("Connection failed");
200+
AsyncClient * client = aClient;
201+
aClient = NULL;
202+
delete client;
203+
}
204+
}
205+

ESPAsyncHTTPClient.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#ifndef ASYNCHTTPCLIENT_H_
2+
#define ASYNCHTTPCLIENT_H_
3+
#include "Arduino.h"
4+
#ifdef ESP8266
5+
#include "ESPAsyncTCP.h"
6+
#else
7+
#include "AsyncTCP.h"
8+
#endif
9+
#include <base64.h>
10+
11+
#ifndef DEBUG
12+
#define DEBUG(...) {}
13+
#endif
14+
15+
16+
class ByteString: public String {
17+
public:
18+
ByteString(void *data, size_t len) :
19+
String() {
20+
copy(data, len);
21+
}
22+
23+
ByteString() :
24+
String() {
25+
}
26+
27+
String& copy(const void *data, unsigned int length);
28+
};
29+
30+
/**
31+
* Asynchronous HTTP Client
32+
*/
33+
struct AsyncHTTPClient {
34+
AsyncClient *aClient = NULL;
35+
36+
bool initialized = false;
37+
String protocol;
38+
String base64Authorization;
39+
String host;
40+
int port;
41+
String uri;
42+
String request;
43+
44+
ByteString response;
45+
int statusCode;
46+
void (*onSuccess)();
47+
void (*onFail)(String);
48+
49+
void initialize(String url);
50+
int getStatusCode() { return statusCode; }
51+
52+
String getBody();
53+
54+
static void clientError(void *arg, AsyncClient *client, err_t error);
55+
static void clientDisconnect(void *arg, AsyncClient *client);
56+
static void clientData(void *arg, AsyncClient *client, void *data, size_t len);
57+
static void clientConnect(void *arg, AsyncClient *client);
58+
void makeRequest(void (*success)(), void (*fail)(String msg));
59+
};
60+
61+
#endif ASYNCHTTPCLIENT_H_

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 Paul Andrews
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# ESPAsyncHttpClient
2+
A very basic asynchronous HTTP client for the ESP8266 that uses ESPAsyncTCP. it was written for a very specific need, so it is not a truly general class.
3+
4+
This code is provided as-is. I am more than happy for anyone to take it and use it, or turn it into an actual general library.

0 commit comments

Comments
 (0)