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
|
/*
* Copyright (C) 2007-2012 Xagasoft, All rights reserved.
*
* This file is part of the libbu++ library and is released under the
* terms of the license contained in the file LICENSE.
*/
#ifndef BU_PROTOCOL_HTTP_H
#define BU_PROTOCOL_HTTP_H
#include <stdint.h>
#include <sys/types.h>
#include "bu/protocol.h"
#include "bu/client.h"
#include "bu/string.h"
#include "bu/hash.h"
namespace Bu
{
/**
* An HTTP Protocol handler. Yes, I know that HTTP stands for Hyper Text
* Transfer Protocol, and that the Protocol part is redundant, but in this
* case the word Protocol is refering to the Libbu++ construct Bu::Protocol,
* and not a means of encoding conversations. Anyway, this class represents
* a general HTTP server processor. Every time a request comes in it calls
* the onRequest function in a subclass with the method and URI that were
* requested. The sub-class can then do whatever it needs to to send back
* a response.
*@ingroup Serving
*/
class ProtocolHttp : public Protocol
{
public: /* Types */
typedef Bu::List<Bu::String> TokenList;
public: /* Interface */
ProtocolHttp();
virtual ~ProtocolHttp();
virtual void onNewConnection( Bu::Client *pClient );
virtual void onNewData( Bu::Client *pClient );
virtual void onRequest(
const Bu::String &sMethod, const Bu::String &sPath )=0;
class Response
{
friend class Bu::ProtocolHttp;
public:
Response( int iCode );
Response( int iCode, const Bu::String &sReason );
virtual ~Response();
void setHeader( const Bu::String &sKey, const Bu::String &sVal );
void setContent( const Bu::String &sCont );
private:
int iCode;
Bu::String sReason;
typedef Bu::Hash<Bu::String,Bu::String> StringHash;
StringHash hHeaders;
Bu::String sContent;
};
void sendResponse( const Response &rRes );
private:
enum TokenType
{
ttOutOfData,
ttString,
ttNewline,
ttDoubleNewline,
ttSeperator
};
/**
* Read an HTTP line, this is up to the first CRLF that isn't followed
* by a continuation character, converting it to one line as it reads.
*@param line All data read will be appended to line, even if no
* end-of-line is read.
*@returns True if an end-of-line is read and the line should be
* processed, false if the end-of-line has not been reached, and more
* data needs to be read before this operation can continue.
*/
TokenType getToken( Bu::String &line );
bool isWS( char buf );
bool isSeperator( char buf );
void earlyResponse();
void lateResponse();
private: /* state */
Bu::Client *pClient;
TokenList lTokens;
int iState;
Bu::String sMethod;
Bu::String sPath;
int iMajor;
int iMinor;
};
}
#endif
|