1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-29 02:40:05 +00:00

URL: Fixed backwards compatibility of URL::createInputStream() when specifying a POST-like request with parameters and no POST data

This commit is contained in:
ed 2021-03-13 12:37:31 +00:00
parent 7d71efe6e0
commit 77d4ac7242
8 changed files with 82 additions and 55 deletions

View file

@ -324,11 +324,12 @@ class WebInputStream::Pimpl
public:
enum { contentStreamCacheSize = 1024 };
Pimpl (WebInputStream&, const URL& urlToCopy, bool isPOSTLike)
Pimpl (WebInputStream&, const URL& urlToCopy, bool addParametersToBody)
: url (urlToCopy),
isContentURL (urlToCopy.getScheme() == "content"),
addParametersToRequestBody (isPOSTLike),
httpRequest (isPOSTLike || url.hasPOSTData() ? "POST" : "GET")
addParametersToRequestBody (addParametersToBody),
hasBodyDataToSend (addParametersToRequestBody || url.hasBodyDataToSend()),
httpRequest (hasBodyDataToSend ? "POST" : "GET")
{
}
@ -380,8 +381,12 @@ public:
address = "http://" + address;
MemoryBlock postData;
if (url.hasPOSTData())
WebInputStream::createHeadersAndPostData (url, headers, postData, addParametersToRequestBody);
if (hasBodyDataToSend)
WebInputStream::createHeadersAndPostData (url,
headers,
postData,
addParametersToRequestBody);
jbyteArray postDataArray = nullptr;
@ -536,7 +541,7 @@ public:
private:
const URL url;
const bool isContentURL, addParametersToRequestBody;
const bool isContentURL, addParametersToRequestBody, hasBodyDataToSend;
bool eofStreamReached = false;
int numRedirectsToFollow = 5, timeOutMs = 0;
String httpRequest, headers;

View file

@ -110,12 +110,12 @@ private:
class WebInputStream::Pimpl
{
public:
Pimpl (WebInputStream& ownerStream, const URL& urlToCopy, bool isPOSTLike)
Pimpl (WebInputStream& ownerStream, const URL& urlToCopy, bool addParametersToBody)
: owner (ownerStream),
url (urlToCopy),
addParametersToRequestBody (isPOSTLike),
hasPOSTData (url.hasPOSTData()),
httpRequest (isPOSTLike || url.hasPOSTData() ? "POST" : "GET")
addParametersToRequestBody (addParametersToBody),
hasBodyDataToSend (url.hasBodyDataToSend() || addParametersToRequestBody),
httpRequest (hasBodyDataToSend ? "POST" : "GET")
{
jassert (symbols); // Unable to load libcurl!
@ -231,8 +231,11 @@ public:
if (! requestHeaders.endsWithChar ('\n'))
requestHeaders << "\r\n";
if (hasPOSTData)
WebInputStream::createHeadersAndPostData (url, requestHeaders, headersAndPostData, addParametersToRequestBody);
if (hasBodyDataToSend)
WebInputStream::createHeadersAndPostData (url,
requestHeaders,
headersAndPostData,
addParametersToRequestBody);
if (! requestHeaders.endsWithChar ('\n'))
requestHeaders << "\r\n";
@ -247,7 +250,7 @@ public:
&& symbols->curl_easy_setopt (curl, CURLOPT_USERAGENT, userAgent.toRawUTF8()) == CURLE_OK
&& symbols->curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, (maxRedirects > 0 ? 1 : 0)) == CURLE_OK)
{
if (hasPOSTData)
if (hasBodyDataToSend)
{
if (symbols->curl_easy_setopt (curl, CURLOPT_READDATA, this) != CURLE_OK
|| symbols->curl_easy_setopt (curl, CURLOPT_READFUNCTION, StaticCurlRead) != CURLE_OK)
@ -259,7 +262,7 @@ public:
}
// handle special http request commands
const auto hasSpecialRequestCmd = hasPOSTData ? (httpRequest != "POST") : (httpRequest != "GET");
const auto hasSpecialRequestCmd = hasBodyDataToSend ? (httpRequest != "POST") : (httpRequest != "GET");
if (hasSpecialRequestCmd)
if (symbols->curl_easy_setopt (curl, CURLOPT_CUSTOMREQUEST, httpRequest.toRawUTF8()) != CURLE_OK)
@ -326,7 +329,7 @@ public:
listener = webInputListener;
if (hasPOSTData)
if (hasBodyDataToSend)
postBuffer = &headersAndPostData;
size_t lastPos = static_cast<size_t> (-1);
@ -345,7 +348,7 @@ public:
singleStep();
// call callbacks if this is a post request
if (hasPOSTData && listener != nullptr && lastPos != postPosition)
if (hasBodyDataToSend && listener != nullptr && lastPos != postPosition)
{
lastPos = postPosition;
@ -616,7 +619,7 @@ public:
// Options
int timeOutMs = 0;
int maxRedirects = 5;
const bool addParametersToRequestBody, hasPOSTData;
const bool addParametersToRequestBody, hasBodyDataToSend;
String httpRequest;
//==============================================================================

View file

@ -70,11 +70,12 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& /* targetEma
class WebInputStream::Pimpl
{
public:
Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, bool isPOSTLike)
Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, bool addParametersToBody)
: owner (pimplOwner),
url (urlToCopy),
addParametersToRequestBody (isPOSTLike),
httpRequestCmd (isPOSTLike || url.hasPOSTData() ? "POST" : "GET")
addParametersToRequestBody (addParametersToBody),
hasBodyDataToSend (addParametersToRequestBody || url.hasBodyDataToSend()),
httpRequestCmd (hasBodyDataToSend ? "POST" : "GET")
{
}
@ -259,7 +260,7 @@ private:
MemoryBlock postData;
int64 contentLength = -1, position = 0;
bool finished = false;
const bool addParametersToRequestBody;
const bool addParametersToRequestBody, hasBodyDataToSend;
int timeOutMs = 0;
int numRedirectsToFollow = 5;
String httpRequestCmd;
@ -288,8 +289,11 @@ private:
{
closeSocket (false);
if (url.hasPOSTData())
WebInputStream::createHeadersAndPostData (url, headers, postData, addParametersToRequestBody);
if (hasBodyDataToSend)
WebInputStream::createHeadersAndPostData (url,
headers,
postData,
addParametersToRequestBody);
auto timeOutTime = Time::getMillisecondCounter();

View file

@ -943,11 +943,12 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE
class WebInputStream::Pimpl
{
public:
Pimpl (WebInputStream& pimplOwner, const URL& urlToUse, bool isPOSTLike)
Pimpl (WebInputStream& pimplOwner, const URL& urlToUse, bool addParametersToBody)
: owner (pimplOwner),
url (urlToUse),
addParametersToRequestBody (isPOSTLike),
httpRequestCmd (isPOSTLike || url.hasPOSTData() ? "POST" : "GET")
addParametersToRequestBody (addParametersToBody),
hasBodyDataToSend (addParametersToRequestBody || url.hasBodyDataToSend()),
httpRequestCmd (hasBodyDataToSend ? "POST" : "GET")
{
}
@ -1091,7 +1092,7 @@ private:
MemoryBlock postData;
int64 position = 0;
bool finished = false;
const bool addParametersToRequestBody;
const bool addParametersToRequestBody, hasBodyDataToSend;
int timeOutMs = 0;
int numRedirectsToFollow = 5;
String httpRequestCmd;
@ -1113,9 +1114,12 @@ private:
{
[req setHTTPMethod: httpMethod];
if (url.hasPOSTData())
if (hasBodyDataToSend)
{
WebInputStream::createHeadersAndPostData (url, headers, postData, addParametersToRequestBody);
WebInputStream::createHeadersAndPostData (url,
headers,
postData,
addParametersToRequestBody);
if (postData.getSize() > 0)
[req setHTTPBody: [NSData dataWithBytes: postData.getData()

View file

@ -35,11 +35,12 @@ namespace juce
class WebInputStream::Pimpl
{
public:
Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, bool isPOSTLike)
Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, bool addParametersToBody)
: owner (pimplOwner),
url (urlToCopy),
addParametersToRequestBody (isPOSTLike),
httpRequestCmd (isPOSTLike || url.hasPOSTData() ? "POST" : "GET")
addParametersToRequestBody (addParametersToBody),
hasBodyDataToSend (addParametersToRequestBody || url.hasBodyDataToSend()),
httpRequestCmd (hasBodyDataToSend ? "POST" : "GET")
{
}
@ -240,7 +241,7 @@ private:
MemoryBlock postData;
int64 position = 0;
bool finished = false;
const bool addParametersToRequestBody;
const bool addParametersToRequestBody, hasBodyDataToSend;
int timeOutMs = 0;
String httpRequestCmd;
int numRedirectsToFollow = 5;
@ -291,8 +292,11 @@ private:
uc.lpszPassword = password;
uc.dwPasswordLength = passwordNumChars;
if (url.hasPOSTData())
WebInputStream::createHeadersAndPostData (url, headers, postData, addParametersToRequestBody);
if (hasBodyDataToSend)
WebInputStream::createHeadersAndPostData (url,
headers,
postData,
addParametersToRequestBody);
if (InternetCrackUrl (address.toWideCharPointer(), 0, 0, &uc))
openConnection (uc, sessionHandle, address, listener);

View file

@ -452,6 +452,11 @@ URL URL::getChildURL (const String& subPath) const
return u;
}
bool URL::hasBodyDataToSend() const
{
return filesToUpload.size() > 0 || postData.getSize() > 0;
}
void URL::createHeadersAndPostData (String& headers,
MemoryBlock& postDataToWrite,
bool addParametersToBody) const
@ -499,9 +504,9 @@ void URL::createHeadersAndPostData (String& headers,
else
{
if (addParametersToBody)
data << URLHelpers::getMangledParameters (*this) << postData;
else
data << postData;
data << URLHelpers::getMangledParameters (*this);
data << postData;
// if the user-supplied headers didn't contain a content-type, add one now..
if (! headers.containsIgnoreCase ("Content-Type"))
@ -886,7 +891,7 @@ URL URL::withUpload (Upload* const f) const
auto u = *this;
for (int i = u.filesToUpload.size(); --i >= 0;)
if (u.filesToUpload.getObjectPointerUnchecked(i)->parameterName == f->parameterName)
if (u.filesToUpload.getObjectPointerUnchecked (i)->parameterName == f->parameterName)
u.filesToUpload.remove (i);
u.filesToUpload.add (f);

View file

@ -282,9 +282,6 @@ public:
/** Returns the data that was set using withPOSTData() as a MemoryBlock. */
const MemoryBlock& getPostDataAsMemoryBlock() const noexcept { return postData; }
/** Returns true if this URL has POST data set using withPOSTData(). */
bool hasPOSTData() const noexcept { return postData.getSize() > 0; }
//==============================================================================
/** Tries to launch the system's default browser to open the URL.
@ -303,21 +300,22 @@ public:
*/
static bool isProbablyAnEmailAddress (const String& possibleEmailAddress);
//==============================================================================
enum class ParameterHandling
{
inAddress,
inPostData
};
//==============================================================================
/** Class used to create a set of options to pass to the createInputStream() method.
You can chain together a series of calls to this class's methods to create
a set of whatever options you want to specify, e.g.
@code
if (auto inputStream = URL ("http://www.xyz.com/foobar")
.createInputStream (URL::InputStreamOptions (false).withConnectionTimeoutMs (1000)
.withNumRedirectsToFollow (0)))
.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)
.withConnectionTimeoutMs (1000)
.withNumRedirectsToFollow (0)))
{
...
}
@ -328,10 +326,9 @@ public:
public:
/** Constructor.
If parameterHandling is ParameterHandling::inPostData and the URL contains some
POST data to send set via one of its withPOSTData() methods, the URL parameters
will be transferred via the request body data. Otherwise the parameters will
be added to the URL address.
If parameterHandling is ParameterHandling::inPostData, any URL parameters
that have been set will be transferred via the request body data. Otherwise
the parameters will be added to the URL address.
*/
explicit InputStreamOptions (ParameterHandling parameterHandling);
@ -371,10 +368,12 @@ public:
*/
InputStreamOptions withNumRedirectsToFollow (int numRedirectsToFollow) const;
/** Specifies which HTTP request to use.
/** Specifies which HTTP request command to use.
If this is not set, then this will be determined by the value of `doPostLikeRequest`
or the presence of POST data set via URL::withPOSTData().
If this is not set, then the command will be POST if parameterHandling is
set to ParameterHandling::inPostData or if any POST data has been specified
via withPOSTData(), withFileToUpload(), or withDataToUpload(). Otherwise it
will be GET.
*/
InputStreamOptions withHttpRequestCmd (const String& httpRequestCmd) const;
@ -666,6 +665,7 @@ private:
URL (const String&, int);
void init();
void addParameter (const String&, const String&);
bool hasBodyDataToSend() const;
void createHeadersAndPostData (String&, MemoryBlock&, bool) const;
URL withUpload (Upload*) const;

View file

@ -36,10 +36,12 @@ class JUCE_API WebInputStream : public InputStream
@param url The URL that should be retrieved. This parameter may also contain
POST data and/or parameters.
@param usePost Specifies whether a GET or a POST command should be used. This
parameter will also influence the way parameters are encoded.
@param addParametersToRequestBody Specifies whether any URL parameters that have
been set will be transferred via the request body data or added
to the URL address. This will also determine whether a POST or GET
command will be used if a custom command is not set.
*/
WebInputStream (const URL& url, bool usePost);
WebInputStream (const URL& url, bool addParametersToRequestBody);
/** Destructor. */
~WebInputStream() override;