Projeto Lógico: Webservice RESTful com JSON no Epos

 

1)   Introdução[edit]

 

Atualmente, na internet, a técnica de comunicação entre sistemas distribuídos que mais ganha força é a REST(Representational State Transfer). REST é a descrição de uma interface web  que utiliza o HTTP e um formato de encapsulamento de dados como JSON ou XML para troca de mensagens sem a necessidade da especificação de um outro protocolo.

 Abaixo estão os princípios de um sistema RESTful retirado do wikipedia:

 

Para encapsular os dados, o formato mais utilizado com REST para comunicação com dispositivos móveis é o JSON, pois possui um menor nível de complexidade para interpretação dos dados.

O OpenEpos não possui suporte por padrão para uma arquitetura RESTful de aplicação web e, dessa forma, proporciona uma oportunidade de trabalho nessa área. Com o desenvolvimento de alguns componentes e aproveitando a já implementação do TCP, pode-se adicionar o suporte a um servidor web com características RESTful ao Epos.

 

 

 

2)   Objetivo[edit]

 

O objetivo do trabalho é desenvolver um webservice RESTful no Epos. Para comprovação do resultado do trabalho, é planejado o desenvolvimento de um sistema que irá informar a temperatura que o mesmo tem armazenado e permitir que o mesmo receba uma temperatura de um dispositivo qualquer externo. Essas características do sistema irão permitir que testes simples possam ser efetivos.

Abaixo estão as características do sistema:

-       Servidor HTTP 1.1.

-       Verificar os pedidos e determinar as respostas de acordo com a especificação do webservice RESTful.

-       JSON Parser para ler dados de pedidos http e JSON Writter para escrever dados no formato JSON para respostas http.

 

 

 

 

3)   Especificação Webservice[edit]

 

1-    Pedido por temperatura

-       Pedido:

-       Resposta:

2-    Recebimento de temperatura

-       Pedido:

-       Resposta:

 

 

4)   Projeto do Desenvolvimento[edit]

 

O projeto será desenvolvido para o OpenEPOS e será feito em cima da implementação do TCP existente. O seguintes componentes foram identificados como necessários:

-       HttpServer

-       HttpServerHandler

-       PathParser

  • Responsável por determinar se um caminho requisitado corresponde a um padrão de caminho pré-determinado. Também irá juntar os argumentos do caminho: um caminho podendo ser "/temperatura/84", o padrão do mesmo seria "/temperatura/*", ou seja, todo asterisco em um padrão de caminho representa um argumento que poderá ser utilizado por um Recurso para responder o pedido.

-       HttpRequest

-       HttpResponse

-       HttpRequestParser

-       HttpResponseWriter

  • Responsável por transformar uma estrutura do tipo HttpResponse em uma String.

-       JSONParser

-       JSONWriter

-       JSONNode

 

4.1)   Diagrama de Classes[edit]

 

 

5)   Diagramas de Sequencia[edit]

 

Os dois diagramas são responsáveis pelo fluxo principal da aplicação e representam os dois casos de uso.

 

 

 

 

6)  Automatos[edit]

6.1) JSON Parser[edit]

 

 

6.2) Http Request Parser[edit]

 

 

 

 

 

 

 

7) Implementacao (andamento)[edit]

7.1) http.h[edit]

 

Responsável pelas estruturas que encapsulam resposta e pedido HTTP, escritor e parser de HTTP, e o HTTPServer, bem como o HTTPServerHandler.

 

#ifndef HTTP_H_

#define HTTP_H_

 

#include<utility/list.h>

#include<utility/path_parser.h>

#include<tcp.h>

#include<utility/string.h>

#include<utility/vector.h>

 

__BEGIN_SYS

 

 

structstring {

       char *_string;

};

 

structrequestLine {

       char *_method;

       char *_requestUri;

       char *_httpVersion;

};

 

structheader {

       char *_name;

       char *_value;

};

 

structstatusLine {

       char *_status;

       char *_httpVersion;

};

 

typedefList_Elements::Doubly_Linked<header> HeaderElement;

typedefList_Elements::Doubly_Linked<string> CharElement;

 

structhttpRequest {

       requestLine_requestLine;

       List<header, HeaderElement> _headers;

       char* _body;

};

 

structhttpResponse {

       statusLine_statusLine;

       List<header, HeaderElement> _headers;

       char* _body;

 

};

 

classHTTPRequestParser {

 

public:

       httpRequest_request;

       bool_parsed;

       HTTPRequestParser(constchar * input) {

             _input = strcpy(_input, input);

             _parsed = false;

             parse();

       }

       httpRequestgetRequest() {return_request;}

       booldidParse() {return_parsed;}

 

private :

       char * _input;

       boolparseRequestLine(char* requestLine);

       boolparseHeaders(char * oneHeader);

       voidparse();

 

};

 

classHTTPResponseWriter {

 

public:

 

       HTTPResponseWriter(httpResponse * httpResponse) {

             _response = newchar[80];

             _httpResponse = httpResponse;

             write();

       }

 

       char* getResponse();

 

private:

       httpResponse * _httpResponse;

       char* _response;

       voidwrite();

 

};

 

classHTTPServer : publicTCP::ServerSocket {

public:

 

       classHTTPServerHandler {

 

       public :

             char * path;

             HTTPServerHandler(constchar * path) {

                    strcpy(this->path, path);

             }

             ~HTTPServerHandler () {};

             virtualhttpResponse * onRequest(httpRequestreq, List<char, PathParser::ArgsElement> * args);

       };

 

       classJsonRestResource {

       public:

             char * path;

 

             JsonRestResource(constchar * path) {

                    strcpy(this->path , path);

             }

             ~JsonRestResource() {}

 

             virtualchar * onRequest(List<char, PathParser::ArgsElement> * args);

       };

 

       classHTTPRestHandler : publicHTTPServerHandler {

 

       public:

             structrestHandler {

                    JsonRestResource * _handler;

                    char* _path;

             };

 

             typedefList_Elements::Doubly_Linked<restHandler> JsonResourceElement;

             List<restHandler, JsonResourceElement> restResources;

 

             HTTPRestHandler(constchar * path) : HTTPServerHandler(path) {}

 

             httpResponse * onRequest(httpRequestreq, List<char, PathParser::ArgsElement> * args) {

 

                    JsonRestResource * selected_handler;

                    PathParser * parsed_path;

 

                    JsonResourceElement *h = restResources.head();

                    db<TCP>(TRC) << "HTTPRestHandler attempting to get resource for request on path=" << req._requestLine._requestUri <<"\n";

                    while(h != 0) {

                           //get path parser to verify if path is compatible

                           PathParser * parser = newPathParser(req._requestLine._requestUri, h->object()->_path);

                           if(parser->didMatch()) {

                                  selected_handler = h->object()->_handler;

                                  parsed_path = parser;

                                  db<TCP>(TRC) << "HTTPRestHandler found resource for request on path=" << req._requestLine._requestUri <<"\n";

                                  break;

                           }

                           h = h->next();

                    }

 

                    httpResponse * response;

                    if(h) {

                           db<TCP>(TRC) << "HTTPRestHandler found resource for request on path=" << req._requestLine._requestUri <<"\n";

                           char * jsonResponse = h->object()->_handler->onRequest(&parsed_path->args);

 

                           db<TCP>(TRC) << "HTTPRestHandler BUILDING RESPONSE\n";

                           //build response for Rest Json web service

 

                           response = newhttpResponse();

 

                           response->_statusLine._httpVersion = newchar[strlen("HTTP/1.1")];

                           strcpy(response->_statusLine._httpVersion, "HTTP/1.1");

                           db<TCP>(TRC) << "HTTPRestHandler setting httpVersion\n";

 

                           response->_statusLine._status = newchar[strlen("200 OK")];

                           strcpy(response->_statusLine._status, "200 OK");

                           db<TCP>(TRC) << "HTTPRestHandler setting statusCode\n";

 

                           response->_body = newchar[strlen(jsonResponse)];

                           strcpy(response->_body, jsonResponse);

                           db<TCP>(TRC) << "HTTPRestHandler setting body\n";

 

 

                           //headers

                           //content len

                           header * contentLenghHeader = new header();

                           contentLenghHeader->_name = newchar[strlen("Content-Length")];

                           strcpy(contentLenghHeader->_name,"Content-Length" );

                           intlenInt = strlen(jsonResponse);

                           char * c = new (&lenInt) char[sizeof(lenInt)];

                           contentLenghHeader->_value = newchar[strlen( c)];

                           strcpy(contentLenghHeader->_value,  c);

                           response->_headers.insert(newHeaderElement(contentLenghHeader));

                           db<TCP>(TRC) << "HTTPRestHandler setting contentLen\n";

 

                           //content type

                           header * contentTypeHeader = new header();

                           contentTypeHeader->_name = newchar[strlen("Content-Type")];

                           strcpy(contentTypeHeader->_name,"Content-Type" );

                           contentTypeHeader->_value = newchar[strlen("application/json")];

                           strcpy(contentTypeHeader->_value, "application/json");

                           response->_headers.insert(newHeaderElement(contentTypeHeader));

                           db<TCP>(TRC) << "HTTPRestHandler did build response on path=" << req._requestLine._requestUri <<"\n";

                           return response;

                    } else {

                           db<TCP>(TRC)  << "HTTPRestHandler resource not found for path=" << req._requestLine._requestUri <<"\n";

                           response = newhttpResponse();

                           response->_statusLine._httpVersion = newchar[strlen("HTTP/1.1")];

                           response->_statusLine._status = newchar[strlen("404 not found")];

                           strcpy(response->_statusLine._httpVersion,"HTTP/1.1");

                           strcpy(response->_statusLine._status,"404 not found");

                           return response;

                    }

             }

 

             booladdHandler(JsonRestResource * h) {

                    //verify if path is already mapped

                    bool possible = true;

                    if(restResources.size() > 0) {

                           JsonResourceElement * element = restResources.head();

                           while(element) {

                                  if(strcmp(element->object()->_path, h->path) == 0) {

                                        possible = true;

                                  }

                                  element = element->next();

                           }

                    }

                    if(possible) {

                           restHandler * ha = newrestHandler();

                           ha->_handler = h;

                           ha->_path = newchar[strlen(h->path)];

                           strcpy(ha->_path, h->path);

                           restResources.insert_tail(newJsonResourceElement(ha));

                           db<TCP>(TRC) << "\nHTTP REST adding handler path=" << ha->_path << " \n";

                    }

                    return possible;

             }

 

             ~HTTPRestHandler() {

                    //do nothing

             }

 

       };

 

       HTTPServer(int port) : TCP::ServerSocket(TCP::Address(tcp()->ip()->address(),port)) {}

 

       structhandler {

             HTTPServerHandler * _handler;

             char* _path;

       };

 

       typedefList_Elements::Doubly_Linked<handler> HandlerElement;

       List<handler, HandlerElement> handlers;

 

       booladdHandler(HTTPServerHandler * h) {

             //verify if path is already mapped

             bool possible = true;

             if(handlers.size() > 0) {

                    HandlerElement * element = handlers.head();

                    while(element) {

                           if(strcmp(element->object()->_path, h->path) == 0) {

                                  possible = true;

                           }

                           element = element->next();

                    }

             }

             if(possible) {

                    handler * ha = new handler();

                    ha->_handler = h;

                    ha->_path = newchar[strlen(h->path)];

                    strcpy(ha->_path, h->path);

                    db<TCP>(TRC) << "\nHTTP adding handler path=" << ha->_path << " \n";

                    handlers.insert_tail(newHandlerElement(ha));

             }

             return possible;

       }

 

       char * receivedLocal(constchar *data,u16 size) {

             received(data, size);

             returnresponse;

       }

 

private:

 

       char* response;

       httpResponse * resourceNotFoundRe;

 

       TCP::Socket* incoming(constTCP::Address& from) {

             //TODO: strategy to accept multiple connections

             returnthis;

       }

 

       voidconnected() {}

 

       voidclosed() {

             listen();

       }

 

       voiderror(short err) {}

 

       voidsent(u16 size) {}

 

       voidreceived(constchar *data,u16 size) {

             //get req from parser

             HTTPRequestParser * parser = newHTTPRequestParser(data);

             if(!parser->_parsed) {

                    return;

             }

 

             httpRequestreq = parser->_request;

 

             HTTPServerHandler * selected_handler;

 

             PathParser * parsed_path;

 

             HandlerElement *h = handlers.head();

             while(h != 0) {

                    //get path parser to verify if path is compatible

                    db<TCP>(TRC) << "\nHTTP testing handler path=" << h->object()->_path << " for path="<< req._requestLine._requestUri << " \n";

                    PathParser * parser = newPathParser(req._requestLine._requestUri, h->object()->_path);

                    if(parser->didMatch()) {

                           selected_handler = h->object()->_handler;

                           parsed_path = parser;

                           db<TCP>(TRC) << "HTTPServer handler found for request on path =" <<req._requestLine._requestUri <<"\n";

                           break;

                    }

                    h = h->next();

             }

 

             httpResponse * res;

             if(selected_handler != 0) {

                    res = selected_handler->onRequest(req, &parsed_path->args);

                    db<TCP>(TRC) << "HTTPServer handler informed response for request on path =" <<req._requestLine._requestUri <<"\n";

             } else {

                    db<TCP>(TRC) << "\nHTTP could not find handler\n";

                    res = resourceNotFoundResponse();

             }

             //get writter to convert response to

             HTTPResponseWriter * wrt = newHTTPResponseWriter(res);

             response = wrt->getResponse();

             db<TCP>(TRC) << "HTTPServer handler responsed=" << response << " for request on path =" <<req._requestLine._requestUri <<"\n";

             send(response, strlen(response));

             close();

       }

 

       httpResponse * resourceNotFoundResponse() {

             if(resourceNotFoundRe == 0) {

                    resourceNotFoundRe = newhttpResponse();

                    resourceNotFoundRe->_statusLine._httpVersion = newchar[strlen("HTTP/1.1")];

                    resourceNotFoundRe->_statusLine._status = newchar[strlen("404 not found")];

                    strcpy(resourceNotFoundRe->_statusLine._httpVersion,"HTTP/1.1");

                    strcpy(resourceNotFoundRe->_statusLine._status,"404 not found");

             }

             returnresourceNotFoundRe;

       }

 

};

 

__END_SYS

 

#endif/* HTTP_H_ */

 

7.2) http.cc[edit]

 

#include<http.h>

 

__BEGIN_SYS

 

boolisspace(char * c);

boolisspace(char  c);

char *trimwhitespace(char *str);

CharElement * createElement(char * p);

 

 

char* HTTPResponseWriter::getResponse() {

       return_response;

}

 

voidHTTPResponseWriter::write() {

       //status line

 

       strcat(_response, _httpResponse->_statusLine._httpVersion);

       db<TCP>(TRC) << "\nHTTP Response Writer response=" << _response << " \n";

       strcat(_response, " ");

       db<TCP>(TRC) << "\nHTTP Response Writer response=" << _response << " \n";

       strcat(_response, _httpResponse->_statusLine._status);

       db<TCP>(TRC) << "\nHTTP Response Writer response=" << _response << " \n";

       strcat(_response,"\r\n");

       db<TCP>(TRC) << "\nHTTP Response Writer response=" << _response << " \n";

       //headers, if any

       if(!_httpResponse->_headers.empty()) {

             HeaderElement * h = _httpResponse->_headers.head();

             while(h) {

                    strcat(_response,h->object()->_name);

                    strcat(_response,":");

                    strcat(_response,h->object()->_value);

                    strcat(_response,"\r\n");

                    h = h->next();

                    db<TCP>(TRC) << "\nHTTP Response Writer response=" << _response << " \n";

             }

       }

       //CRLF

       strcat(_response,"\r\n");

       if(_httpResponse->_body) {

             strcat(_response, _httpResponse->_body);

       }

       db<TCP>(TRC) << "\nHTTP Response Writer response=" << _response << " \n";

 

 

}

 

List<string, CharElement> * split(char * input, constchar * pttr) {

//     char str[] ="This\r\n a \r\nsample\r\n string\r\n";

//       char * pch;

//       pch = strtok(str," ,.-");

//       while (pch != 0)

//       {

//                  db<TCP>(TRC) << "\nSPLIT TEST worked =" <<pch<< "  \n ";

//

//         pch = strtok(0, "\r\n");

//       }

 

       List<string, CharElement> * v = newList<string, CharElement>;

//     char pattern[strlen(pttr)];

//     strcpy(pattern, pttr);

       char *p;

       char inp[strlen(input)];

       strcpy(inp, input);

       p = strtok(inp, pttr);

       if(p != 0) {

             while (p != 0) {

                    if(!isspace(p)) {

                           db<TCP>(TRC) << "\nHTTP did split=" << p << " \n";

                           v->insert_tail(createElement(p));

                    }

                    p = strtok(0, pttr);

 

             }

       } else {

             db<TCP>(TRC) << "\nHTTPcouldnot SPLIT!!\n";

       }

       return v;

 

}

 

CharElement * createElement(char * p){

       string * s = newstring();

       s->_string = newchar[strlen(p)];

       strcpy(s->_string, p);

       CharElement * element = newCharElement(s);

       returnelement;

}

 

boolisspace(char * content) {

       int len1 = strlen(content);

       if(len1 == 0) {

             returntrue;

       }

       char c[len1];

       strcpy(c, content);

       intlen = strlen(c);

       intcount = 0;

       for(int i= 0; i < len; i++) {

             if(isspace(c[i])) {

                    count++;

             }

       }

       if(count == len) {

             returntrue;

       } else {

             returnfalse;

       }

}

 

boolisspace(char c){

       if(c == 0 || c == 0x20 || c == 0x09 || c == 0x0a || c == 0x0b || c == 0x0c || c == 0x0d) {

             returntrue;

       }

       returnfalse;

}

 

 

char *trimwhitespace(char *str)

{

    size_tlen = 0;

    char *frontp = str - 1;

    char *endp = 0;

 

    if( str == 0 )

            return 0;

 

    if( str[0] == '\0' )

            returnstr;

 

    len = strlen(str);

    endp = str + len;

 

    /* Move the front andback pointers toaddress

     * thefirst non-whitespacecharactersfrom

     * each end.

     */

    while( isspace(*(++frontp)) );

    while( isspace(*(--endp)) && endp != frontp );

 

    if( str + len - 1 != endp )

            *(endp + 1) = '\0';

    elseif( frontp != str &&  endp == frontp )

            *str = '\0';

 

    /* Shift thestringsothat it starts atstrso

     * thatifit'sdynamicallyallocated, wecan

     * still free it onthereturned pointer.  Note

     * the reuse ofendptomeanthe front ofthe

     * string buffer now.

     */

    endp = str;

    if( frontp != str )

    {

            while( *frontp ) *endp++ = *frontp++;

            *endp = '\0';

    }

 

 

    returnstr;

}

 

 

//char * trimwhitespace(char *str)

//{

//     char *end;

//

//     // Trimleadingspace

//     while(isspace(str)) str++;

//

//     if(*str == 0)// Allspaces?

//     returnstr;

//

//     // Trimtrailingspace

//     end = str + strlen(str) - 1;

//     while(end > str && isspace(end)) end--;

//

//     // Write new nullterminator

//     *(end+1) = 0;

//

//     returnstr;

//}

 

voidHTTPRequestParser::parse() {

       List<string, CharElement> * allContents = split(_input, "\n");

 

       if(allContents->size() > 0) {

             string * requestLine = allContents->head()->object();

             //ifcant parse requestline, abort

             if(!parseRequestLine(requestLine->_string)) {

                    db<TCP>(TRC) << "\nHTTP:Nao conseguiu fazer o parser do requestline: "<< _input << " \n";

                    return;

             }

 

             //Verifica qntosheaders tem fazendo a comparacao com a linha em branco que antecede o body ou o final.

             CharElement * possibleHeader = allContents->head()->next();

             while(possibleHeader != 0) {

                    db<TCP>(TRC) << "\nHTTP: Processingpossible header <<" << possibleHeader->object()->_string << " \n";

                    string * header = possibleHeader->object();

                    boolparsed = parseHeaders(header->_string);

                    if(!parsed && !possibleHeader->next()) {

                           db<TCP>(TRC) << "\nHTTP: Processingbody <<" << possibleHeader->object()->_string << " \n";

                           strcpy(_request._body,possibleHeader->object()->_string);

                    } elseif(!parsed) {

                           db<TCP>(TRC) << "\nHTTP: Processing header failed= <<" << possibleHeader->object()->_string << " \n";

                           return;

                    }

                    possibleHeader = possibleHeader->next();

 

             }

             _parsed = true;

       }

}

 

boolHTTPRequestParser::parseRequestLine(char* requestLine) {

       db<TCP>(TRC) << "\nHTTP: ParsingRequestLine: "<< requestLine << " \n";

       List<string, CharElement> * requestLineContents = split(requestLine, "  ");

 

       db<TCP>(TRC) << "\nHTTP:Numero de elementos da requestLineContents: "<< requestLineContents->size() << " \n";

       if(requestLineContents->size() == 3) {

             CharElement * method = requestLineContents->head();

             char * methodValue = trimwhitespace(method->object()->_string);

             _request._requestLine._method = newchar[strlen(methodValue)];

             strcpy(_request._requestLine._method, methodValue);

             db<TCP>(TRC) << "\nHTTP: Parsed httpMethod: "<< _request._requestLine._method << " \n";

 

             char * requestUriValue = trimwhitespace(method->next()->object()->_string);

             _request._requestLine._requestUri = newchar[strlen(requestUriValue)];

             strcpy(_request._requestLine._requestUri, requestUriValue);

             db<TCP>(TRC) << "\nHTTP: Parsed requestUri: "<< _request._requestLine._requestUri << " \n";

 

             char * httpVersionValue = trimwhitespace(method->next()->next()->object()->_string);

             _request._requestLine._httpVersion = newchar[strlen(httpVersionValue)];

             strcpy(_request._requestLine._httpVersion, httpVersionValue);

             db<TCP>(TRC) << "\nHTTP: Parsed httpVersion: "<< _request._requestLine._httpVersion << " \n";

             returntrue;

       } else {

             db<TCP>(TRC) << "\nHTTP:FAILED - > Expected 3 But it found requestLineContents: "<< requestLineContents->size() << " \n";

             returnfalse;

       }

 

}

boolHTTPRequestParser::parseHeaders(char * oneHeader) {

       List<string, CharElement> * headerContent = split(oneHeader, ":");

       if(headerContent->size() == 2) {

             header * _header = new header();

 

             char * headerName = trimwhitespace(headerContent->head()->object()->_string);

             _header->_name = newchar[strlen(headerName)];

             strcpy(_header->_name, headerName);

             db<TCP>(TRC) << "\nHTTP: Parsed headername=: "<<_header->_name << " \n";

 

             char* headerValue = trimwhitespace(headerContent->head()->next()->object()->_string);

             _header->_value = newchar[strlen(headerValue)];

             strcpy(_header->_value,headerValue );

             db<TCP>(TRC) << "\nHTTP: Parsed headervalue=: "<<headerValue<< " \n";

 

             _request._headers.insert(newHeaderElement(_header));

             db<TCP>(TRC) << "\nHTTP: Processed header <<" << oneHeader<< " \n";

             returntrue;

       } else {

             db<TCP>(TRC) << "\nHTTP: Processed header failed <<" << oneHeader<< " \n";

             returnfalse;

       }

}

 

__END_SYS

 

7.3) json.h[edit]

 

#ifndef JSONPARSER_H_

#define JSONPARSER_H_

 

#include<utility/list.h>

#include<utility/string.h>

#include<tcp.h>

 

__BEGIN_SYS

 

structjsonNode {

       char * key;

       char * value;

};

 

classJsonParser {

 

private:

       char * string;

 

       voidparse();

       intreadSeparators(int * index, char string[]);

 

 

public:

       boolparsed;

       typedefList_Elements::Doubly_Linked<jsonNode> JsonElement;

       List<jsonNode, JsonElement> nodes;

 

       JsonParser(constchar * input) {

             string = newchar[strlen(input)];

             strcpy(string,input);

             parsed = false;

             parse();

       }

 

       booldidParse();

       List<jsonNode, JsonElement> getNodes();

 

};

 

classJsonWriter {

 

public:

       char * json;

       boolhasValues;

       JsonWriter() {

             strcpy(json, "{");

             hasValues = false;}

 

       voidwrite(constchar * key, constchar * value);

       char* getJson() {

             char temp2[2];

             strcpy(temp2, json);

             returnstrcat(temp2, "}");

       }

 

};

 

__END_SYS

 

#endif/* PATHPARSER_H_ */

 

7.4) json.cc[edit]

 

#include<utility/json.h>

 

__BEGIN_SYS

 

voidincreaseArrayIfNeeded(int index, int size, char * keyTemp){

       if(index >= size){

             char * temp;

             temp = newchar[size+1];

             for(int i =0; i < size; i++){

                    temp[i] = keyTemp[i];

             }

             delete[] keyTemp;

             keyTemp = temp;

       }

}

 

voidincreaseArraySize(int extraSize, int size, char * keyTemp){

       char * temp;

       temp = newchar[size + extraSize];

       for(int i =0; i < size; i++){

             temp[i] = keyTemp[i];

       }

       delete[] keyTemp;

       keyTemp = temp;

}

 

 

voidJsonWriter::write(constchar *key,constchar * value) {

       constchar * DB_QUOTES = "\"";

       constchar * TWO_POINTS = " : ";

       constchar * SEPARATOR = ",";

 

 

       db<TCP>(TRC) << "JsonWriter:: "<< json << "\n";

       if(hasValues) {

             strcat(json,SEPARATOR);

             db<TCP>(TRC) << "JsonWriter:: "<< json << "\n";

       } else {

             hasValues = true;

       }

       strcat(json, DB_QUOTES);

       db<TCP>(TRC) << "JsonWriter:: "<< json << "\n";

       strcat(json, key);

       db<TCP>(TRC) << "JsonWriter:: "<< json << "\n";

       strcat(json, DB_QUOTES);

       db<TCP>(TRC) << "JsonWriter:: "<< json << "\n";

       strcat(json, TWO_POINTS);

       db<TCP>(TRC) << "JsonWriter:: "<< json << "\n";

       strcat(json, DB_QUOTES);

       db<TCP>(TRC) << "JsonWriter:: "<< json << "\n";

       strcat(json, value);

       db<TCP>(TRC) << "JsonWriter:: "<< json << "\n";

       strcat(json, DB_QUOTES);

       db<TCP>(TRC) << "JsonWriter:: "<< json << "\n";

}

 

boolJsonParser::didParse() {

       returnparsed;

}

 

intJsonParser::readSeparators(int * idx, char string[]) {

       int index = *idx;

       while(string[index] == ' ' || string[index] == '\n') {

             index++;

       }

       return index;

}

 

voidJsonParser::parse() {

       db<TCP>(TRC) << "JsonParser::trying to parse "<< string << "\n";

       if (string[0] != '{') {

             db<TCP>(TRC) << "JsonParser::could not parse "<< string << " because json has to start with {" << "\n";

             return;

       }

       bool continuar = true;

       int index = 1;

       while (continuar) {

             index = readSeparators(&index, string);

             char * keyTemp;

             keyTemp = newchar[2];

             char * valueTemp;

             valueTemp = newchar[2];

             db<TCP>(TRC) << "JsonParser:: linha 46= " << index << "=" << string[index] << " \n";

             if (string[index] == '\"') {

                    index++;

                    db<TCP>(TRC) << "JsonParser:: linha 49= " << index << "=" << string[index] <<" \n";

                    while (string[index] != '\"') {

                           char * temp;

                           temp = newchar[1];

                           temp[0] = string[index];

                           strcat(keyTemp, temp);

                           db<TCP>(TRC) << "JsonParser:: linha 52= " << index << "=" << string[index] << " keyTemp=" << keyTemp <<" \n";

                           index++;

                    }

                    index++;

                    index = readSeparators(&index, string);

                    if (string[index] != ':') {

                           db<TCP>(TRC) << "JsonParser::could not parse "<< "=" << string[index] << " because was expecting :" << "\n";

                           return;

                    }

                    index++;

                    index = readSeparators(&index, string);

                    if (string[index] != '\"') {

                           db<TCP>(TRC) << "JsonParser::could not parse "<< "=" << string[index] <<" because was expecting double quotes"<< "\n";

                           return;

                    }

                    index++;

                    db<TCP>(TRC) << "JsonParser:: linha 69= " << index << "=" << string[index] <<" \n";

                    while (string[index] != '\"') {

                           char * temp;

                           temp = newchar[1];

                           temp[0] = string[index];

                           strcat(valueTemp, temp);

                           db<TCP>(TRC) << "JsonParser:: linha 71= " << index << "=" << string[index] << " valueTemp=" << valueTemp <<" \n";

                           index++;

                    }

                    index++;

                    jsonNode * node = new jsonNode();

                    node->value = newchar[strlen(valueTemp)];

                    strcpy(node->value, valueTemp);

                    node->key = newchar[strlen(keyTemp)];

                    strcpy(node->key, keyTemp);

                    delete[] keyTemp;

                    delete[] valueTemp;

                    db<TCP>(TRC) << "JsonParser:: found key=" << node->key << "\n";

                    db<TCP>(TRC) << "JsonParser:: found value=" << node->value << "\n";

                    nodes.insert(new JsonElement(node));

                    index = readSeparators(&index, string);

                    if (string[index] == '}') {

                           continuar = false;

                    } else {

                           if (string[index] == ',') {

                                  //keyTemp = {0};

                                  //valueTemp = {0};

                                  index++;

                           } else {

                                  db<TCP>(TRC) << "JsonParser::error was expecting , but got=" << string[index] << "\n";

                                  return;

                           }

                    }

             } else {

                    db<TCP>(TRC) << "JsonParser::could not parse "<< string << " because was expecting double quotes"<< "\n";

                    return;

             }

       }

       parsed = true;

}

 

__END_SYS

 

7.5) path_parser.h[edit]

 

#ifndef PATHPARSER_H_

#define PATHPARSER_H_

 

#include<utility/list.h>

#include<utility/string.h>

#include<radio.h>

 

__BEGIN_SYS

 

// class should receive a pattern like /temperatura/*, where * means its an argument

// and should receive a path like /temperatura/ or /temperatura/20F

 

classPathParser {

 

public:

       typedef List_Elements::Doubly_Linked<char> ArgsElement;

       List<char*, ArgsElement> args;

 

       PathParser(char * path, char * pattern) {

             this->pattern = newchar[strlen(pattern)];

             strcpy(this->pattern, pattern);

             this->path = newchar[strlen(path)];

             strcpy(this->path, path);

             db<TCP>(TRC) << "\nPathParser:: parsing pattern=" << this->pattern << " for path=" << path << "\n";

             matched = false;

             parse();

 

       }

 

       booldidMatch();

 

private:

       char * path;

       char * pattern;

       boolmatched;

 

       voidparse();

 

};

 

__END_SYS

 

#endif/* PATHPARSER_H_ */

 

7.6) path_parser.cc[edit]

 

#include<utility/path_parser.h>

 

__BEGIN_SYS

 

boolPathParser::didMatch() {

       returnmatched;

}

 

voidPathParser::parse() {

       intpathLen = strlen(path);

       intpatternLen = strlen(pattern);

       if(pathLen >= patternLen && patternLen > 0) {

             intpathIndex = 0;

             intpatternIndex = 0;

 

             if(pattern[patternIndex] == '/') {

                    patternIndex++;

                    if(path[pathIndex] == '/') {

                           pathIndex++;

                    } else {

                           return;

                    }

             } else {

                    return;

             }

             while(patternIndex < patternLen) {

                    //if its not the beginning, verify if its an argument or a path name

                    if(pattern[patternIndex] != '*') { // its a name, we have to match char by char

                           while(pattern[patternIndex] != '/' && patternIndex < patternLen) {

                                  if(pathIndex < pathLen && pattern[patternIndex] == path[pathIndex]) {

                                        pathIndex++;

                                        patternIndex++;

                                  } else {

                                        return;

                                  }

                           }

                    } else { // its an argument

                           if (pathIndex >= pathLen)

                                  return;

                           while(pattern[patternIndex] != '/' && patternIndex < patternLen ) {

                                  char * argument;

                                  int argIndex = 0;

                                  while(path[pathIndex] != '/' && pathIndex < pathLen) {

                                        argument[argIndex] = path[pathIndex];

                                        argIndex++;

                                        pathIndex++;

                                  }

                                  argument[argIndex] = '\0';

                                  patternIndex++;

                                  //store the argument

                                  if(strlen(argument) > 0) {

                                        args.insert(new ArgsElement(argument));

                                  }

                           }

                    }

                    // skip the next '/'

                    if (pattern[patternIndex] == '/' && patternIndex < patternLen) {

                           if (path[pathIndex] == '/') {

                                  pathIndex++;

                                  patternIndex++;

                           } else {

                                  return;

                           }

                    }

             }

             if (patternIndex >= patternLen && pathIndex < pathLen)

                    return;

             matched = true;

       }

}

 

__END_SYS

 

7.7) string.h[edit]

 

 

// EPOS String Utility Declarations

 

 

 

// This work is licensed under the EPOS Software License v1.0.

 

// A copy of this license is available at the EPOS system source tree root.

 

// A copy of this license is also available online at:

 

// http://epos.lisha.ufsc.br/EPOS+Software+License+v1.0

 

// Note that EPOS Software License applies to both source code and executables.

 

 

 

#ifndef __string_h

 

#define __string_h

 

 

 

extern"C" {

 

intmemcmp(constvoid * m1, constvoid * m2, size_t n);

 

void * memcpy(void * d, constvoid * s, size_t n);

 

void * memset(void * m, int c, size_t n);

 

void * memchr(constvoid * m, int c, size_t n);

 

intstrcmp(constchar * s1, constchar * s2);

 

intstrncmp(constchar * s1, constchar * s2, size_t n);

 

char * strcpy(char * d, constchar * s);

 

char * strncpy(char * d, constchar * s, size_t n);

 

char * strcat(char * d, constchar * s);

 

char * strchr(constchar * s, int c);

 

char * strrchr(constchar * s, int c);

 

size_tstrlen(constchar * s);

 

longatol(constchar *s);

 

char *itoa(int v, char *s);

 

intutoa(unsignedlong v, char * d);

 

char * strtok(char *s, constchar *delim);

 

char * strtok_r(char *s, constchar *delim, char **last);

 

}

 

 

 

#endif

 

 

 

7.6) path_parser.cc

8)   Testes de Unidade[edit]

 

 

8.1)  Testes Componentes JSON (json_test.cc)[edit]

8.1.1)  Descricao dos Testes[edit]

 

- Teste 1: Verificar se é possível escrever o JSON Object={"temperatura": "104F"}

-- Componente: JSONWriter

-- Resultados Esperados:

-- JSONWriter.getJson() == {"temperatura": "104F"}

 

- Teste 2: Verficar se é possível ler corretamente o JSON Object={"temperatura": "104F"}

-- Componente: JSONParser

-- JSONParser.getNodes().size == 1

-- JSONParser.getNodes().contains(temperatura)

-- JSONParser.getNodes().get(temperatura).value == "104F"

 

- Teste 3: Verificar se é possível adicionar ao JSON Object inicial o seguinte atributo: "action": "teste"

-- Componente: JSONWriter

-- JSONWriter.getJson() == {"temperatura": "104F", "action": "teste"}

 

- Teste 4: Verificar se é possível ler corretamente o JSON Object={"temperatura": "104F", "action": "teste"}

-- Componente: JSONParser

-- JSONParser.getNodes().size == 2

-- JSONParser.getNodes().contains(temperatura)

-- JSONParser.getNodes().get(temperatura).value == "104F"

-- JSONParser.getNodes().contains(action)

-- JSONParser.getNodes().get(temperatura).value == "teste"

 

8.1.2)  Implementacao dos Testes[edit]

 

#include <utility/ostream.h>

#include <utility/malloc.h>

#include <utility/json.h>

 

__USING_SYS

;

 

voidtest_write_and_parse();

voidexpectedWriterOutput22(char expectedWriterOutput2[]);

voidexpectedWriterOutput1(char expectedWriterOutput[]);

 

OStream cout;

 

intmain() {

 

       cout << "JSON Utility Test\n";

 

       test_write_and_parse();

       cout << "\nDone!\n";

 

       return 0;

}

 

voidexpectedWriterOutput1(char expectedWriterOutput[]) {

       strcat(expectedWriterOutput, "{");

       strcat(expectedWriterOutput, "\"");

       strcat(expectedWriterOutput, "temperatura");

       strcat(expectedWriterOutput, "\"");

       strcat(expectedWriterOutput, " : ");

       strcat(expectedWriterOutput, "\"");

       strcat(expectedWriterOutput, "104F");

       strcat(expectedWriterOutput, "\"");

       strcat(expectedWriterOutput, "}");

}

 

voidexpectedWriterOutput22(char expectedWriterOutput2[]) {

       strcat(expectedWriterOutput2, "{");

       strcat(expectedWriterOutput2, "\"");

       strcat(expectedWriterOutput2, "temperatura");

       strcat(expectedWriterOutput2, "\"");

       strcat(expectedWriterOutput2, " : ");

       strcat(expectedWriterOutput2, "\"");

       strcat(expectedWriterOutput2, "104F");

       strcat(expectedWriterOutput2, "\"");

       strcat(expectedWriterOutput2, ",");

       strcat(expectedWriterOutput2, "\"");

       strcat(expectedWriterOutput2, "action");

       strcat(expectedWriterOutput2, "\"");

       strcat(expectedWriterOutput2, " : ");

       strcat(expectedWriterOutput2, "\"");

       strcat(expectedWriterOutput2, "teste");

       strcat(expectedWriterOutput2, "\"");

       strcat(expectedWriterOutput2, "}");

}

 

voidtest_write_and_parse() {

 

       //test temperatura=104F

       constchar * tempkey = "temperatura";

       constchar * tempvalue = "104F";

 

       cout << "\nTest1!\n";

 

       //write

       JsonWriter * writer = new JsonWriter();

       writer->write(tempkey, tempvalue);

       constchar * writerOutput = writer->getJson();

       cout << "Wrote=" << writerOutput << "\n";

       //build json to compare and read

       char expectedWriterOutput[80];

       expectedWriterOutput1(expectedWriterOutput);

       cout << "Expects=" << expectedWriterOutput << "\n";

 

       if (strcmp(writerOutput, expectedWriterOutput) != 0) {

             cout << "\nDid not Match\n";

       } else {

             cout << "passou 1" << "\n";

       }

 

       //read

       JsonParser * parser = new JsonParser(writerOutput);

       if (parser->didParse()) {

             if (parser->nodes.size() == 1) {

                    cout << "passou 2 \n";

                    jsonNode * node = parser->nodes.head()->object();

                    if (strcmp(node->key, tempkey) != 0

                                  || strcmp(node->value, tempvalue) != 0) {

                           cout << "key=" << node->key << "\n" ;

                           cout << "value=" << node->value << "\n" ;

 

                    } else {

                           cout << "passou 3 \n";

                    }

 

             } else {

                    cout << "\nNode expected:" << tempkey << ":" << tempvalue

                                  << " but none was given \n";

             }

       } else {

             cout << "\nCould not parse\n";

       }

       cout << "\nTest2!\n";

 

       //test temperatura=104F && action=teste

       //write action

       constchar * actionkey = "action";

       constchar * actionvalue = "teste";

       writer->write(actionkey, actionvalue);

       constchar * writerOutput2 = writer->getJson();

       cout << "Wrote=" << writerOutput2 << "\n";

 

       //build json to compare and read

       char expectedWriterOutput2[80];

       expectedWriterOutput22(expectedWriterOutput2);

       cout << "Expects=" << expectedWriterOutput2 << "\n";

 

       if (strcmp(writerOutput2, expectedWriterOutput2) != 0) {

             cout << "\nDid not match\n";

       } else {

             cout << "passou 4\n";

       }

 

       //parse

       JsonParser * parser2 = new JsonParser(writerOutput2);

       if (parser2->didParse()) {

             if (parser2->nodes.size() == 2) {

                    cout << "passou 5 \n";

                    JsonParser::JsonElement * e = parser2->nodes.head();

                    while (e) {

                           jsonNode * node = e->object();

                           cout << "will parse next node \n";

                           cout << "parsed key=" << node->key << "\n";

                           cout << "parsed value=" << node->value << "\n";

                           cout << "parsed=" << node->key << ":" << node->value << "\n";

                           e = e->next();

                           cout << "trying to parse next node \n";

                    }

                    cout << "finished testing nodes \n";

             } else {

                    cout << "\nDid not parse the two values\n";

             }

       } else {

             cout << "\nCould not parse\n";

       }

 

}

 

8.2)   Testes Componentes HTTP (http_test.cc)[edit]

 

8.2.1)   Descricao dos Testes[edit]

 

- Teste 1: Transformar corretamente o pedido HTTP abaixo a um objeto httpRequest correspondente:

-- Componente: HTTPRequestParser

-- Resultados Esperados:

--- httpRequest.requestLine.httpVersion  == HTTP/1.1

--- httpRequest.requestLine.method == GET

--- httpRequest.headers.size == 1

--- httpRequest.headers.contains(Host)

--- httpRequest.headers.get(Host).value == www.google.com

GET / HTTP/1.1

Host: www.google.com

 

Testando

 

 

 

- Teste 2: Transformar corretamente o pedido HTTP abaixo a um objeto httpRequest correspondente:

-- Componente HTTPRequestParser

-- Resultados Esperados:

--- httpRequest.requestLine.httpVersion  == HTTP/1.1

--- httpRequest.requestLine.method == POST

--- httpRequest.requestLine.requestUri == /enlighten/rest

--- httpRequest.headers.size == 2

--- httpRequest.headers.contains(Host)

--- httpRequest.headers.get(Host).value == api.opencalais.com

--- httpRequest.headers.contains(Content-Length)

--- httpRequest.headers.get(Content-Length).value == length

--- httpRequest.body == licenseID=string&content=string&/paramsXML=string

POST /enlighten/rest HTTP/1.1
Host: api.opencalais.com
Content-Type: application/x-www-form-urlencoded
Content-Length: length
 
licenseID=string&content=string&/paramsXML=string
 

 




- Teste 3: Transformar corretamente o objeto httpResponse em uma resposta HTTP descrita abaixo:

-- Componente HTTPResponseWriter

-- Resultados Esperados:

--- HTTPResponseWriter.getResponse() == HTTP/1.1 200 OK\r\n\r\nHello world!\r\n

 

HTTP/1.1 200 OK

 

Hello world!

 

 

 

 

- Teste 4: Transformar corretamente o objeto httpResponse em uma resposta HTTP descrita abaixo:

-- Componente HTTPResponseWriter

-- Resultados Esperados:

--- HTTPResponseWriter.getResponse() == HTTP/1.1 200 OK\r\nContent-Type: text/xmlcharset=utf-8\r\nContent-Length: 8\r\n\r\nTestando\r\n

 

HTTP/1.1 200 OK

Content-Type: text/xml; charset=utf-8

Content-Length: 8

 

Testando

 

 


8.2.2)   Implementacao dos Testes[edit]

 

#include<utility/ostream.h>

#include<utility/malloc.h>

#include<http.h>

 

__USING_SYS

;

 

voidtest_parser();

voidtest_parser2();

 

voidtest_writer();

voidtest_writer2();

 

OStream cout;

 

intmain() {

 

       cout << "HTTP Utilities Test\n";

 

       cout << "\nTesting Parser!\n";

       test_parser();

       cout << "\nDone test parse 1!\n";

       test_parser2();

       cout << "\nDone test parse 2!\n";

 

       cout << "\nTesting Writer!\n";

       test_writer();

       cout << "\nDone test writer 1!\n";

       test_writer2();

       cout << "\nDone test writer 2!\n";

 

       return 0;

}

 

voidtest_parser() {

 

       char request_msg[80] = "GET / HTTP/1.1";

       cout << "\nMsg=" << request_msg;

       strcat(request_msg, "\r\n");

 

       strcat(request_msg, "Host: www.google.com");

       strcat(request_msg, "\r\n");

 

       strcat(request_msg, "\r\n");

 

       cout << "\nTesting\n ";

       cout << request_msg;

 

       HTTPRequestParser * parser = new HTTPRequestParser(request_msg);

       if (parser->didParse()) {

             httpRequest req = parser->getRequest();

             if (strcmp(req._requestLine._httpVersion, "HTTP/1.1") != 0) {

                    cout << "\nCould not parse version expected=" << "HTTP/1.1"

                                  << " but got=" << req._requestLine._httpVersion << "\n ";

             } else {

                    cout << "\nPassou httpVersion\n";

             }

 

             if (strcmp(req._requestLine._method, "GET") != 0) {

                    cout << "\nCould not parse version expected=" << "GET"

                                  << " but got=" << req._requestLine._method << "\n ";

             } else {

                    cout << "\nPassou method\n";

             }

 

             if (strcmp(req._requestLine._requestUri, "/") != 0) {

                    cout << "\nCould not parse version expected=" << "/" << " but got="

                                  << req._requestLine._requestUri << "\n ";

             } else {

                    cout << "\nPassou requestUri\n";

             }

 

             if (req._headers.size() == 1) {

                    HeaderElement * h = req._headers.head();

                    if (strcmp(h->object()->_name, "Host") != 0) {

                           cout << "\nCould not parse header expected=" << "Host"

                                        << " but got=" << h->object()->_name << "\n ";

                    } else {

                           cout << "\nPassou header Host\n";

                    }

                    if (strcmp(h->object()->_value, "www.google.com") != 0) {

                           cout << "\nCould not parse header expected="

                                        << " www.google.com" << " but got="

                                        << h->object()->_value << " eol\n ";

                    } else {

                           cout << "\nPassou header Host valor\n";

                    }

             } else {

                    cout << "\nCould not parse headers expected=" << 1 << " but got="

                                  << req._headers.size() << "\n ";

             }

 

       } else {

             cout << "\nCould not parse msg" << "\n ";

       }

 

}

 

voidtest_parser2() {

 

       char request_msg[80] = "POST /enlighten/calais.asmx/Enlighten HTTP/1.1";

       cout << "\nMsg=" << request_msg;

       strcat(request_msg, "\r\n");

 

       strcat(request_msg, "Host: api.opencalais.com");

       strcat(request_msg, "\r\n");

 

       strcat(request_msg, "Content-Type: application/x-www-form-urlencoded");

       strcat(request_msg, "\r\n");

 

       strcat(request_msg, "Content-Length: 34");

       strcat(request_msg, "\r\n");

 

       strcat(request_msg, "\r\n");

 

       strcat(request_msg, "licenseID=string&content=string&paramsXML=string");

       strcat(request_msg, "\r\n");

 

       cout << "\nTesting2" << request_msg;

 

       HTTPRequestParser * parser = new HTTPRequestParser(request_msg);

       if (parser->didParse()) {

             httpRequest req = parser->getRequest();

             if (strcmp(req._requestLine._httpVersion, "HTTP/1.1") != 0) {

                    cout << "\nCould not parse version expected=" << "HTTP/1.1"

                                  << " but got=" << req._requestLine._httpVersion;

             }

 

             if (strcmp(req._requestLine._method, "POST") != 0) {

                    cout << "\nCould not parse version expected=" << "POST"

                                  << " but got=" << req._requestLine._method;

             }

 

             if (strcmp(req._requestLine._requestUri, "/enlighten/calais.asmx/Enlighten") != 0) {

                    cout << "\nCould not parse version expected="

                                  << "/enlighten/calais.asmx/Enlighten" << " but got="

                                  << req._requestLine._requestUri;

             }

             if (req._headers.size() == 3) {

                    HeaderElement * he = req._headers.head();

                    header * h = he->object();

                    if (strcmp(h->_name , "Host")) {

                           cout << "\nCould not parse header expected=" << "Host"

                                        << " but got=" << h->_name;

                    }

                    if (strcmp(h->_value, "api.opencalais.com") != 0) {

                           cout << "\nCould not parse header expected="

                                        << "api.opencalais.com" << " but got=" << h->_value;

                    }

 

                    he = he->next();

                    h = he->object();

                    if (strcmp(h->_name, "Content-Type") != 0) {

                           cout << "\nCould not parse header expected=" << "Content-Type"

                                        << " but got=" << h->_name;

                    }

                    if (strcmp(h->_value, "application/x-www-form-urlencoded") != 0) {

                           cout << "\nCould not parse header expected="

                                        << "application/x-www-form-urlencoded" << " but got="

                                        << h->_value;

                    }

 

                    he = he->next();

                    h = he->object();

                    if (strcmp(h->_name, "Content-Length") != 0) {

                           cout << "\nCould not parse header expected=" << "Content-Length"

                                        << " but got=" << h->_name;

                    }

                    if (strcmp(h->_value, "34") != 0) {

                           cout << "\nCould not parse header expected=" << "34"

                                        << " butgot=" << h->_value;

                    }

 

             } else {

                    cout << "\nCould not parse headers expected=" << 1 << " but got="

                                  << req._headers.size();

             }

 

 

             //if (strcmp(req._body, "licenseID=string&content=string&paramsXML=string") != 0) {

             //     cout << "\nCould not read body expected="

             //                  << "licenseID=string&content=string&paramsXML=string";

             //     cout   << "\n but got=" << req._body;

 

             //}

 

       } else {

             cout << "\nCould not parse msg=" << request_msg;

       }

 

}

 

voidtest_writer() {

       constchar * response_msg = "HTTP/1.1 200 OK\r\n\r\nHello world!\r\n";

 

       cout << "\nTesting" << response_msg;

       httpResponse * res = new httpResponse();

       cout << "\nCriou o response";

       strcpy(res->_body, "Hello world!");

       strcpy(res->_statusLine._httpVersion, "HTTP/1.1");

       strcpy(res->_statusLine._status, "200");

 

       cout << "\nTerminou de montar o response";

 

       HTTPResponseWriter * writer = newHTTPResponseWriter(res);

       cout << "\nCriou o writer";

       constchar * writer_response = writer->getResponse();

       if (strcmp(writer_response, response_msg) != 0) {

             cout << "\nWriter Ok=" << writer_response;

       } else {

             cout << "\nCould not write msg=" << response_msg << " got="

                           << writer_response;

       }

       cout << "\nTerminou de montar o writer";

}

 

voidtest_writer2() {

       char response_msg[80] = "HTTP/1.1 200 OK";

       strcat(response_msg, "\r\n");

 

       strcat(response_msg, "Content-Type: text/xml; charset=utf-8");

       strcat(response_msg, "\r\n");

 

       strcat(response_msg, "Content-Length: 8");

       strcat(response_msg, "\r\n");

 

       strcat(response_msg, "\r\n");

 

       strcat(response_msg, "testando");

       strcat(response_msg, "\r\n");

 

       cout << "\nTesting" << response_msg;

 

       httpResponse * res = new httpResponse();

       strcpy(res->_body, "testando");

       strcpy(res->_statusLine._httpVersion, "HTTP/1.1");

       strcpy(res->_statusLine._status, "200");

       List<header, HeaderElement> * headers = newList<header, HeaderElement>();

 

       header * type = new header();

       strcpy(type->_name, "Content-Type");

       strcpy(type->_value, "text/xml; charset=utf-8");

       headers->insert(newHeaderElement(type));

 

       header * length = new header();

       strcpy(type->_name, "Content-Length");

       strcpy(type->_value, "8");

       headers->insert(newHeaderElement(length));

 

       res->_headers = *headers;

       strcpy(res->_body, "testando");

 

       HTTPResponseWriter * writer = new HTTPResponseWriter(res);

       constchar * writer_response = writer->getResponse();

       if (strcmp(writer_response, response_msg) != 0) {

             cout << "\nWriter Ok=" << writer_response;

       } else {

             cout << "\nCould not write msg=" << response_msg << " got="

                           << writer_response;

       }

 

}

 

 

9) Teste Integracao[edit]

 

9.1)   Descricao do Teste[edit]

 

Nesse teste o objetivo é utilizar todos os componentes criados. A ideia é fazer um web service para atender a pedidos de temperatura.

 

 

 - Teste : Fazer pedido para /temperatura e receber uma resposta com um JSON:

- Componentes Utilizados:

--- HTTPRequestParser (ler o pedido HTTP)

--- HTTPResponseWriter (escrever o pedido HTTP)

--- HTTPServer (Receber o pedido e mandar para um HTTPHandler, se o pedido for válido e existir um Handler para o "PATH" requisitado)

--- HTTPRestHandler (responsavel por mapear todos os recursos para o seu "PATH", irá montar a resposta baseado na resposta do Recurso)

--- TemperaturaJSONResource (recurso responsável por responder o valor em JSON para o pedido)

--- PathParser (irá verificar se o PATH informado está compatível com o PADRÃO esperado)

- Resultados Esperados:

-- Espera-se receber uma resposta HTTP da seguinte forma:

--- HTTP OK

--- Header: Content-Type=application/json

--- Header: Content-Lenght

--- Body={"temperatura":"104F"}

 

 

9.2)   Implementacao do Teste[edit]

 

#include<utility/ostream.h>

#include<utility/malloc.h>

#include<http.h>

#include<utility/json.h>

 

__USING_SYS

 

OStream cout;

HTTPServer * server;

 

classTemperaturaJsonRestResource: publicHTTPServer::JsonRestResource {

public:

TemperaturaJsonRestResource(constchar * path) :

JsonRestResource(path) {

 

}

 

char * onRequest(List<char, PathParser::ArgsElement> * args) {

JsonWriter * writer = new JsonWriter();

constchar * tempKey = "temperatura";

constchar * tempValue = "104F";

writer->write(tempKey, tempValue);

char * response = writer->getJson();

cout << "Temperatura Resource Response=" << response << "\n";

return response;

}

};

 

intmain() {

 

cout << "HTTP Integration Test\n";

 

server = new HTTPServer(80);

constchar * path = "/temperatura";

HTTPServer::HTTPRestHandler * handler = newHTTPServer::HTTPRestHandler(

path);

TemperaturaJsonRestResource * resource = new TemperaturaJsonRestResource(

path);

handler->addHandler(resource);

server->addHandler(handler);

 

constchar * request_msg = "GET /temperatura HTTP/1.1";

char * response = server->receivedLocal(request_msg, strlen(request_msg));

 

cout << response << "\n ";

 

return 0;

 

}

10)  Link para Projeto (Imagens ...)[edit]

 

http://www.gliffy.com/pubdoc/3601660/L.png

 

10)  Referências[edit]

 

HTTP

http://www.w3.org/Protocols/rfc2616/rfc2616.html

 

JSON

http://www.ietf.org/rfc/rfc4627.txt

 

REST

http://pt.wikipedia.org/wiki/REST

Tags:

Código

so2.tar.gz