]> git.mxchange.org Git - simgear.git/blob - simgear/io/HTTPRequest.cxx
Merge branch 'next' of gitorious.org:fg/simgear into next
[simgear.git] / simgear / io / HTTPRequest.cxx
1 #include "HTTPRequest.hxx"
2
3 #include <simgear/misc/strutils.hxx>
4 #include <simgear/compiler.h>
5 #include <simgear/debug/logstream.hxx>
6
7 using std::string;
8 using std::map;
9
10 namespace simgear
11 {
12
13 namespace HTTP
14 {
15
16 extern const int DEFAULT_HTTP_PORT;
17
18 Request::Request(const string& url, const string method) :
19     _method(method),
20     _url(url),
21     _responseVersion(HTTP_VERSION_UNKNOWN),
22     _responseStatus(0),
23     _responseLength(0),
24     _receivedBodyBytes(0),
25     _willClose(false)
26 {
27     
28 }
29
30 Request::~Request()
31 {
32     
33 }
34
35 void Request::setUrl(const string& url)
36 {
37     _url = url;
38 }
39
40 string_list Request::requestHeaders() const
41 {
42     string_list r;
43     return r;
44 }
45
46 string Request::header(const std::string& name) const
47 {
48     return string();
49 }
50
51 void Request::responseStart(const string& r)
52 {
53     const int maxSplit = 2; // HTTP/1.1 nnn reason-string
54     string_list parts = strutils::split(r, NULL, maxSplit);
55     if (parts.size() != 3) {
56         SG_LOG(SG_IO, SG_WARN, "HTTP::Request: malformed response start:" << r);
57         setFailure(400, "malformed HTTP response header");
58         return;
59     }
60     
61     _responseVersion = decodeVersion(parts[0]);    
62     _responseStatus = strutils::to_int(parts[1]);
63     _responseReason = parts[2];
64 }
65
66 void Request::responseHeader(const string& key, const string& value)
67 {
68     if (key == "connection") {
69         _willClose = (value.find("close") >= 0);
70     }
71     
72     _responseHeaders[key] = value;
73 }
74
75 void Request::responseHeadersComplete()
76 {
77     // no op
78 }
79
80 void Request::processBodyBytes(const char* s, int n)
81 {
82     _receivedBodyBytes += n;
83     gotBodyData(s, n);
84 }
85
86 void Request::gotBodyData(const char* s, int n)
87 {
88
89 }
90
91 void Request::responseComplete()
92 {
93     
94 }
95     
96 string Request::scheme() const
97 {
98     int firstColon = url().find(":");
99     if (firstColon > 0) {
100         return url().substr(0, firstColon);
101     }
102     
103     return ""; // couldn't parse scheme
104 }
105     
106 string Request::path() const
107 {
108     string u(url());
109     int schemeEnd = u.find("://");
110     if (schemeEnd < 0) {
111         return ""; // couldn't parse scheme
112     }
113     
114     int hostEnd = u.find('/', schemeEnd + 3);
115     if (hostEnd < 0) { 
116         return ""; // couldn't parse host
117     }
118     
119     int query = u.find('?', hostEnd + 1);
120     if (query < 0) {
121         // all remainder of URL is path
122         return u.substr(hostEnd);
123     }
124     
125     return u.substr(hostEnd, query - hostEnd);
126 }
127
128 string Request::host() const
129 {
130     string hp(hostAndPort());
131     int colonPos = hp.find(':');
132     if (colonPos >= 0) {
133         return hp.substr(0, colonPos); // trim off the colon and port
134     } else {
135         return hp; // no port specifier
136     }
137 }
138
139 unsigned short Request::port() const
140 {
141     string hp(hostAndPort());
142     int colonPos = hp.find(':');
143     if (colonPos >= 0) {
144         return (unsigned short) strutils::to_int(hp.substr(colonPos + 1));
145     } else {
146         return DEFAULT_HTTP_PORT;
147     }
148 }
149
150 string Request::hostAndPort() const
151 {
152     string u(url());
153     int schemeEnd = u.find("://");
154     if (schemeEnd < 0) {
155         return ""; // couldn't parse scheme
156     }
157     
158     int hostEnd = u.find('/', schemeEnd + 3);
159     if (hostEnd < 0) { // all remainder of URL is host
160         return u.substr(schemeEnd + 3);
161     }
162     
163     return u.substr(schemeEnd + 3, hostEnd - (schemeEnd + 3));
164 }
165
166 void Request::setResponseLength(unsigned int l)
167 {
168     _responseLength = l;
169 }
170
171 unsigned int Request::responseLength() const
172 {
173 // if the server didn't supply a content length, use the number
174 // of bytes we actually received (so far)
175     if ((_responseLength == 0) && (_receivedBodyBytes > 0)) {
176         return _receivedBodyBytes;
177     }
178     
179     return _responseLength;
180 }
181
182 void Request::setFailure(int code, const std::string& reason)
183 {
184     _responseStatus = code;
185     _responseReason = reason;
186     failed();
187 }
188
189 void Request::failed()
190 {
191     // no-op in base class
192 }
193
194 Request::HTTPVersion Request::decodeVersion(const string& v)
195 {
196     if (v == "HTTP/1.1") return HTTP_1_1;
197     if (v == "HTTP/1.0") return HTTP_1_0;
198     if (strutils::starts_with(v, "HTTP/0.")) return HTTP_0_x;
199     return HTTP_VERSION_UNKNOWN;
200 }
201
202 bool Request::closeAfterComplete() const
203 {
204 // for non HTTP/1.1 connections, assume server closes
205     return _willClose || (_responseVersion != HTTP_1_1);
206 }
207
208 } // of namespace HTTP
209
210 } // of namespace simgear