Skip to content

Commit 62632fe

Browse files
author
Massimo Banzi
committed
First commit
adding modified code
0 parents  commit 62632fe

File tree

7 files changed

+698
-0
lines changed

7 files changed

+698
-0
lines changed

LICENSE.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) [year] [fullname]
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy of
6+
this software and associated documentation files (the "Software"), to deal in
7+
the Software without restriction, including without limitation the rights to
8+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9+
the Software, and to permit persons to whom the Software is furnished to do so,
10+
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, FITNESS
17+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# Warning
2+
3+
Documentation needs to be updated because of massive changes in API
4+
5+
I have changed the original code to allow the library to be used with any network connection
6+
7+
# RestClient for Arduino
8+
9+
HTTP Request library for Arduino derived from https://github.com/csquared/arduino-restclient
10+
11+
# Usage
12+
13+
### Include
14+
15+
16+
17+
```c++
18+
#include <Ethernet.h>
19+
#include <SPI.h>
20+
#include "RestClient.h"
21+
```
22+
23+
### RestClient(host/ip, [port])
24+
25+
Constructor to create an RestClient object to make requests against.
26+
27+
Use domain name and default to port 80:
28+
```c++
29+
RestClient client = RestClient("arduino-http-lib-test.herokuapp.com");
30+
```
31+
32+
Use a local IP and an explicit port:
33+
```c++
34+
RestClient client = RestClient("192.168.1.50",5000);
35+
```
36+
37+
### dhcp()
38+
39+
Sets up `EthernetClient` with a mac address of `DEADBEEFFEED`
40+
41+
```c++
42+
client.dhcp()
43+
```
44+
45+
Note: you can have multiple RestClient objects but only need to call
46+
this once.
47+
48+
Note: if you have multiple Arduinos on the same network, you'll need
49+
to give each one a different mac address.
50+
51+
### begin(byte mac[])
52+
53+
It just wraps the `EthernetClient` call to `begin` and DHCPs.
54+
Use this if you need to explicitly set the mac address.
55+
56+
```c++
57+
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
58+
if (client.begin(mac) == 0) {
59+
Serial.println("Failed to configure Ethernet using DHCP");
60+
}
61+
```
62+
63+
### Manual Ethernet Setup
64+
65+
You can skip the above methods and just configure the EthernetClient yourself:
66+
67+
```c++
68+
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
69+
//the IP address for the shield:
70+
byte ip[] = { 192, 168, 2, 11 };
71+
Ethernet.begin(mac,ip);
72+
```
73+
74+
```c++
75+
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
76+
Ethernet.begin(mac);
77+
```
78+
79+
This is especially useful for debugging network connection issues.
80+
81+
## RESTful methods
82+
83+
All methods return an HTTP status code or 0 if there was an error.
84+
85+
### `get(const char* path)`
86+
### `get(const char* path, String* response)`
87+
88+
Start making requests!
89+
90+
```c++
91+
int statusCode = client.get("/"));
92+
```
93+
94+
Pass in a string *by reference* for the response:
95+
```
96+
String response = "";
97+
int statusCode = client.get("/", &response);
98+
```
99+
100+
### post(const char* path, const char* body)
101+
### post(const char* path, String* response)
102+
### post(const char* path, const char* body, String* response)
103+
104+
```
105+
String response = "";
106+
int statusCode = client.post("/", &response);
107+
statusCode = client.post("/", "foo=bar");
108+
response = "";
109+
statusCode = client.post("/", "foo=bar", &response);
110+
```
111+
112+
### put(const char* path, const char* body)
113+
### put(const char* path, String* response)
114+
### put(const char* path, const char* body, String* response)
115+
116+
```
117+
String response = "";
118+
int statusCode = client.put("/", &response);
119+
statusCode = client.put("/", "foo=bar");
120+
response = "";
121+
statusCode = client.put("/", "foo=bar", &response);
122+
```
123+
124+
### del(const char* path)
125+
### del(const char* path, const char* body)
126+
### del(const char* path, String* response)
127+
### del(const char* path, const char* body, String* response)
128+
129+
```
130+
String response = "";
131+
int statusCode = client.del("/", &response);
132+
```
133+
134+
## Full Example
135+
136+
I test every way of calling the library (against a public heroku app)[https://github.com/csquared/arduino-http-test].
137+
138+
You can find the file in File->Examples->RestClient->full_test_suite
139+
140+
## Debug Mode
141+
142+
If you're having trouble, you can always open `RestClient.cpp` and throw at the top:
143+
144+
```c++
145+
#define HTTP_DEBUG
146+
```
147+
148+
Everything happening in the client will get printed to the Serial port.
149+
150+
# Thanks
151+
152+
[ricardochimal](https://github.com/ricardochimal) For all his c++ help. Couldn't have done this without you!
153+
154+
[theycallmeswift](https://github.com/theycallmeswift) Helping incept and debug v1.0

RestClient.cpp

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
#include "Client.h"
2+
#include "RestClient.h"
3+
4+
#ifdef HTTP_DEBUG
5+
#define HTTP_DEBUG_PRINT(string) (Serial.print(string))
6+
#endif
7+
8+
#ifndef HTTP_DEBUG
9+
#define HTTP_DEBUG_PRINT(string)
10+
#endif
11+
12+
13+
RestClient::RestClient(Client& netClient, const char* _host) {
14+
host = _host;
15+
port = 80;
16+
num_headers = 0;
17+
contentType = "x-www-form-urlencoded"; // default
18+
this->client = &netClient;
19+
}
20+
21+
RestClient::RestClient(Client& netClient, const char* _host, int _port) {
22+
host = _host;
23+
port = _port;
24+
num_headers = 0;
25+
contentType = "x-www-form-urlencoded"; // default
26+
this->client = &netClient;
27+
}
28+
29+
30+
31+
32+
// GET path
33+
int RestClient::get(const char* path){
34+
return request("GET", path, NULL, NULL);
35+
}
36+
37+
//GET path with response
38+
int RestClient::get(const char* path, String* response){
39+
return request("GET", path, NULL, response);
40+
}
41+
42+
// POST path and body
43+
int RestClient::post(const char* path, const char* body){
44+
return request("POST", path, body, NULL);
45+
}
46+
47+
// POST path and body with response
48+
int RestClient::post(const char* path, const char* body, String* response){
49+
return request("POST", path, body, response);
50+
}
51+
52+
// PUT path and body
53+
int RestClient::put(const char* path, const char* body){
54+
return request("PUT", path, body, NULL);
55+
}
56+
57+
// PUT path and body with response
58+
int RestClient::put(const char* path, const char* body, String* response){
59+
return request("PUT", path, body, response);
60+
}
61+
62+
// DELETE path
63+
int RestClient::del(const char* path){
64+
return request("DELETE", path, NULL, NULL);
65+
}
66+
67+
// DELETE path and response
68+
int RestClient::del(const char* path, String* response){
69+
return request("DELETE", path, NULL, response);
70+
}
71+
72+
// DELETE path and body
73+
int RestClient::del(const char* path, const char* body ){
74+
return request("DELETE", path, body, NULL);
75+
}
76+
77+
// DELETE path and body with response
78+
int RestClient::del(const char* path, const char* body, String* response){
79+
return request("DELETE", path, body, response);
80+
}
81+
82+
void RestClient::write(const char* string){
83+
HTTP_DEBUG_PRINT(string);
84+
client->print(string);
85+
}
86+
87+
void RestClient::setHeader(const char* header){
88+
headers[num_headers] = header;
89+
num_headers++;
90+
}
91+
92+
void RestClient::setContentType(const char* contentTypeValue){
93+
contentType = contentTypeValue;
94+
}
95+
96+
// The mother- generic request method.
97+
//
98+
int RestClient::request(const char* method, const char* path,
99+
const char* body, String* response){
100+
101+
HTTP_DEBUG_PRINT("HTTP: connect\n");
102+
103+
if(client->connect(host, port)){
104+
HTTP_DEBUG_PRINT("HTTP: connected\n");
105+
HTTP_DEBUG_PRINT("REQUEST: \n");
106+
// Make a HTTP request line:
107+
write(method);
108+
write(" ");
109+
write(path);
110+
write(" HTTP/1.1\r\n");
111+
for(int i=0; i<num_headers; i++){
112+
write(headers[i]);
113+
write("\r\n");
114+
}
115+
write("Host: ");
116+
write(host);
117+
write("\r\n");
118+
write("Connection: close\r\n");
119+
120+
if(body != NULL){
121+
char contentLength[30];
122+
sprintf(contentLength, "Content-Length: %d\r\n", strlen(body));
123+
write(contentLength);
124+
125+
write("Content-Type: ");
126+
write(contentType);
127+
write("\r\n");
128+
}
129+
130+
write("\r\n");
131+
132+
if(body != NULL){
133+
write(body);
134+
write("\r\n");
135+
write("\r\n");
136+
}
137+
138+
//make sure you write all those bytes.
139+
delay(100);
140+
141+
HTTP_DEBUG_PRINT("HTTP: call readResponse\n");
142+
int statusCode = readResponse(response);
143+
HTTP_DEBUG_PRINT("HTTP: return readResponse\n");
144+
145+
//cleanup
146+
HTTP_DEBUG_PRINT("HTTP: stop client\n");
147+
num_headers = 0;
148+
client->stop();
149+
delay(50);
150+
HTTP_DEBUG_PRINT("HTTP: client stopped\n");
151+
152+
return statusCode;
153+
}else{
154+
HTTP_DEBUG_PRINT("HTTP Connection failed\n");
155+
return 0;
156+
}
157+
}
158+
159+
int RestClient::readResponse(String* response) {
160+
161+
// an http request ends with a blank line
162+
boolean currentLineIsBlank = true;
163+
boolean httpBody = false;
164+
boolean inStatus = false;
165+
166+
char statusCode[4];
167+
int i = 0;
168+
int code = 0;
169+
170+
if(response == NULL){
171+
HTTP_DEBUG_PRINT("HTTP: NULL RESPONSE POINTER: \n");
172+
}else{
173+
HTTP_DEBUG_PRINT("HTTP: NON-NULL RESPONSE POINTER: \n");
174+
}
175+
176+
HTTP_DEBUG_PRINT("HTTP: RESPONSE: \n");
177+
while (client->connected()) {
178+
HTTP_DEBUG_PRINT(".");
179+
180+
if (client->available()) {
181+
HTTP_DEBUG_PRINT(",");
182+
183+
char c = client->read();
184+
HTTP_DEBUG_PRINT(c);
185+
186+
if(c == ' ' && !inStatus){
187+
inStatus = true;
188+
}
189+
190+
if(inStatus && i < 3 && c != ' '){
191+
statusCode[i] = c;
192+
i++;
193+
}
194+
if(i == 3){
195+
statusCode[i] = '\0';
196+
code = atoi(statusCode);
197+
}
198+
199+
if(httpBody){
200+
//only write response if its not null
201+
if(response != NULL) response->concat(c);
202+
}
203+
else
204+
{
205+
if (c == '\n' && currentLineIsBlank) {
206+
httpBody = true;
207+
}
208+
209+
if (c == '\n') {
210+
// you're starting a new line
211+
currentLineIsBlank = true;
212+
}
213+
else if (c != '\r') {
214+
// you've gotten a character on the current line
215+
currentLineIsBlank = false;
216+
}
217+
}
218+
}
219+
}
220+
221+
HTTP_DEBUG_PRINT("HTTP: return readResponse3\n");
222+
return code;
223+
}

0 commit comments

Comments
 (0)