1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
9 #include <anna/core/functions.hpp>
10 #include <anna/core/tracing/Logger.hpp>
12 #include <anna/http/parser/ReadHeader.hpp>
14 #include <anna/http/Transport.hpp>
15 #include <anna/http/functions.hpp>
16 #include <anna/http/internal/defines.hpp>
17 #include <anna/http/Header.hpp>
18 #include <anna/http/internal/EncodedBlock.hpp>
23 //----------------------------------------------------------------------------------------------------
24 // Si el mensaje HTTP no contiene la etiqueta content-length => el mensaje se acaba cuando llegue
25 // el primer crlf en solitario, es decir, la primera linea vacia.
27 // (1) El valor que acompania al Header es opcional ... solo verificamos que venga en el caso de
28 // que sea el ContentLength.
29 // (2) Hay una probabilidad muy alta de que la fecha contenga algun ':' asi que hay que tratarlo
30 // de forma distinta al resto de los header.
32 // Recordar que el ContentLength indica la longitud del cuerpo del mensaje (si existe) =>
33 // la longitud total del mensaje sea <la longitud de la cabecera> + <longitud del body>.
35 // (3) version 1.0.5 - El servidor de aplicaciones tomcat envia mensajes HTTP sin el Header Content-Length, con lo que
36 // aplicando la regla de la RFC siempre obtendremos un cuerpo de mensaje vacio.
37 // Segun la RFC cuando no llega este indicador el mensaje termina con los primeros 0xd0xa consecutivos.
38 // Para permitir la interconexion de nuestros sistemas con este servidor de aplicaciones, vamos a modificar el comportamiento
39 // del parser y considerando el fin del mensaje el fin del paquete recibido como parametro.
41 // (4) version 1.0.7 - Los header no reconocidos los guarda como extensiones.
42 //----------------------------------------------------------------------------------------------------
44 int http::parser::ReadHeader::processLine(http::Transport& transport, const DataBlock& dataBlock, const http::Token& line) const
46 if(line.getSize() == 0) { // (3)
47 const int size = line.calculeOffset(dataBlock) + sizeEndOfLine;
48 setState(transport, ClassType::WaitMessage);
52 const Tokenizer& tokenizer = transport.split(line, ':');
54 Tokenizer::const_iterator ii = tokenizer.begin();
56 const Token* token = tokenizer [ii];
58 const Header::Type::_v typeHeader = Header::asType(token);
60 Header* header = NULL;
62 if(typeHeader == Header::Type::None) {
64 string msg("http::parser::ReadHeader::processLine | Unreconized header identifier: ");
65 msg += line.getStringValue();
66 throw RuntimeException(msg, ANNA_FILE_LOCATION);
69 header = transport.getInputMessage()->createHeader(token->getStringValue());
70 } else if(typeHeader != Header::Type::TransferEncoding)
71 header = transport.getInputMessage()->createHeader(typeHeader);
73 token = tokenizer [++ ii]; // (1);
75 if(typeHeader == Header::Type::ContentLength) {
77 throw RuntimeException("http::parser::ReadHeader::processLine | Missing body length at Header ContentLength", ANNA_FILE_LOCATION);
79 transport.setContentLength(token->getIntegerValue());
80 header->setValue(token);
81 setState(transport, ClassType::WaitEndOfHeader);
82 } else if(typeHeader == Header::Type::TransferEncoding) {
83 EncodedBlock* encodedBlock = transport.getEncodedBlock();
86 throw RuntimeException("http::parser::ReadHeader::processLine | Missing encode mode at Transfer-Encoding Header", ANNA_FILE_LOCATION);
88 if(token->match("chunked")) {
89 encodedBlock->setType(EncodedBlock::Type::Chunked);
90 setState(transport, ClassType::WaitChunkSize);
92 } else if(token != NULL) { // (2)
93 const int offset = token->calculeOffset(line);
94 const int size = line.getSize() - offset;
96 date.setValue(line.getData() + offset, size);
97 header->setValue(&date);
99 header->setValue(token); // (4)
101 if(header != NULL && Logger::isActive(Logger::Debug)) {
102 Logger::debug(header->asString(), ANNA_FILE_LOCATION);