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