Advertisement
Guest User

Untitled

a guest
Jun 16th, 2014
445
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.51 KB | None | 0 0
  1. #include "HttpClient.h"
  2.  
  3. #define LOGGING
  4. #define TIMEOUT 5000 // Allow maximum 5s between data packets.
  5.  
  6. /**
  7. * Constructor.
  8. */
  9. HttpClient::HttpClient()
  10. {
  11.  
  12. }
  13.  
  14. /**
  15. * Method to send a header, should only be called from within the class.
  16. */
  17. void HttpClient::sendHeader(const char* aHeaderName, const char* aHeaderValue)
  18. {
  19.     client.print(aHeaderName);
  20.     client.print(": ");
  21.     client.println(aHeaderValue);
  22.  
  23.     #ifdef LOGGING
  24.     Serial.print(aHeaderName);
  25.     Serial.print(": ");
  26.     Serial.println(aHeaderValue);
  27.     #endif
  28. }
  29.  
  30. void HttpClient::sendHeader(const char* aHeaderName, const int aHeaderValue)
  31. {
  32.     client.print(aHeaderName);
  33.     client.print(": ");
  34.     client.println(aHeaderValue);
  35.  
  36.     #ifdef LOGGING
  37.     Serial.print(aHeaderName);
  38.     Serial.print(": ");
  39.     Serial.println(aHeaderValue);
  40.     #endif
  41. }
  42.  
  43. void HttpClient::sendHeader(const char* aHeaderName)
  44. {
  45.     client.println(aHeaderName);
  46.  
  47.     #ifdef LOGGING
  48.     Serial.println(aHeaderName);
  49.     #endif
  50. }
  51.  
  52. /**
  53. * Method to send an HTTP Request. Allocate variables in your application code
  54. * in the aResponse struct and set the headers and the options in the aRequest
  55. * struct.
  56. */
  57. void HttpClient::request(http_request_t &aRequest, http_response_t &aResponse, http_header_t headers[], const char* aHttpMethod)
  58. {
  59.     // If a proper response code isn't received it will be set to -1.
  60.     aResponse.status = -1;
  61.  
  62.     bool connected = false;
  63.     if(aRequest.hostname!=NULL) {
  64.         connected = client.connect(aRequest.hostname.c_str(), aRequest.port);
  65.     }   else {
  66.         connected = client.connect(aRequest.ip, aRequest.port);
  67.     }
  68.  
  69.  
  70.     #ifdef LOGGING
  71.     if (connected) {
  72.         if(aRequest.hostname!=NULL) {
  73.             Serial.print("HttpClient>\tConnecting to: ");
  74.             Serial.print(aRequest.hostname);
  75.         } else {
  76.             Serial.print("HttpClient>\tConnecting to IP: ");
  77.             Serial.print(aRequest.ip);
  78.         }
  79.         Serial.print(":");
  80.         Serial.println(aRequest.port);
  81.     } else {
  82.         Serial.println("HttpClient>\tConnection failed.");
  83.     }
  84.     #endif
  85.  
  86.     if (!connected) {
  87.         client.stop();
  88.         // If TCP Client can't connect to host, exit here.
  89.         return;
  90.     }
  91.  
  92.     //
  93.     // Send HTTP Headers
  94.     //
  95.  
  96.     // Send initial headers (only HTTP 1.0 is supported for now).
  97.     client.print(aHttpMethod);
  98.     client.print(" ");
  99.     client.print(aRequest.path);
  100.     client.print(" HTTP/1.0\r\n");
  101.  
  102.     #ifdef LOGGING
  103.     Serial.println("HttpClient>\tStart of HTTP Request.");
  104.     Serial.print(aHttpMethod);
  105.     Serial.print(" ");
  106.     Serial.print(aRequest.path);
  107.     Serial.print(" HTTP/1.0\r\n");
  108.     #endif
  109.  
  110.     // Send General and Request Headers.
  111.     sendHeader("Connection", "close"); // Not supporting keep-alive for now.
  112.     if(aRequest.hostname!=NULL) {
  113.         sendHeader("HOST", aRequest.hostname.c_str());
  114.     }
  115.  
  116.     // TODO: Support for connecting with IP address instead of URL
  117.     // if (aRequest.hostname == NULL) {
  118.     //     //sendHeader("HOST", ip);
  119.     // } else {
  120.     //     sendHeader("HOST", aRequest.hostname);
  121.     // }
  122.  
  123.  
  124.     //Send Entity Headers
  125.     // TODO: Check the standard, currently sending Content-Length : 0 for empty
  126.     // POST requests, and no content-length for other types.
  127.     if (aRequest.body != NULL) {
  128.         sendHeader("Content-Length", (aRequest.body).length());
  129.     } else if (strcmp(aHttpMethod, HTTP_METHOD_POST) == 0) { //Check to see if its a Post method.
  130.         sendHeader("Content-Length", 0);
  131.     }
  132.  
  133.     if (headers != NULL)
  134.     {
  135.         int i = 0;
  136.         while (headers[i].header != NULL)
  137.         {
  138.             if (headers[i].value != NULL) {
  139.                 sendHeader(headers[i].header, headers[i].value);
  140.             } else {
  141.                 sendHeader(headers[i].header);
  142.             }
  143.             i++;
  144.         }
  145.     }
  146.  
  147.     // Empty line to finish headers
  148.     client.println();
  149.     client.flush();
  150.  
  151.     //
  152.     // Send HTTP Request Body
  153.     //
  154.  
  155.     if (aRequest.body != NULL) {
  156.         client.println(aRequest.body);
  157.  
  158.         #ifdef LOGGING
  159.         Serial.println(aRequest.body);
  160.         #endif
  161.     }
  162.  
  163.     #ifdef LOGGING
  164.     Serial.println("HttpClient>\tEnd of HTTP Request.");
  165.     #endif
  166.  
  167.     //
  168.     // Receive HTTP Response
  169.     //
  170.     // The first value of client.available() might not represent the
  171.     // whole response, so after the first chunk of data is received instead
  172.     // of terminating the connection there is a delay and another attempt
  173.     // to read data.
  174.     // The loop exits when the connection is closed, or if there is a
  175.     // timeout or an error.
  176.  
  177.     unsigned int bufferPosition = 0;
  178.     unsigned long lastRead = millis();
  179.     unsigned long firstRead = millis();
  180.     bool error = false;
  181.     bool timeout = false;
  182.  
  183.     do {
  184.         #ifdef LOGGING
  185.         int bytes = client.available();
  186.         if(bytes) {
  187.             Serial.print("\r\nHttpClient>\tReceiving TCP transaction of ");
  188.             Serial.print(bytes);
  189.             Serial.println(" bytes.");
  190.         }
  191.         #endif
  192.  
  193.         while (client.available()) {
  194.             char c = client.read();
  195.             #ifdef LOGGING
  196.             Serial.print(c);
  197.             #endif
  198.             lastRead = millis();
  199.  
  200.             if (c == -1) {
  201.                 error = true;
  202.  
  203.                 #ifdef LOGGING
  204.                 Serial.println("HttpClient>\tError: No data available.");
  205.                 #endif
  206.  
  207.                 break;
  208.             }
  209.  
  210.             // Check that received character fits in buffer before storing.
  211.             if (bufferPosition < sizeof(buffer)-1) {
  212.                 buffer[bufferPosition] = c;
  213.             } else if ((bufferPosition == sizeof(buffer)-1)) {
  214.                 buffer[bufferPosition] = '\0'; // Null-terminate buffer
  215.                 client.stop();
  216.                 error = true;
  217.  
  218.                 #ifdef LOGGING
  219.                 Serial.println("HttpClient>\tError: Response body larger than buffer.");
  220.                 #endif
  221.             }
  222.             bufferPosition++;
  223.         }
  224.  
  225.         #ifdef LOGGING
  226.         if (bytes) {
  227.             Serial.print("\r\nHttpClient>\tEnd of TCP transaction.");
  228.         }
  229.         #endif
  230.  
  231.         // Check that there hasn't been more than 5s since last read.
  232.         timeout = millis() - lastRead > TIMEOUT;
  233.  
  234.         // Unless there has been an error or timeout wait 200ms to allow server
  235.         // to respond or close connection.
  236.         if (!error && !timeout) {
  237.             delay(200);
  238.         }
  239.     } while (client.connected() && !timeout && !error);
  240.  
  241.     #ifdef LOGGING
  242.     if (timeout) {
  243.         Serial.println("\r\nHttpClient>\tError: Timeout while reading response.");
  244.     }
  245.     Serial.print("\r\nHttpClient>\tEnd of HTTP Response (");
  246.     Serial.print(millis() - firstRead);
  247.     Serial.println("ms).");
  248.     #endif
  249.     client.stop();
  250.  
  251.     String raw_response(buffer);
  252.  
  253.     // Not super elegant way of finding the status code, but it works.
  254.     String statusCode = raw_response.substring(9,12);
  255.  
  256.     #ifdef LOGGING
  257.     Serial.print("HttpClient>\tStatus Code: ");
  258.     Serial.println(statusCode);
  259.     #endif
  260.  
  261.     int bodyPos = raw_response.indexOf("\r\n\r\n");
  262.     if (bodyPos == -1) {
  263.         #ifdef LOGGING
  264.         Serial.println("HttpClient>\tError: Can't find HTTP response body.");
  265.         #endif
  266.  
  267.         return;
  268.     }
  269.     // Return the entire message body from bodyPos+4 till end.
  270.     aResponse.body = raw_response.substring(bodyPos+4);
  271.     aResponse.status = atoi(statusCode.c_str());
  272. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement