dodo  0.0.1
A C++ library to create containerized Linux services
httpfragment.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of the dodo library (https://github.com/jmspit/dodo).
3  * Copyright (c) 2019 Jan-Marten Spit.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 
19 /**
20  * @file httpfragment.hpp
21  * Defines the dodo::network::protocol::http::HTTPFragment class.
22  */
23 
24 #ifndef dodo_network_protocol_http_httpfragment_hpp
25 #define dodo_network_protocol_http_httpfragment_hpp
26 
28 #include <string>
29 
30 namespace dodo {
31 
32  namespace network::protocol::http {
33 
34 
35 
36  /**
37  * Generic HTTP fragment, either a complete (such as HTTPRequest) or incomplete
38  * HTTP fragment (ssuch as a HTTPRequest::HTTPRequestLine) . Descendant classes implement
39  * ParseResult parse( VirtualReadBuffer& buffer ) to extract a complete HTTP fragment.
40  * Note that the buffer is expected to be blocking on reads, if the HTTPFragment
41  * expects more data it will wait and in case of a read timeout, fail. If the parse
42  * fails due to incomplete data within the timeout, the ParseResult return value is
43  * `{ peSystemError, common::SystemError::ecEAGAIN }`.
44  */
45  class HTTPFragment {
46  public:
47 
48  /**
49  * Parse results returned by the parse functions.
50  */
51  enum ParseError : unsigned int {
52  peOk = 0, /**< Ok */
53  peIncomplete, /**< Not an error, but more data is expected to complete */
54  peSystemError, /**< The parse failed due to system error SocketReadBuffer::getLastError() */
55  peExpectCRLF, /**< A CR was not followed by an LF */
56  peUnFinishedToken, /**< A token is being parsed but is ending erroneously */
57  peExpectingHeaderColon, /**< A header field name was read, but no colon found after it. */
58  peInvalidHeaderFieldValue, /**< A header field value was being read, but it is invalid. */
59  peInvalidHeaderListEnd, /**< A header list is not ending properly. */
60  peInvalidMethod, /**< An invalid method was specified in the request line. */
61  peInvalidHTTPVersion, /**< An invalid HTTP version was specified in the request line. */
62  peInvalidRequestLine, /**< The request line is invalid. */
63  peInvalidContentLength, /**< The content length does not match the message body size. */
64  peUnexpectedBody, /**< A message body is present but should not be there. */
65  peInvalidTransferEncoding, /**< The specified transfer-encoding header is invalid. */
66  peInvalidChunkHex, /**< The hex chunk size is invalid. */
67  peInvalidLastChunk, /**< The last chunk does not have size 0. */
68  peExpectingUnsignedInt, /**< An unsigned int was expected. */
69  };
70 
71  /**
72  * Used to convey parsing succces. If parseError is peOk, the parse was succesfull.
73  * If parseError == peSystemError, systemError will be set to something else then SystemError::ecOK.
74  */
75  struct ParseResult {
76 
77  /**
78  * Default constructor sets to `{ parseError = peOk; systemError = common::SystemError::ecOK; }`
79  */
81 
82  /**
83  * Explicit constructor.
84  * @param pe The ParseError to set.
85  * @param se The SystemError to set.
86  */
88 
89  /**
90  * Test if `parseError == peOk && systemError == common::SystemError::ecOK`.
91  * @return true when all is well.
92  */
93  bool ok() const { return parseError == peOk && systemError == common::SystemError::ecOK; }
94 
95  /**
96  * Test if `systemError == common::SystemError::ecEAGAIN`
97  * @return true if there was more data expected.
98  */
99  bool eof() const { return systemError == common::SystemError::ecEAGAIN; }
100 
101  /**
102  * Set the systemError. Implictly sets parseError to peOK ig `se == common::SystemError::ecOK`
103  * and to peSystemError if `se != common::SystemError::ecOK`
104  * @param se The SystemError to set.
105  */
107  systemError = se;
109  else parseError = peOk;
110  }
111 
112  /**
113  * Return the systemError.
114  * @return thesystemError part.
115  */
117 
118  /**
119  * Return the ParseResult as a human readable string.
120  * @return The ParseResult as a string.
121  */
122  std::string asString() const { return common::Puts() << "pe:" << getParseResultAsString(parseError) << "/se:" << systemError.asString(); }
123 
124  private:
125  /** The parse eror. */
127  /** The common::SystemError is parseError == peSystemError, undefined otherwise.*/
129  };
130 
131 
132  /**
133  * Read a complete HTTPFragment from a VirtualReadBuffer.
134  * @param buffer the VirtualReadBuffer to get characters from.
135  * @return The ParseError.
136  */
137  virtual ParseResult parse( VirtualReadBuffer& buffer ) = 0;
138 
139  /**
140  * Convert the HTTPFragment in a HTTP protocol string.
141  * @return The HTTPFragment as a string.
142  */
143  virtual std::string asString() const = 0;
144 
145  /**
146  * Return the string description of a ParseError.
147  * @param error The ParseError to describe.
148  * @return The ParseError description.
149  */
150  static std::string getParseResultAsString( ParseError error );
151 
152  };
153 
154  }
155 
156 }
157 
158 #endif
dodo::network::protocol::http::HTTPFragment::peExpectingUnsignedInt
@ peExpectingUnsignedInt
An unsigned int was expected.
Definition: httpfragment.hpp:68
dodo::network::protocol::http::HTTPFragment::asString
virtual std::string asString() const =0
Convert the HTTPFragment in a HTTP protocol string.
dodo::network::protocol::http::HTTPFragment::peExpectingHeaderColon
@ peExpectingHeaderColon
A header field name was read, but no colon found after it.
Definition: httpfragment.hpp:57
dodo::network::protocol::http::HTTPFragment::getParseResultAsString
static std::string getParseResultAsString(ParseError error)
Return the string description of a ParseError.
Definition: httpfragment.cpp:37
socketreadbuffer.hpp
dodo::network::protocol::http::HTTPFragment::peIncomplete
@ peIncomplete
Not an error, but more data is expected to complete.
Definition: httpfragment.hpp:53
dodo::network::protocol::http::HTTPFragment::peUnFinishedToken
@ peUnFinishedToken
A token is being parsed but is ending erroneously.
Definition: httpfragment.hpp:56
dodo::network::protocol::http::HTTPFragment::ParseResult::ParseResult
ParseResult(ParseError pe, common::SystemError se)
Explicit constructor.
Definition: httpfragment.hpp:87
dodo::network::protocol::http::HTTPFragment::peInvalidHeaderListEnd
@ peInvalidHeaderListEnd
A header list is not ending properly.
Definition: httpfragment.hpp:59
dodo::network::protocol::http::HTTPFragment::ParseResult::ok
bool ok() const
Test if parseError == peOk && systemError == common::SystemError::ecOK.
Definition: httpfragment.hpp:93
dodo::network::VirtualReadBuffer
Interface to read individual bytes whilst the implementation can read from an actual source (such as ...
Definition: socketreadbuffer.hpp:44
dodo::network::protocol::http::HTTPFragment::ParseResult::setSystemError
void setSystemError(common::SystemError se)
Set the systemError.
Definition: httpfragment.hpp:106
dodo::network::protocol::http::HTTPFragment::peSystemError
@ peSystemError
The parse failed due to system error SocketReadBuffer::getLastError()
Definition: httpfragment.hpp:54
dodo::network::protocol::http::HTTPFragment::ParseResult::ParseResult
ParseResult()
Default constructor sets to { parseError = peOk; systemError = common::SystemError::ecOK; }
Definition: httpfragment.hpp:80
dodo::network::protocol::http::HTTPFragment::ParseError
ParseError
Parse results returned by the parse functions.
Definition: httpfragment.hpp:51
dodo::common::SystemError::ecEAGAIN
@ ecEAGAIN
11 Try again
Definition: systemerror.hpp:71
dodo::network::protocol::http::HTTPFragment
Generic HTTP fragment, either a complete (such as HTTPRequest) or incomplete HTTP fragment (ssuch as ...
Definition: httpfragment.hpp:45
dodo::network::protocol::http::HTTPFragment::peInvalidChunkHex
@ peInvalidChunkHex
The hex chunk size is invalid.
Definition: httpfragment.hpp:66
dodo::common::SystemError::asString
std::string asString() const
Get the system error string.
Definition: systemerror.hpp:322
dodo
A C++ platform interface to lean Linux services tailored for containerized deployment.
Definition: application.hpp:29
dodo::network::protocol::http::HTTPFragment::peInvalidRequestLine
@ peInvalidRequestLine
The request line is invalid.
Definition: httpfragment.hpp:62
dodo::network::protocol::http::HTTPFragment::peInvalidTransferEncoding
@ peInvalidTransferEncoding
The specified transfer-encoding header is invalid.
Definition: httpfragment.hpp:65
dodo::network::protocol::http::HTTPFragment::ParseResult::getSystemError
common::SystemError getSystemError() const
Return the systemError.
Definition: httpfragment.hpp:116
dodo::network::protocol::http::HTTPFragment::parse
virtual ParseResult parse(VirtualReadBuffer &buffer)=0
Read a complete HTTPFragment from a VirtualReadBuffer.
dodo::network::protocol::http::HTTPFragment::peUnexpectedBody
@ peUnexpectedBody
A message body is present but should not be there.
Definition: httpfragment.hpp:64
dodo::network::protocol::http::HTTPFragment::ParseResult
Used to convey parsing succces.
Definition: httpfragment.hpp:75
dodo::network::protocol::http::HTTPFragment::ParseResult::eof
bool eof() const
Test if systemError == common::SystemError::ecEAGAIN
Definition: httpfragment.hpp:99
dodo::network::protocol::http::HTTPFragment::peInvalidLastChunk
@ peInvalidLastChunk
The last chunk does not have size 0.
Definition: httpfragment.hpp:67
dodo::common::SystemError::ecOK
@ ecOK
0 Not an error, success
Definition: systemerror.hpp:60
dodo::network::protocol::http::HTTPFragment::ParseResult::asString
std::string asString() const
Return the ParseResult as a human readable string.
Definition: httpfragment.hpp:122
dodo::network::protocol::http::HTTPFragment::ParseResult::parseError
ParseError parseError
The parse eror.
Definition: httpfragment.hpp:126
dodo::network::protocol::http::HTTPFragment::peInvalidHeaderFieldValue
@ peInvalidHeaderFieldValue
A header field value was being read, but it is invalid.
Definition: httpfragment.hpp:58
dodo::network::protocol::http::HTTPFragment::peInvalidMethod
@ peInvalidMethod
An invalid method was specified in the request line.
Definition: httpfragment.hpp:60
dodo::network::protocol::http::HTTPFragment::peOk
@ peOk
Ok.
Definition: httpfragment.hpp:52
dodo::common::Puts
Helper class to write strings in stream format, eg.
Definition: puts.hpp:46
dodo::common::SystemError
Linux system error primitive to provide a consistent interface to Linux error codes.
Definition: systemerror.hpp:53
dodo::network::protocol::http::HTTPFragment::peExpectCRLF
@ peExpectCRLF
A CR was not followed by an LF.
Definition: httpfragment.hpp:55
dodo::network::protocol::http::HTTPFragment::ParseResult::systemError
common::SystemError systemError
The common::SystemError is parseError == peSystemError, undefined otherwise.
Definition: httpfragment.hpp:128
dodo::network::protocol::http::HTTPFragment::peInvalidContentLength
@ peInvalidContentLength
The content length does not match the message body size.
Definition: httpfragment.hpp:63
dodo::network::protocol::http::HTTPFragment::peInvalidHTTPVersion
@ peInvalidHTTPVersion
An invalid HTTP version was specified in the request line.
Definition: httpfragment.hpp:61