OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/url_request/url_request.h" | 5 #include "net/url_request/url_request.h" |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/process_util.h" | 9 #include "base/process_util.h" |
10 #include "base/singleton.h" | 10 #include "base/singleton.h" |
11 #include "base/stats_counters.h" | 11 #include "base/stats_counters.h" |
| 12 #include "base/string_util.h" |
12 #include "googleurl/src/gurl.h" | 13 #include "googleurl/src/gurl.h" |
13 #include "net/base/load_flags.h" | 14 #include "net/base/load_flags.h" |
14 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
15 #include "net/base/upload_data.h" | 16 #include "net/base/upload_data.h" |
| 17 #include "net/http/http_util.h" |
16 #include "net/url_request/url_request_job.h" | 18 #include "net/url_request/url_request_job.h" |
17 #include "net/url_request/url_request_job_manager.h" | 19 #include "net/url_request/url_request_job_manager.h" |
18 | 20 |
19 #ifndef NDEBUG | 21 #ifndef NDEBUG |
20 URLRequestMetrics url_request_metrics; | 22 URLRequestMetrics url_request_metrics; |
21 #endif | 23 #endif |
22 | 24 |
23 using base::Time; | 25 using base::Time; |
24 using net::UploadData; | 26 using net::UploadData; |
25 using std::string; | 27 using std::string; |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 DCHECK(job_); | 289 DCHECK(job_); |
288 | 290 |
289 job_->ContinueDespiteLastError(); | 291 job_->ContinueDespiteLastError(); |
290 } | 292 } |
291 | 293 |
292 void URLRequest::OrphanJob() { | 294 void URLRequest::OrphanJob() { |
293 job_->DetachRequest(); // ensures that the job will not call us again | 295 job_->DetachRequest(); // ensures that the job will not call us again |
294 job_ = NULL; | 296 job_ = NULL; |
295 } | 297 } |
296 | 298 |
| 299 // static |
| 300 std::string URLRequest::StripPostSpecificHeaders(const std::string& headers) { |
| 301 // These are headers that may be attached to a POST. |
| 302 static const char* const kPostHeaders[] = { |
| 303 "content-type", |
| 304 "content-length", |
| 305 "origin" |
| 306 }; |
| 307 |
| 308 std::string stripped_headers; |
| 309 net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); |
| 310 |
| 311 while (it.GetNext()) { |
| 312 bool is_post_specific = false; |
| 313 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kPostHeaders); ++i) { |
| 314 if (LowerCaseEqualsASCII(it.name_begin(), it.name_end(), |
| 315 kPostHeaders[i])) { |
| 316 is_post_specific = true; |
| 317 break; |
| 318 } |
| 319 } |
| 320 if (!is_post_specific) { |
| 321 // Assume that name and values are on the same line. |
| 322 stripped_headers.append(it.name_begin(), it.values_end()); |
| 323 stripped_headers.append("\r\n"); |
| 324 } |
| 325 } |
| 326 return stripped_headers; |
| 327 } |
| 328 |
297 int URLRequest::Redirect(const GURL& location, int http_status_code) { | 329 int URLRequest::Redirect(const GURL& location, int http_status_code) { |
298 // TODO(darin): treat 307 redirects of POST requests very carefully. we | 330 // TODO(darin): treat 307 redirects of POST requests very carefully. we |
299 // should prompt the user before re-submitting the POST body. | 331 // should prompt the user before re-submitting the POST body. |
300 DCHECK(!(method_ == "POST" && http_status_code == 307)) << "implement me!"; | 332 DCHECK(!(method_ == "POST" && http_status_code == 307)) << "implement me!"; |
301 | 333 |
302 if (redirect_limit_ <= 0) { | 334 if (redirect_limit_ <= 0) { |
303 DLOG(INFO) << "disallowing redirect: exceeds limit"; | 335 DLOG(INFO) << "disallowing redirect: exceeds limit"; |
304 return net::ERR_TOO_MANY_REDIRECTS; | 336 return net::ERR_TOO_MANY_REDIRECTS; |
305 } | 337 } |
306 | 338 |
307 if (!job_->IsSafeRedirect(location)) { | 339 if (!job_->IsSafeRedirect(location)) { |
308 DLOG(INFO) << "disallowing redirect: unsafe protocol"; | 340 DLOG(INFO) << "disallowing redirect: unsafe protocol"; |
309 return net::ERR_UNSAFE_REDIRECT; | 341 return net::ERR_UNSAFE_REDIRECT; |
310 } | 342 } |
311 | 343 |
312 // NOTE: even though RFC 2616 says to preserve the request method when | 344 // NOTE: even though RFC 2616 says to preserve the request method when |
313 // following a 302 redirect, normal browsers don't do that. instead, they | 345 // following a 302 redirect, normal browsers don't do that. instead, they |
314 // all convert a POST into a GET in response to a 302, and so shall we. | 346 // all convert a POST into a GET in response to a 302, and so shall we. |
| 347 bool was_post = method_ == "POST"; |
315 url_ = location; | 348 url_ = location; |
316 method_ = "GET"; | 349 method_ = "GET"; |
317 upload_ = 0; | 350 upload_ = 0; |
318 status_ = URLRequestStatus(); | 351 status_ = URLRequestStatus(); |
319 --redirect_limit_; | 352 --redirect_limit_; |
320 | 353 |
| 354 if (was_post) { |
| 355 // If being switched from POST to GET, must remove headers that were |
| 356 // specific to the POST and don't have meaning in GET. For example |
| 357 // the inclusion of a multipart Content-Type header in GET can cause |
| 358 // problems with some servers: |
| 359 // http://code.google.com/p/chromium/issues/detail?id=843 |
| 360 // |
| 361 // TODO(eroman): It would be better if this data was structured into |
| 362 // specific fields/flags, rather than a stew of extra headers. |
| 363 extra_request_headers_ = StripPostSpecificHeaders(extra_request_headers_); |
| 364 } |
| 365 |
321 if (!final_upload_progress_) { | 366 if (!final_upload_progress_) { |
322 final_upload_progress_ = job_->GetUploadProgress(); | 367 final_upload_progress_ = job_->GetUploadProgress(); |
323 } | 368 } |
324 | 369 |
325 OrphanJob(); | 370 OrphanJob(); |
326 | 371 |
327 is_pending_ = false; | 372 is_pending_ = false; |
328 Start(); | 373 Start(); |
329 return net::OK; | 374 return net::OK; |
330 } | 375 } |
331 | 376 |
332 int64 URLRequest::GetExpectedContentSize() const { | 377 int64 URLRequest::GetExpectedContentSize() const { |
333 int64 expected_content_size = -1; | 378 int64 expected_content_size = -1; |
334 if (job_) | 379 if (job_) |
335 expected_content_size = job_->expected_content_size(); | 380 expected_content_size = job_->expected_content_size(); |
336 | 381 |
337 return expected_content_size; | 382 return expected_content_size; |
338 } | 383 } |
OLD | NEW |