Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(469)

Side by Side Diff: net/server/http_server.cc

Issue 274813002: HttpServer: Handling of multiple header fields with the same name and multiple values of "Connectio… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | net/server/http_server_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/server/http_server.h" 5 #include "net/server/http_server.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 } 135 }
136 136
137 HttpServerRequestInfo request; 137 HttpServerRequestInfo request;
138 size_t pos = 0; 138 size_t pos = 0;
139 if (!ParseHeaders(connection, &request, &pos)) 139 if (!ParseHeaders(connection, &request, &pos))
140 break; 140 break;
141 141
142 // Sets peer address if exists. 142 // Sets peer address if exists.
143 socket->GetPeerAddress(&request.peer); 143 socket->GetPeerAddress(&request.peer);
144 144
145 std::string connection_header = request.GetHeaderValue("connection"); 145 bool connection_upgrade = false;
146 if (connection_header == "Upgrade") { 146 {
pfeldman 2014/05/08 13:38:18 There is no need for this.
147 std::string connection_header = request.GetHeaderValue("connection");
pfeldman 2014/05/08 13:38:18 if (request.HasHeaderValue("connection", "upgrade"
148 StringToLowerASCII(&connection_header);
149 std::vector<std::string> conn_items;
150 Tokenize(connection_header, ",", &conn_items);
151 for (std::vector<std::string>::iterator it = conn_items.begin();
152 it != conn_items.end(); ++it) {
153 base::TrimString(*it, " \t", &*it);
154 if (*it == "upgrade") {
155 connection_upgrade = true;
156 break;
157 }
158 }
159 }
160 if (connection_upgrade) {
147 connection->web_socket_.reset(WebSocket::CreateWebSocket(connection, 161 connection->web_socket_.reset(WebSocket::CreateWebSocket(connection,
148 request, 162 request,
149 &pos)); 163 &pos));
150 164
151 if (!connection->web_socket_.get()) // Not enough data was received. 165 if (!connection->web_socket_.get()) // Not enough data was received.
152 break; 166 break;
153 delegate_->OnWebSocketRequest(connection->id(), request); 167 delegate_->OnWebSocketRequest(connection->id(), request);
154 connection->Shift(pos); 168 connection->Shift(pos);
155 continue; 169 continue;
156 } 170 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 // This HTTP request parser uses a simple state machine to quickly parse 212 // This HTTP request parser uses a simple state machine to quickly parse
199 // through the headers. The parser is not 100% complete, as it is designed 213 // through the headers. The parser is not 100% complete, as it is designed
200 // for use in this simple test driver. 214 // for use in this simple test driver.
201 // 215 //
202 // Known issues: 216 // Known issues:
203 // - does not handle whitespace on first HTTP line correctly. Expects 217 // - does not handle whitespace on first HTTP line correctly. Expects
204 // a single space between the method/url and url/protocol. 218 // a single space between the method/url and url/protocol.
205 219
206 // Input character types. 220 // Input character types.
207 enum header_parse_inputs { 221 enum header_parse_inputs {
208 INPUT_SPACE, 222 INPUT_LWS,
209 INPUT_CR, 223 INPUT_CR,
210 INPUT_LF, 224 INPUT_LF,
211 INPUT_COLON, 225 INPUT_COLON,
212 INPUT_DEFAULT, 226 INPUT_DEFAULT,
213 MAX_INPUTS, 227 MAX_INPUTS,
214 }; 228 };
215 229
216 // Parser states. 230 // Parser states.
217 enum header_parse_states { 231 enum header_parse_states {
218 ST_METHOD, // Receiving the method 232 ST_METHOD, // Receiving the method
(...skipping 18 matching lines...) Expand all
237 /* SEPARATOR */ { ST_SEPARATOR, ST_ERR, ST_ERR, ST_VALUE, ST_ERR }, 251 /* SEPARATOR */ { ST_SEPARATOR, ST_ERR, ST_ERR, ST_VALUE, ST_ERR },
238 /* VALUE */ { ST_VALUE, ST_HEADER, ST_NAME, ST_VALUE, ST_VALUE }, 252 /* VALUE */ { ST_VALUE, ST_HEADER, ST_NAME, ST_VALUE, ST_VALUE },
239 /* DONE */ { ST_DONE, ST_DONE, ST_DONE, ST_DONE, ST_DONE }, 253 /* DONE */ { ST_DONE, ST_DONE, ST_DONE, ST_DONE, ST_DONE },
240 /* ERR */ { ST_ERR, ST_ERR, ST_ERR, ST_ERR, ST_ERR } 254 /* ERR */ { ST_ERR, ST_ERR, ST_ERR, ST_ERR, ST_ERR }
241 }; 255 };
242 256
243 // Convert an input character to the parser's input token. 257 // Convert an input character to the parser's input token.
244 int charToInput(char ch) { 258 int charToInput(char ch) {
245 switch(ch) { 259 switch(ch) {
246 case ' ': 260 case ' ':
247 return INPUT_SPACE; 261 case '\t':
262 return INPUT_LWS;
248 case '\r': 263 case '\r':
249 return INPUT_CR; 264 return INPUT_CR;
250 case '\n': 265 case '\n':
251 return INPUT_LF; 266 return INPUT_LF;
252 case ':': 267 case ':':
253 return INPUT_COLON; 268 return INPUT_COLON;
254 } 269 }
255 return INPUT_DEFAULT; 270 return INPUT_DEFAULT;
256 } 271 }
257 272
258 bool HttpServer::ParseHeaders(HttpConnection* connection, 273 bool HttpServer::ParseHeaders(HttpConnection* connection,
259 HttpServerRequestInfo* info, 274 HttpServerRequestInfo* info,
260 size_t* ppos) { 275 size_t* ppos) {
261 size_t& pos = *ppos; 276 size_t& pos = *ppos;
262 size_t data_len = connection->recv_data_.length(); 277 size_t data_len = connection->recv_data_.length();
263 int state = ST_METHOD; 278 int state = ST_METHOD;
264 std::string buffer; 279 std::string buffer;
265 std::string header_name; 280 std::string header_name;
266 std::string header_value; 281 std::string header_value;
267 while (pos < data_len) { 282 while (pos < data_len) {
268 char ch = connection->recv_data_[pos++]; 283 char ch = connection->recv_data_[pos++];
269 int input = charToInput(ch); 284 int input = charToInput(ch);
270 int next_state = parser_state[state][input]; 285 int next_state = parser_state[state][input];
271 286
272 bool transition = (next_state != state); 287 bool transition = (next_state != state);
288 HttpServerRequestInfo::HeadersMap::iterator it;
273 if (transition) { 289 if (transition) {
274 // Do any actions based on state transitions. 290 // Do any actions based on state transitions.
275 switch (state) { 291 switch (state) {
276 case ST_METHOD: 292 case ST_METHOD:
277 info->method = buffer; 293 info->method = buffer;
278 buffer.clear(); 294 buffer.clear();
279 break; 295 break;
280 case ST_URL: 296 case ST_URL:
281 info->path = buffer; 297 info->path = buffer;
282 buffer.clear(); 298 buffer.clear();
283 break; 299 break;
284 case ST_PROTO: 300 case ST_PROTO:
285 // TODO(mbelshe): Deal better with parsing protocol. 301 // TODO(mbelshe): Deal better with parsing protocol.
286 DCHECK(buffer == "HTTP/1.1"); 302 DCHECK(buffer == "HTTP/1.1");
287 buffer.clear(); 303 buffer.clear();
288 break; 304 break;
289 case ST_NAME: 305 case ST_NAME:
290 header_name = StringToLowerASCII(buffer); 306 header_name = StringToLowerASCII(buffer);
291 buffer.clear(); 307 buffer.clear();
292 break; 308 break;
293 case ST_VALUE: 309 case ST_VALUE:
294 base::TrimWhitespaceASCII(buffer, base::TRIM_LEADING, &header_value); 310 base::TrimWhitespaceASCII(buffer, base::TRIM_LEADING, &header_value);
295 // TODO(mbelshe): Deal better with duplicate headers 311 it = info->headers.find(header_name);
296 DCHECK(info->headers.find(header_name) == info->headers.end()); 312 // See last paragraph ("Multiple message-header fields...")
297 info->headers[header_name] = header_value; 313 // of www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
314 if (it == info->headers.end()) {
315 info->headers[header_name] = header_value;
316 } else {
317 it->second.append(",");
318 it->second.append(header_value);
319 }
298 buffer.clear(); 320 buffer.clear();
299 break; 321 break;
300 case ST_SEPARATOR: 322 case ST_SEPARATOR:
301 break; 323 break;
302 } 324 }
303 state = next_state; 325 state = next_state;
304 } else { 326 } else {
305 // Do any actions based on current state 327 // Do any actions based on current state
306 switch (state) { 328 switch (state) {
307 case ST_METHOD: 329 case ST_METHOD:
(...skipping 23 matching lines...) Expand all
331 } 353 }
332 354
333 HttpConnection* HttpServer::FindConnection(StreamListenSocket* socket) { 355 HttpConnection* HttpServer::FindConnection(StreamListenSocket* socket) {
334 SocketToConnectionMap::iterator it = socket_to_connection_.find(socket); 356 SocketToConnectionMap::iterator it = socket_to_connection_.find(socket);
335 if (it == socket_to_connection_.end()) 357 if (it == socket_to_connection_.end())
336 return NULL; 358 return NULL;
337 return it->second; 359 return it->second;
338 } 360 }
339 361
340 } // namespace net 362 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/server/http_server_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698