Created
May 5, 2016 22:56
-
-
Save DaKaZ/5044f3168412ce0b3f5bf1d46130765e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "RestClient.h" | |
#define HTTP_DEBUG | |
#ifdef HTTP_DEBUG | |
#define HTTP_DEBUG_PRINT(string) (Serial.print(string)) | |
#endif | |
#ifndef HTTP_DEBUG | |
#define HTTP_DEBUG_PRINT(string) | |
#endif | |
RestClient::RestClient(const char* _host){ | |
host = _host; | |
port = 80; | |
fingerprint = NULL; | |
num_headers = 0; | |
contentType = "x-www-form-urlencoded"; // default | |
} | |
RestClient::RestClient(const char* _host, int _port){ | |
host = _host; | |
port = _port; | |
fingerprint = NULL; | |
num_headers = 0; | |
contentType = "x-www-form-urlencoded"; // default | |
} | |
RestClient::RestClient(const char* _host, int _port, const char* _fingerprint){ | |
host = _host; | |
port = _port; | |
fingerprint = _fingerprint; | |
num_headers = 0; | |
contentType = "x-www-form-urlencoded"; // default | |
} | |
// GET path | |
int RestClient::get(const char* path){ | |
return request("GET", path, NULL, NULL); | |
} | |
//GET path with response | |
int RestClient::get(const char* path, String* response){ | |
return request("GET", path, NULL, response); | |
} | |
// POST path and body | |
int RestClient::post(const char* path, const char* body){ | |
return request("POST", path, body, NULL); | |
} | |
// POST path and body with response | |
int RestClient::post(const char* path, const char* body, String* response){ | |
return request("POST", path, body, response); | |
} | |
// PUT path and body | |
int RestClient::put(const char* path, const char* body){ | |
return request("PUT", path, body, NULL); | |
} | |
// PUT path and body with response | |
int RestClient::put(const char* path, const char* body, String* response){ | |
return request("PUT", path, body, response); | |
} | |
// DELETE path | |
int RestClient::del(const char* path){ | |
return request("DELETE", path, NULL, NULL); | |
} | |
// DELETE path and response | |
int RestClient::del(const char* path, String* response){ | |
return request("DELETE", path, NULL, response); | |
} | |
// DELETE path and body | |
int RestClient::del(const char* path, const char* body ){ | |
return request("DELETE", path, body, NULL); | |
} | |
// DELETE path and body with response | |
int RestClient::del(const char* path, const char* body, String* response){ | |
return request("DELETE", path, body, response); | |
} | |
void RestClient::write(const char* string){ | |
if(fingerprint) { | |
HTTP_DEBUG_PRINT("\nSSL Print: "); | |
HTTP_DEBUG_PRINT(string); | |
sslClient.print(string); | |
} else { | |
HTTP_DEBUG_PRINT("\nHTTP Print: "); | |
HTTP_DEBUG_PRINT(string); | |
client.print(string); | |
} | |
} | |
void RestClient::setHeader(const char* header){ | |
headers[num_headers] = header; | |
num_headers++; | |
} | |
void RestClient::setContentType(const char* contentTypeValue){ | |
contentType = contentTypeValue; | |
} | |
// The mother- generic request method. | |
// | |
int RestClient::request(const char* method, const char* path, | |
const char* body, String* response){ | |
HTTP_DEBUG_PRINT("HTTP: connect\n"); | |
if (fingerprint) { | |
if(!sslClient.connect(host, port)){ | |
HTTP_DEBUG_PRINT("HTTPS Connection failed\n"); | |
return 0; | |
} | |
HTTP_DEBUG_PRINT("Verifiying SSL certificate\n"); | |
if (sslClient.verify(fingerprint, host)) { | |
HTTP_DEBUG_PRINT("SSL certificate matches\n"); | |
} else { | |
HTTP_DEBUG_PRINT("SSL certificate does not match\n"); | |
return 0; | |
} | |
} else { | |
if(!client.connect(host, port)){ | |
HTTP_DEBUG_PRINT("HTTP Connection failed\n"); | |
return 0; | |
} | |
} | |
HTTP_DEBUG_PRINT("HTTP: connected\n"); | |
HTTP_DEBUG_PRINT("REQUEST: \n"); | |
// Make a HTTP request line: | |
write(method); | |
write(" "); | |
write(path); | |
write(" HTTP/1.1\r\n"); | |
for(int i=0; i<num_headers; i++){ | |
write(headers[i]); | |
write("\r\n"); | |
} | |
write("Host: "); | |
write(host); | |
write("\r\n"); | |
write("Connection: close\r\n"); | |
if(body != NULL){ | |
char contentLength[30]; | |
sprintf(contentLength, "Content-Length: %d\r\n", strlen(body)); | |
write(contentLength); | |
write("Content-Type: "); | |
write(contentType); | |
write("\r\n"); | |
} | |
write("\r\n"); | |
if(body != NULL){ | |
write(body); | |
write("\r\n"); | |
write("\r\n"); | |
} | |
HTTP_DEBUG_PRINT("\nEND REQUEST\n"); | |
//make sure you write all those bytes. | |
delay(1000); | |
HTTP_DEBUG_PRINT("HTTP: call readResponse\n"); | |
int statusCode = readResponse(response); | |
HTTP_DEBUG_PRINT("HTTP: return readResponse\n"); | |
//cleanup | |
HTTP_DEBUG_PRINT("HTTP: stop client\n"); | |
num_headers = 0; | |
if(fingerprint){ | |
sslClient.stop(); | |
} else { | |
client.stop(); | |
} | |
delay(50); | |
HTTP_DEBUG_PRINT("HTTP: client stopped\n"); | |
return statusCode; | |
} | |
int RestClient::readResponse(String* response) { | |
// an http request ends with a blank line | |
boolean currentLineIsBlank = true; | |
boolean httpBody = false; | |
boolean inStatus = false; | |
char statusCode[4]; | |
int i = 0; | |
int code = 0; | |
if(response == NULL){ | |
HTTP_DEBUG_PRINT("HTTP: NULL RESPONSE POINTER: \n"); | |
}else{ | |
HTTP_DEBUG_PRINT("HTTP: NON-NULL RESPONSE POINTER: \n"); | |
} | |
HTTP_DEBUG_PRINT("HTTP: RESPONSE: \n"); | |
void* http_client; | |
if(fingerprint) { | |
HTTP_DEBUG_PRINT("HTTP: Connect: " + String(sslClient.connected()) + " Available: " + String(sslClient.available()) + "\n"); | |
while (sslClient.connected()) { | |
HTTP_DEBUG_PRINT("."); | |
if (sslClient.available()) { | |
HTTP_DEBUG_PRINT(","); | |
char c = sslClient.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){ | |
//only write response if its not null | |
if(response != NULL) response->concat(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; | |
} | |
} | |
} | |
} | |
HTTP_DEBUG_PRINT("HTTPS client closed \n"); | |
}else { | |
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){ | |
//only write response if its not null | |
if(response != NULL) response->concat(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; | |
} | |
} | |
} | |
} | |
} | |
HTTP_DEBUG_PRINT("HTTP: return readResponse3\n"); | |
return code; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment