Changeset 222728 in webkit
- Timestamp:
- Oct 2, 2017 12:00:17 PM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r222726 r222728 1 2017-10-02 Basuke Suzuki <Basuke.Suzuki@sony.com> 2 3 [CURL] Should handle redirects in WebCore 4 https://bugs.webkit.org/show_bug.cgi?id=21242 5 6 Reviewed by Alex Christensen. 7 8 * platform/network/ResourceHandle.cpp: 9 * platform/network/curl/CurlContext.cpp: 10 (WebCore::CurlHandle::enableAutoReferer): Deleted. 11 * platform/network/curl/CurlContext.h: 12 * platform/network/curl/CurlRequest.cpp: 13 (WebCore::CurlRequest::setupTransfer): 14 (WebCore::CurlRequest::didReceiveHeader): 15 (WebCore::CurlRequest::didReceiveData): 16 * platform/network/curl/ResourceHandleCurl.cpp: 17 (WebCore::ResourceHandle::start): 18 (WebCore::ResourceHandle::continueDidReceiveResponse): 19 (WebCore::ResourceHandle::continueWillSendRequest): 20 * platform/network/curl/ResourceHandleCurlDelegate.cpp: 21 (WebCore::ResourceHandleCurlDelegate::curlDidReceiveResponse): 22 (WebCore::ResourceHandleCurlDelegate::shouldRedirectAsGET): 23 (WebCore::ResourceHandleCurlDelegate::willSendRequest): 24 (WebCore::ResourceHandleCurlDelegate::continueWillSendRequest): 25 (WebCore::ResourceHandleCurlDelegate::continueAfterWillSendRequest): 26 * platform/network/curl/ResourceHandleCurlDelegate.h: 27 * platform/network/curl/ResourceResponse.h: 28 * platform/network/curl/ResourceResponseCurl.cpp: 29 (WebCore::ResourceResponse::shouldRedirect): 30 (WebCore::ResourceResponse::isMovedPermanently const): 31 (WebCore::ResourceResponse::isFound const): 32 (WebCore::ResourceResponse::isSeeOther const): 33 (WebCore::ResourceResponse::isRedirection const): Deleted. 34 1 35 2017-10-02 Antti Koivisto <antti@apple.com> 2 36 -
trunk/Source/WebCore/platform/network/ResourceHandle.cpp
r222467 r222728 171 171 } 172 172 173 #if !PLATFORM(COCOA) && !USE(CFURLCONNECTION) && !USE(SOUP) 173 #if !PLATFORM(COCOA) && !USE(CFURLCONNECTION) && !USE(SOUP) && !USE(CURL) 174 174 // ResourceHandle never uses async client calls on these platforms yet. 175 175 void ResourceHandle::continueWillSendRequest(ResourceRequest&&) -
trunk/Source/WebCore/platform/network/curl/CurlContext.cpp
r222521 r222728 426 426 } 427 427 428 void CurlHandle::enableAutoReferer()429 {430 curl_easy_setopt(m_handle, CURLOPT_AUTOREFERER, 1L);431 }432 433 428 void CurlHandle::enableHttpAuthentication(long option) 434 429 { -
trunk/Source/WebCore/platform/network/curl/CurlContext.h
r222521 r222728 249 249 250 250 void enableFollowLocation(); 251 void enableAutoReferer();252 251 253 252 void enableHttpAuthentication(long); -
trunk/Source/WebCore/platform/network/curl/CurlRequest.cpp
r222665 r222728 170 170 m_curlHandle->enableTimeout(); 171 171 172 m_curlHandle->enableAutoReferer();173 m_curlHandle->enableFollowLocation();174 172 m_curlHandle->enableProxyIfExists(); 175 173 m_curlHandle->enableCookieJarIfExists(); … … 276 274 } 277 275 278 // If the FOLLOWLOCATION option is enabled for the curl handle then 279 // curl will follow the redirections internally. Thus this header callback 280 // will be called more than one time with the line starting "HTTP" for one job. 281 282 m_response.url = m_curlHandle->getEffectiveURL(); 276 m_response.url = m_request.url(); 283 277 m_response.statusCode = statusCode; 284 278 … … 308 302 309 303 auto receiveBytes = buffer->size(); 310 311 // this shouldn't be necessary but apparently is. CURL writes the data312 // of html page even if it is a redirect that was handled internally313 // can be observed e.g. on gmail.com314 auto statusCode = m_curlHandle->getResponseCode();315 if (statusCode && (300 <= *statusCode) && (*statusCode < 400))316 return receiveBytes;317 304 318 305 if (receiveBytes) { -
trunk/Source/WebCore/platform/network/curl/ResourceHandleCurl.cpp
r222665 r222728 66 66 return false; 67 67 68 // Only allow the POST and GET methods for non-HTTP requests. 69 const ResourceRequest& request = firstRequest(); 70 if (!request.url().protocolIsInHTTPFamily() && request.httpMethod() != "GET" && request.httpMethod() != "POST") { 71 scheduleFailure(InvalidURLFailure); // Error must not be reported immediately 72 return true; 73 } 74 68 75 d->m_delegate = adoptRef(new ResourceHandleCurlDelegate(this)); 69 76 return d->m_delegate->start(); … … 251 258 } 252 259 260 void ResourceHandle::continueDidReceiveResponse() 261 { 262 notImplemented(); 263 } 264 265 void ResourceHandle::continueWillSendRequest(ResourceRequest&& request) 266 { 267 ASSERT(isMainThread()); 268 ASSERT(!client() || client()->usesAsyncCallbacks()); 269 270 if (d->m_delegate) 271 d->m_delegate->continueWillSendRequest(WTFMove(request)); 272 } 273 253 274 } // namespace WebCore 254 275 -
trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.cpp
r222665 r222728 202 202 } 203 203 204 // HTTP redirection 205 if (response().isRedirection()) { 206 String location = response().httpHeaderField(HTTPHeaderName::Location); 207 if (!location.isEmpty()) { 208 URL newURL = URL(m_firstRequest.url(), location); 209 210 ResourceRequest redirectedRequest = m_firstRequest; 211 redirectedRequest.setURL(newURL); 212 ResourceResponse localResponse = response(); 213 if (m_handle->client()) 214 m_handle->client()->willSendRequest(m_handle, WTFMove(redirectedRequest), WTFMove(localResponse)); 215 216 m_firstRequest.setURL(newURL); 217 218 return; 219 } 204 if (response().shouldRedirect()) { 205 willSendRequest(); 206 return; 220 207 } 221 208 … … 288 275 CurlCacheManager::getInstance().didFail(*m_handle); 289 276 m_handle->client()->didFail(m_handle, resourceError); 277 } 278 279 bool ResourceHandleCurlDelegate::shouldRedirectAsGET(const ResourceRequest& request, bool crossOrigin) 280 { 281 if ((request.httpMethod() == "GET") || (request.httpMethod() == "HEAD")) 282 return false; 283 284 if (!request.url().protocolIsInHTTPFamily()) 285 return true; 286 287 if (response().isSeeOther()) 288 return true; 289 290 if ((response().isMovedPermanently() || response().isFound()) && (request.httpMethod() == "POST")) 291 return true; 292 293 if (crossOrigin && (request.httpMethod() == "DELETE")) 294 return true; 295 296 return false; 297 } 298 299 void ResourceHandleCurlDelegate::willSendRequest() 300 { 301 ASSERT(isMainThread()); 302 303 static const int maxRedirects = 20; 304 305 if (m_redirectCount++ > maxRedirects) { 306 m_handle->client()->didFail(m_handle, ResourceError::httpError(CURLE_TOO_MANY_REDIRECTS, response().url())); 307 return; 308 } 309 310 String location = response().httpHeaderField(HTTPHeaderName::Location); 311 URL newURL = URL(m_firstRequest.url(), location); 312 bool crossOrigin = !protocolHostAndPortAreEqual(m_firstRequest.url(), newURL); 313 314 ResourceRequest newRequest = m_firstRequest; 315 newRequest.setURL(newURL); 316 317 if (shouldRedirectAsGET(newRequest, crossOrigin)) { 318 newRequest.setHTTPMethod("GET"); 319 newRequest.setHTTPBody(nullptr); 320 newRequest.clearHTTPContentType(); 321 } 322 323 // Should not set Referer after a redirect from a secure resource to non-secure one. 324 if (!newURL.protocolIs("https") && protocolIs(newRequest.httpReferrer(), "https") && m_handle->context()->shouldClearReferrerOnHTTPSToHTTPRedirect()) 325 newRequest.clearHTTPReferrer(); 326 327 m_user = newURL.user(); 328 m_pass = newURL.pass(); 329 newRequest.removeCredentials(); 330 331 if (crossOrigin) { 332 // If the network layer carries over authentication headers from the original request 333 // in a cross-origin redirect, we want to clear those headers here. 334 newRequest.clearHTTPAuthorization(); 335 newRequest.clearHTTPOrigin(); 336 } 337 338 ResourceResponse responseCopy = response(); 339 if (m_handle->client()->usesAsyncCallbacks()) 340 m_handle->client()->willSendRequestAsync(m_handle, WTFMove(newRequest), WTFMove(responseCopy)); 341 else { 342 auto request = m_handle->client()->willSendRequest(m_handle, WTFMove(newRequest), WTFMove(responseCopy)); 343 continueAfterWillSendRequest(WTFMove(request)); 344 } 345 } 346 347 void ResourceHandleCurlDelegate::continueWillSendRequest(ResourceRequest&& request) 348 { 349 ASSERT(isMainThread()); 350 351 continueAfterWillSendRequest(WTFMove(request)); 352 } 353 354 void ResourceHandleCurlDelegate::continueAfterWillSendRequest(ResourceRequest&& request) 355 { 356 ASSERT(isMainThread()); 357 358 // willSendRequest might cancel the load. 359 if (cancelledOrClientless() || !m_curlRequest) 360 return; 361 362 m_currentRequest = WTFMove(request); 363 364 bool isSyncRequest = m_curlRequest->isSyncRequest(); 365 m_curlRequest->cancel(); 366 m_curlRequest->setDelegate(nullptr); 367 368 m_curlRequest = createCurlRequest(m_currentRequest); 369 370 if (protocolHostAndPortAreEqual(m_currentRequest.url(), response().url())) { 371 auto credential = getCredential(m_currentRequest, true); 372 m_curlRequest->setUserPass(credential.first, credential.second); 373 } 374 375 m_curlRequest->start(isSyncRequest); 290 376 } 291 377 -
trunk/Source/WebCore/platform/network/curl/ResourceHandleCurlDelegate.h
r222665 r222728 56 56 void dispatchSynchronousJob(); 57 57 58 void continueWillSendRequest(ResourceRequest&&); 59 58 60 private: 59 61 // Called from main thread. … … 70 72 void curlDidFailWithError(const ResourceError&) override; 71 73 74 bool shouldRedirectAsGET(const ResourceRequest&, bool crossOrigin); 75 void willSendRequest(); 76 void continueAfterWillSendRequest(ResourceRequest&&); 77 72 78 void handleDataURL(); 73 79 … … 76 82 std::unique_ptr<MultipartHandle> m_multipartHandle; 77 83 unsigned m_authFailureCount { 0 }; 78 // Used by worker thread. 84 int m_redirectCount { 0 }; 85 79 86 ResourceRequest m_firstRequest; 80 87 ResourceRequest m_currentRequest; -
trunk/Source/WebCore/platform/network/curl/ResourceResponse.h
r222521 r222728 53 53 void setDeprecatedNetworkLoadMetrics(const NetworkLoadMetrics& networkLoadMetrics) { m_networkLoadMetrics = networkLoadMetrics; } 54 54 55 bool isRedirection() const; 55 bool shouldRedirect(); 56 bool isMovedPermanently() const; 57 bool isFound() const; 58 bool isSeeOther() const; 56 59 bool isNotModified() const; 57 60 bool isUnauthorized() const; -
trunk/Source/WebCore/platform/network/curl/ResourceResponseCurl.cpp
r222521 r222728 134 134 } 135 135 136 bool ResourceResponse:: isRedirection() const136 bool ResourceResponse::shouldRedirect() 137 137 { 138 138 auto statusCode = httpStatusCode(); 139 return (300 <= statusCode) && (statusCode < 400) && (statusCode != 304); 139 if ((statusCode < 300) || (400 <= statusCode)) 140 return false; 141 142 // Some 3xx status codes aren't actually redirects. 143 if (statusCode == 300 || statusCode == 304 || statusCode == 305 || statusCode == 306) 144 return false; 145 146 if (httpHeaderField(HTTPHeaderName::Location).isEmpty()) 147 return false; 148 149 return true; 150 } 151 152 bool ResourceResponse::isMovedPermanently() const 153 { 154 return (httpStatusCode() == 301); 155 } 156 157 bool ResourceResponse::isFound() const 158 { 159 return (httpStatusCode() == 302); 160 } 161 162 bool ResourceResponse::isSeeOther() const 163 { 164 return (httpStatusCode() == 303); 140 165 } 141 166
Note: See TracChangeset
for help on using the changeset viewer.