Skip to content

Commit d501c6e

Browse files
committed
refactored library to send as one large String
1 parent 5082ca5 commit d501c6e

File tree

2 files changed

+214
-71
lines changed

2 files changed

+214
-71
lines changed

RestClient.cpp

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ RestClient::RestClient(Client& netClient, const char* _host, int _port) {
2525
host = _host;
2626
port = _port;
2727
num_headers = 0;
28-
contentType = "x-www-form-urlencoded"; // default
28+
contentType = "application/x-www-form-urlencoded"; // default
2929
this->client = &netClient;
3030
}
3131

@@ -73,36 +73,36 @@ int RestClient::request(const char* method, String path, String body){
7373
HTTP_DEBUG_PRINT("HTTP: connected\n");
7474
HTTP_DEBUG_PRINT("REQUEST: \n");
7575
// Make a HTTP request line:
76-
client->print(method);
77-
client->print(" ");
78-
client->print(path);
79-
client->println(" HTTP/1.1");
76+
String requestString = method;
77+
requestString += " ";
78+
requestString += path;
79+
requestString += " HTTP/1.1";
80+
requestString += "\n";
8081
for(int i=0; i<num_headers; i++){
81-
client->println(headers[i]);
82+
requestString += headers[i];
83+
requestString += "\n";
8284
}
83-
client->print("Host: ");
84-
client->println(host);
85-
client->println("Connection: close");
86-
87-
// TODO: POST is not sending body right now. Not sure why not
85+
requestString += "Host: ";
86+
requestString += host;
87+
requestString += "\n";
88+
requestString += "Connection: close";
89+
requestString += "\n";
90+
//TODO: deal with binary content
8891
if(body != ""){
89-
//char contentLength[30];
90-
//sprintf(contentLength, "Content-Length: %d", body.length());
91-
client->print("Content-Length: ");
92-
client->println(body.length());
93-
94-
client->print("Content-Type: ");
95-
client->println(contentType);
96-
HTTP_DEBUG_PRINT(body.length());
97-
HTTP_DEBUG_PRINT(contentType);
98-
client->println(); // empty line after headers
99-
client->println(body);
100-
HTTP_DEBUG_PRINT(body);
92+
requestString += "Content-Length: ";
93+
requestString += body.length();
94+
requestString += "\n";
95+
requestString += "Content-Type: ";
96+
requestString += contentType;
97+
requestString += "\n\n";
98+
requestString += body;
99+
requestString += "\n\n";
101100
}
102-
client->println();
101+
client->print(requestString);
102+
103103
// make sure you've sent all bytes. Ugly hack.
104-
// TODO: check output buffer instead
105-
delay(100);
104+
// TODO: check output buffer instead?
105+
delay(50);
106106

107107
HTTP_DEBUG_PRINT("HTTP: call getResponse\n");
108108
int statusCode = getResponse();
@@ -114,7 +114,7 @@ int RestClient::request(const char* method, String path, String body){
114114
if (!client->connected()) {
115115
HTTP_DEBUG_PRINT("HTTP: stop client\n");
116116
num_headers = 0;
117-
client->stop();
117+
//client->stop();
118118
HTTP_DEBUG_PRINT("HTTP: client stopped\n");
119119
}
120120
return statusCode;

RestClient.h

Lines changed: 187 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,190 @@
1-
#include <Arduino.h>
21
#include "Client.h"
2+
#include "RestClient.h"
33

4+
//#define HTTP_DEBUG true
5+
#ifdef HTTP_DEBUG
6+
#define HTTP_DEBUG_PRINT(string) (Serial.print(string))
7+
#endif
48

5-
class RestClient {
6-
7-
public:
8-
RestClient(Client& netClient, const char* _host);
9-
RestClient(Client& netClient, const char* _host, int _port);
10-
11-
//Generic HTTP Request
12-
int request(const char* method, String path, String body);
13-
// Set a Request Header
14-
void setHeader(String);
15-
// Set Content-Type Header
16-
void setContentType(String);
17-
18-
// GET path
19-
int get(const char*);
20-
21-
// POST path and body
22-
int post(const char* path, const char* body);
23-
24-
// PUT path and body
25-
int put(const char* path, const char* body);
26-
27-
// DELETE path
28-
int del(const char*);
29-
// DELETE path and body
30-
int del(const char*, const char*);
31-
// get HTTP response:
32-
String readResponse(){ return responseBody;};
33-
// TO DO: add cookie functions
34-
35-
private:
36-
Client* client;
37-
int getResponse();
38-
// void write(const char*);
39-
const char* host;
40-
int port;
41-
int num_headers;
42-
String headers[10];
43-
String contentType;
44-
String responseBody; // body of the HTTP response
45-
long requestStart; // time the request started
46-
int timeout; // timeout to avoid blocking
47-
};
9+
#ifndef HTTP_DEBUG
10+
#define HTTP_DEBUG_PRINT(string)
11+
#endif
12+
13+
14+
RestClient::RestClient(Client& netClient, const char* _host) {
15+
host = _host;
16+
port = 80;
17+
num_headers = 0;
18+
contentType = "x-www-form-urlencoded"; // default
19+
this->client = &netClient;
20+
this->responseBody = "";
21+
this->timeout = 1000; // default. TODO: add a setter function
22+
}
23+
24+
RestClient::RestClient(Client& netClient, const char* _host, int _port) {
25+
host = _host;
26+
port = _port;
27+
num_headers = 0;
28+
contentType = "application/x-www-form-urlencoded"; // default
29+
this->client = &netClient;
30+
}
31+
32+
// GET path
33+
int RestClient::get(const char* path){
34+
return request("GET", path, "");
35+
}
36+
37+
// POST path and body
38+
int RestClient::post(const char* path, String body){
39+
return request("POST", path, body);
40+
}
41+
42+
// PUT path and body
43+
int RestClient::put(const char* path, String body){
44+
return request("PUT", path, body);
45+
}
46+
47+
// DELETE path
48+
int RestClient::del(const char* path){
49+
return request("DELETE", path, "");
50+
}
51+
52+
// DELETE path and body
53+
int RestClient::del(const char* path, String body ){
54+
return request("DELETE", path, body);
55+
}
56+
57+
void RestClient::setHeader(String header){
58+
headers[num_headers] = header;
59+
num_headers++;
60+
}
61+
62+
void RestClient::setContentType(String contentTypeValue){
63+
contentType = contentTypeValue;
64+
}
65+
66+
// The mother- generic request method.
67+
//
68+
int RestClient::request(const char* method, String path, String body){
69+
70+
HTTP_DEBUG_PRINT("HTTP: connect\n");
71+
72+
if(client->connect(host, port)){
73+
HTTP_DEBUG_PRINT("HTTP: connected\n");
74+
HTTP_DEBUG_PRINT("REQUEST: \n");
75+
// Make a HTTP request line:
76+
String requestString = method;
77+
requestString += " ";
78+
requestString += path;
79+
requestString += " HTTP/1.1";
80+
requestString += "\n";
81+
for(int i=0; i<num_headers; i++){
82+
requestString += headers[i];
83+
requestString += "\n";
84+
}
85+
requestString += "Host: ";
86+
requestString += host;
87+
requestString += "\n";
88+
requestString += "Connection: close";
89+
requestString += "\n";
90+
//TODO: deal with binary content
91+
if(body != ""){
92+
requestString += "Content-Length: ";
93+
requestString += body.length();
94+
requestString += "\n";
95+
requestString += "Content-Type: ";
96+
requestString += contentType;
97+
requestString += "\n\n";
98+
requestString += body;
99+
requestString += "\n\n";
100+
}
101+
client->print(requestString);
102+
103+
// make sure you've sent all bytes. Ugly hack.
104+
// TODO: check output buffer instead?
105+
delay(50);
106+
107+
HTTP_DEBUG_PRINT("HTTP: call getResponse\n");
108+
int statusCode = getResponse();
109+
HTTP_DEBUG_PRINT("HTTP: return getResponse\n");
110+
111+
//cleanup
112+
// only stop if server disconnected. Otherwise you can
113+
// get in an infinite loop in getResponse:
114+
if (!client->connected()) {
115+
HTTP_DEBUG_PRINT("HTTP: stop client\n");
116+
num_headers = 0;
117+
//client->stop();
118+
HTTP_DEBUG_PRINT("HTTP: client stopped\n");
119+
}
120+
return statusCode;
121+
}else{
122+
HTTP_DEBUG_PRINT("HTTP Connection failed\n");
123+
return 0;
124+
}
125+
}
126+
127+
int RestClient::getResponse() {
128+
this->requestStart = millis();
129+
// an http request ends with a blank line
130+
boolean currentLineIsBlank = true;
131+
boolean httpBody = false;
132+
boolean inStatus = false;
133+
// clear response string:
134+
this->responseBody = "";
135+
136+
char statusCode[4];
137+
int i = 0;
138+
int code = 0;
139+
140+
HTTP_DEBUG_PRINT("HTTP: RESPONSE: \n");
141+
while (client->connected()) {
142+
// HTTP_DEBUG_PRINT(".");
143+
if (client->available()) {
144+
// HTTP_DEBUG_PRINT(",");
145+
146+
char c = client->read();
147+
HTTP_DEBUG_PRINT(c);
148+
149+
if(c == ' ' && !inStatus){
150+
inStatus = true;
151+
}
152+
153+
if(inStatus && i < 3 && c != ' '){
154+
statusCode[i] = c;
155+
i++;
156+
}
157+
if(i == 3){
158+
statusCode[i] = '\0';
159+
code = atoi(statusCode);
160+
}
161+
162+
if(httpBody){
163+
// add this char tot the responseBody
164+
this->responseBody += c;
165+
}
166+
else
167+
{
168+
if (c == '\n' && currentLineIsBlank) {
169+
httpBody = true;
170+
}
171+
172+
if (c == '\n') {
173+
// you're starting a new line
174+
currentLineIsBlank = true;
175+
}
176+
else if (c != '\r') {
177+
// you've gotten a character on the current line
178+
currentLineIsBlank = false;
179+
}
180+
}
181+
} else {
182+
// there is a condition where client connects
183+
// and available() always <= 0. So timeout is here to catch that:
184+
if (millis() - this->requestStart > this->timeout) return 0;
185+
}
186+
}
187+
188+
HTTP_DEBUG_PRINT("HTTP: return getResponse3\n");
189+
return code;
190+
}

0 commit comments

Comments
 (0)