summaryrefslogtreecommitdiffstats
path: root/src/HTTPServer/HTTPMessage.h
blob: c0667030f2b36e2cf2d45777bbed60392ac7f957 (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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176

// 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 eStatus
	{
		HTTP_OK = 200,
		HTTP_BAD_REQUEST = 400,
	} ;

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

	// Force a virtual destructor in all descendants
	virtual ~cHTTPMessage() {}
	
	/** 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(size_t a_ContentLength)        { m_ContentLength = a_ContentLength; }
	
	const AString & GetContentType  (void) const { return m_ContentType; }
	size_t          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.
	AString::npos when the object is created.
	Parsed by AddHeader() or set directly by SetContentLength() */
	size_t 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 AString::npos number for error
	*/
	size_t ParseHeaders(const char * a_Data, size_t a_Size);
	
	/** Returns true if the request did contain a Content-Length header */
	bool HasReceivedContentLength(void) const { return (m_ContentLength != AString::npos); }
	
	/** 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; }
	
	/** Returns the URL used in the request, without any parameters */
	AString GetBareURL(void) const;
	
	/** 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(); }
	
	/** Returns true if the request did present auth data that was understood by the parser */
	bool HasAuth(void) const { return m_HasAuth; }
	
	/** Returns the username that the request presented. Only valid if HasAuth() is true */
	const AString & GetAuthUsername(void) const { return m_AuthUsername; }
	
	/** Returns the password that the request presented. Only valid if HasAuth() is true */
	const AString & GetAuthPassword(void) const { return m_AuthPassword; }
	
	bool DoesAllowKeepAlive(void) const { return m_AllowKeepAlive; }
	
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;
	
	/** Set to true if the request contains auth data that was understood by the parser */
	bool m_HasAuth;
	
	/** The username used for auth */
	AString m_AuthUsername;
	
	/** The password used for auth */
	AString m_AuthPassword;
	
	/** Set to true if the request indicated that it supports keepalives.
	If false, the server will close the connection once the request is finished */
	bool m_AllowKeepAlive;
	
	
	/** Parses the incoming data for the first line (RequestLine)
	Returns the number of bytes consumed, or -1 for an error
	*/
	size_t ParseRequestLine(const char * a_Data, size_t 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;
} ;