summaryrefslogtreecommitdiffstats
path: root/source/HTTPServer/HTTPMessage.h
blob: ef8e12ca495df67d52442735bf21796d2d296f89 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

// HTTPMessage.h

// Declares the cHTTPMessage class representing the common ancestor for HTTP request and response classes





#pragma once

#include "EnvelopeParser.h"





class cHTTPMessage
{
public:
	enum
	{
		HTTP_OK = 200,
		HTTP_BAD_REQUEST = 400,
	} ;

	enum eKind
	{
		mkRequest,
		mkResponse,
	} ;
	
	cHTTPMessage(eKind a_Kind);

	/// Adds a header into the internal map of headers. Recognizes special headers: Content-Type and Content-Length
	void AddHeader(const AString & a_Key, const AString & a_Value);
	
	void SetContentType  (const AString & a_ContentType) { m_ContentType   = a_ContentType; }
	void SetContentLength(int a_ContentLength)           { m_ContentLength = a_ContentLength; }
	
	const AString & GetContentType  (void) const { return m_ContentType; }
	int             GetContentLength(void) const { return m_ContentLength; }

protected:
	typedef std::map<AString, AString> cNameValueMap;
	
	eKind m_Kind;
	
	cNameValueMap m_Headers;

	/// Type of the content; parsed by AddHeader(), set directly by SetContentLength()
	AString m_ContentType;

	/// Length of the content that is to be received. -1 when the object is created, parsed by AddHeader() or set directly by SetContentLength()
	int m_ContentLength;
} ;





class cHTTPRequest :
	public cHTTPMessage,
	protected cEnvelopeParser::cCallbacks
{
	typedef cHTTPMessage super;
	
public:
	cHTTPRequest(void);
	
	/** Parses the request line and then headers from the received data.
	Returns the number of bytes consumed or a negative number for error
	*/
	int ParseHeaders(const char * a_Data, int a_Size);
	
	/// Returns true if the request did contain a Content-Length header
	bool HasReceivedContentLength(void) const { return (m_ContentLength >= 0); }
	
	/// Returns the method used in the request
	const AString & GetMethod(void) const { return m_Method; }
	
	/// Returns the URL used in the request
	const AString & GetURL(void) const { return m_URL; }
	
	/// Sets the UserData pointer that is stored within this request. The request doesn't touch this data (doesn't delete it)!
	void SetUserData(void * a_UserData) { m_UserData = a_UserData; }
	
	/// Retrieves the UserData pointer that has been stored within this request.
	void * GetUserData(void) const { return m_UserData; }
	
	/// Returns true if more data is expected for the request headers
	bool IsInHeaders(void) const { return m_EnvelopeParser.IsInHeaders(); }
	
protected:
	/// Parser for the envelope data
	cEnvelopeParser m_EnvelopeParser;
	
	/// True if the data received so far is parsed successfully. When false, all further parsing is skipped
	bool m_IsValid;
	
	/// Bufferred incoming data, while parsing for the request line
	AString m_IncomingHeaderData;
	
	/// Method of the request (GET / PUT / POST / ...)
	AString m_Method;
	
	/// Full URL of the request
	AString m_URL;
	
	/// Data that the HTTPServer callbacks are allowed to store.
	void * m_UserData;
	
	
	/** Parses the incoming data for the first line (RequestLine)
	Returns the number of bytes consumed, or -1 for an error
	*/
	int ParseRequestLine(const char * a_Data, int a_Size);
	
	// cEnvelopeParser::cCallbacks overrides:
	virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override;
} ;





class cHTTPResponse :
	public cHTTPMessage
{
	typedef cHTTPMessage super;

public:
	cHTTPResponse(void);
	
	/** Appends the response to the specified datastream - response line and headers.
	The body will be sent later directly through cConnection::Send()
	*/
	void AppendToData(AString & a_DataStream) const;
} ;