Skip to content

Commit

Permalink
[Curl] Remove chunked transfer processing for PUT/POST methods
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=259209

Reviewed by Fujii Hironori.

CurlFormDataStream::shouldUseChunkTransfer() always returns false since 204820@main.
Since chunked transfer processing has not been used for a long time, we will
remove chunked transfer processing for PUT/POST methods.

It also requires libcurl built with large file support as a required feature.

* Source/WebCore/platform/network/curl/CurlContext.cpp:
(WebCore::CurlContext::CurlContext):
(WebCore::CurlHandle::enableHttpPostRequest):
(WebCore::CurlHandle::enableHttpPutRequest):
(WebCore::CurlHandle::setPostFieldSize): Deleted.
(WebCore::CurlHandle::setInFileSize): Deleted.
(WebCore::CurlHandle::expectedSizeOfCurlOffT): Deleted.
* Source/WebCore/platform/network/curl/CurlContext.h:
* Source/WebCore/platform/network/curl/CurlFormDataStream.cpp:
(WebCore::CurlFormDataStream::totalSize):
(WebCore::CurlFormDataStream::shouldUseChunkTransfer): Deleted.
(WebCore::CurlFormDataStream::computeContentLength): Deleted.
* Source/WebCore/platform/network/curl/CurlFormDataStream.h:
(WebCore::CurlFormDataStream::elementSize): Deleted.
* Source/WebCore/platform/network/curl/CurlRequest.cpp:
(WebCore::CurlRequest::setupPUT):
(WebCore::CurlRequest::setupPOST):
(WebCore::CurlRequest::setupSendData): Deleted.
* Source/WebCore/platform/network/curl/CurlRequest.h:

Canonical link: https://commits.webkit.org/266059@main
  • Loading branch information
kshukuwa authored and fujii committed Jul 14, 2023
1 parent 359976c commit 04637e9
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 92 deletions.
37 changes: 3 additions & 34 deletions Source/WebCore/platform/network/curl/CurlContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ CurlContext::CurlContext()
m_scheduler = makeUnique<CurlRequestScheduler>(maxConnects, maxTotalConnections, maxHostConnections);

auto info = curl_version_info(CURLVERSION_NOW);
RELEASE_ASSERT(info->features & CURL_VERSION_LARGEFILE);
m_isAltSvcEnabled = info->features & CURL_VERSION_ALTSVC;
m_isHttp2Enabled = info->features & CURL_VERSION_HTTP2;
#if ENABLE_CURL_HTTP3
Expand Down Expand Up @@ -483,33 +484,17 @@ void CurlHandle::enableHttpHeadRequest()
curl_easy_setopt(m_handle, CURLOPT_NOBODY, 1L);
}

void CurlHandle::enableHttpPostRequest()
void CurlHandle::enableHttpPostRequest(curl_off_t size)
{
enableHttp();
curl_easy_setopt(m_handle, CURLOPT_POST, 1L);
curl_easy_setopt(m_handle, CURLOPT_POSTFIELDSIZE_LARGE, static_cast<curl_off_t>(0));
}

void CurlHandle::setPostFieldSize(curl_off_t size)
{
if (expectedSizeOfCurlOffT() != sizeof(long long))
size = static_cast<int>(size);

curl_easy_setopt(m_handle, CURLOPT_POSTFIELDSIZE_LARGE, size);
}

void CurlHandle::enableHttpPutRequest()
void CurlHandle::enableHttpPutRequest(curl_off_t size)
{
enableHttp();
curl_easy_setopt(m_handle, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(m_handle, CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(0));
}

void CurlHandle::setInFileSize(curl_off_t size)
{
if (expectedSizeOfCurlOffT() != sizeof(long long))
size = static_cast<int>(size);

curl_easy_setopt(m_handle, CURLOPT_INFILESIZE_LARGE, size);
}

Expand Down Expand Up @@ -948,22 +933,6 @@ std::optional<CertificateInfo> CurlHandle::certificateInfo() const
return std::nullopt;
}

int CurlHandle::expectedSizeOfCurlOffT()
{
// The size of a curl_off_t could be different in WebKit and in cURL depending on
// compilation flags of both.
static int expectedSizeOfCurlOffT = 0;
if (!expectedSizeOfCurlOffT) {
curl_version_info_data* infoData = curl_version_info(CURLVERSION_NOW);
if (infoData->features & CURL_VERSION_LARGEFILE)
expectedSizeOfCurlOffT = sizeof(long long);
else
expectedSizeOfCurlOffT = sizeof(int);
}

return expectedSizeOfCurlOffT;
}

#ifndef NDEBUG

void CurlHandle::enableVerboseIfUsed()
Expand Down
7 changes: 2 additions & 5 deletions Source/WebCore/platform/network/curl/CurlContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,8 @@ class CurlHandle {
void enableHttp();
void enableHttpGetRequest();
void enableHttpHeadRequest();
void enableHttpPostRequest();
void setPostFieldSize(curl_off_t);
void enableHttpPutRequest();
void setInFileSize(curl_off_t);
void enableHttpPostRequest(curl_off_t size);
void enableHttpPutRequest(curl_off_t size);
void setHttpCustomRequest(const String&);

void enableConnectionOnly();
Expand Down Expand Up @@ -326,7 +324,6 @@ class CurlHandle {
};

void enableRequestHeaders();
static int expectedSizeOfCurlOffT();

static CURLcode willSetupSslCtxCallback(CURL*, void* sslCtx, void* userData);
CURLcode willSetupSslCtx(void* sslCtx);
Expand Down
22 changes: 6 additions & 16 deletions Source/WebCore/platform/network/curl/CurlFormDataStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#if USE(CURL)

#include "BlobRegistry.h"
#include "CurlContext.h"
#include "Logging.h"
#include <wtf/MainThread.h>

Expand Down Expand Up @@ -81,29 +80,20 @@ const Vector<uint8_t>* CurlFormDataStream::getPostData()
return m_postData.get();
}

bool CurlFormDataStream::shouldUseChunkTransfer()
{
computeContentLength();

return m_shouldUseChunkTransfer;
}

unsigned long long CurlFormDataStream::totalSize()
{
computeContentLength();

return m_totalSize;
}
if (!m_formData)
return 0;

void CurlFormDataStream::computeContentLength()
{
if (!m_formData || m_isContentLengthUpdated)
return;
if (m_isContentLengthUpdated)
return m_totalSize;

m_isContentLengthUpdated = true;

for (const auto& element : m_formData->elements())
m_totalSize += element.lengthInBytes();

return m_totalSize;
}

std::optional<size_t> CurlFormDataStream::read(char* buffer, size_t size)
Expand Down
6 changes: 0 additions & 6 deletions Source/WebCore/platform/network/curl/CurlFormDataStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,20 @@ class CurlFormDataStream {

void clean();

size_t elementSize() { return m_formData ? m_formData->elements().size() : 0; }

const Vector<uint8_t>* getPostData();
bool shouldUseChunkTransfer();
unsigned long long totalSize();

std::optional<size_t> read(char*, size_t);
unsigned long long totalReadSize() { return m_totalReadSize; }

private:
void computeContentLength();

std::optional<size_t> readFromFile(const FormDataElement::EncodedFileData&, char*, size_t);
std::optional<size_t> readFromData(const Vector<uint8_t>&, char*, size_t);

RefPtr<FormData> m_formData;

std::unique_ptr<Vector<uint8_t>> m_postData;
bool m_isContentLengthUpdated { false };
bool m_shouldUseChunkTransfer { false };
unsigned long long m_totalSize { 0 };
unsigned long long m_totalReadSize { 0 };

Expand Down
42 changes: 12 additions & 30 deletions Source/WebCore/platform/network/curl/CurlRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,46 +511,28 @@ void CurlRequest::appendAcceptLanguageHeader(HTTPHeaderMap& header)

void CurlRequest::setupPUT()
{
m_curlHandle->enableHttpPutRequest();
curl_off_t totalSize = m_formDataStream.totalSize();

// Disable the Expect: 100 continue header
m_curlHandle->removeRequestHeader("Expect"_s);

auto elementSize = m_formDataStream.elementSize();
if (!elementSize)
return;
m_curlHandle->enableHttpPutRequest(totalSize);
m_curlHandle->setReadCallbackFunction(willSendDataCallback, this);

setupSendData(true);
// Disable a "Expect: 100-continue" header
m_curlHandle->removeRequestHeader("Expect"_s);
}

void CurlRequest::setupPOST()
{
m_curlHandle->enableHttpPostRequest();
curl_off_t totalSize = m_formDataStream.totalSize();

auto elementSize = m_formDataStream.elementSize();
m_curlHandle->enableHttpPostRequest(totalSize);
m_curlHandle->setReadCallbackFunction(willSendDataCallback, this);

if (!m_request.hasHTTPHeader(HTTPHeaderName::ContentType) && !elementSize)
// Override the default POST Content-Type: header
if (!m_request.hasHTTPHeader(HTTPHeaderName::ContentType) && !totalSize)
m_curlHandle->removeRequestHeader("Content-Type"_s);

if (!elementSize)
return;

setupSendData(false);
}

void CurlRequest::setupSendData(bool forPutMethod)
{
// curl guesses that we want chunked encoding as long as we specify the header
if (m_formDataStream.shouldUseChunkTransfer())
m_curlHandle->appendRequestHeader("Transfer-Encoding: chunked"_s);
else {
if (forPutMethod)
m_curlHandle->setInFileSize(static_cast<curl_off_t>(m_formDataStream.totalSize()));
else
m_curlHandle->setPostFieldSize(static_cast<curl_off_t>(m_formDataStream.totalSize()));
}

m_curlHandle->setReadCallbackFunction(willSendDataCallback, this);
// Disable a "Expect: 100-continue" header
m_curlHandle->removeRequestHeader("Expect"_s);
}

void CurlRequest::invokeDidReceiveResponseForFile(const URL& url)
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/platform/network/curl/CurlRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ class CurlRequest : public ThreadSafeRefCounted<CurlRequest>, public CurlRequest
void appendAcceptLanguageHeader(HTTPHeaderMap&);
void setupPOST();
void setupPUT();
void setupSendData(bool forPutMethod);

// Processing for DidReceiveResponse
bool needToInvokeDidReceiveResponse() const { return m_didReceiveResponse && !m_didNotifyResponse; }
Expand Down

0 comments on commit 04637e9

Please sign in to comment.