mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-22 01:34:21 +00:00
Added a number-of-redirects parameter to URL::createInputStream
This commit is contained in:
parent
4d1a63fe3b
commit
268497e8bc
10 changed files with 285 additions and 102 deletions
|
|
@ -666,38 +666,103 @@ public final class JuceDemo extends Activity
|
|||
public static final HTTPStream createHTTPStream (String address,
|
||||
boolean isPost, byte[] postData, String headers,
|
||||
int timeOutMs, int[] statusCode,
|
||||
StringBuffer responseHeaders)
|
||||
StringBuffer responseHeaders,
|
||||
int numRedirectsToFollow)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpURLConnection connection = (HttpURLConnection) (new URL(address)
|
||||
.openConnection());
|
||||
if (connection != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (isPost)
|
||||
{
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setConnectTimeout(timeOutMs);
|
||||
connection.setDoOutput(true);
|
||||
connection.setChunkedStreamingMode(0);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
out.write(postData);
|
||||
out.flush();
|
||||
}
|
||||
// timeout parameter of zero for HttpUrlConnection is a blocking connect (negative value for juce::URL)
|
||||
if (timeOutMs < 0)
|
||||
timeOutMs = 0;
|
||||
else if (timeOutMs == 0)
|
||||
timeOutMs = 30000;
|
||||
|
||||
return new HTTPStream (connection, statusCode, responseHeaders);
|
||||
}
|
||||
catch (Throwable e)
|
||||
// headers - if not empty, this string is appended onto the headers that are used for the request. It must therefore be a valid set of HTML header directives, separated by newlines.
|
||||
// So convert headers string to an array, with an element for each line
|
||||
String headerLines[] = headers.split("\\n");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection());
|
||||
|
||||
if (connection != null)
|
||||
{
|
||||
connection.disconnect();
|
||||
try
|
||||
{
|
||||
connection.setInstanceFollowRedirects (false);
|
||||
connection.setConnectTimeout (timeOutMs);
|
||||
connection.setReadTimeout (timeOutMs);
|
||||
|
||||
// Set request headers
|
||||
for (int i = 0; i < headerLines.length; ++i)
|
||||
{
|
||||
int pos = headerLines[i].indexOf (":");
|
||||
|
||||
if (pos > 0 && pos < headerLines[i].length())
|
||||
{
|
||||
String field = headerLines[i].substring (0, pos);
|
||||
String value = headerLines[i].substring (pos + 1);
|
||||
|
||||
if (value.length() > 0)
|
||||
connection.setRequestProperty (field, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (isPost)
|
||||
{
|
||||
connection.setRequestMethod ("POST");
|
||||
connection.setDoOutput (true);
|
||||
|
||||
if (postData != null)
|
||||
{
|
||||
OutputStream out = connection.getOutputStream();
|
||||
out.write(postData);
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders);
|
||||
|
||||
// Process redirect & continue as necessary
|
||||
int status = statusCode[0];
|
||||
|
||||
if (--numRedirectsToFollow >= 0
|
||||
&& (status == 301 || status == 302 || status == 303 || status == 307))
|
||||
{
|
||||
// Assumes only one occurrence of "Location"
|
||||
int pos1 = responseHeaders.indexOf ("Location:") + 10;
|
||||
int pos2 = responseHeaders.indexOf ("\n", pos1);
|
||||
|
||||
if (pos2 > pos1)
|
||||
{
|
||||
String newLocation = responseHeaders.substring(pos1, pos2);
|
||||
// Handle newLocation whether it's absolute or relative
|
||||
URL baseUrl = new URL (address);
|
||||
URL newUrl = new URL (baseUrl, newLocation);
|
||||
String transformedNewLocation = newUrl.toString();
|
||||
|
||||
if (transformedNewLocation != address)
|
||||
{
|
||||
address = transformedNewLocation;
|
||||
// Clear responseHeaders before next iteration
|
||||
responseHeaders.delete (0, responseHeaders.length());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return httpStream;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {}
|
||||
catch (Throwable e) {}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public final void launchURL (String url)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@ extern bool juceDemoRepaintDebuggingActive;
|
|||
//#define JUCE_WASAPI
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_WASAPI_EXCLUSIVE
|
||||
//#define JUCE_WASAPI_EXCLUSIVE
|
||||
#endif
|
||||
|
||||
#ifndef JUCE_DIRECTSOUND
|
||||
//#define JUCE_DIRECTSOUND
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -666,38 +666,103 @@ public final class JuceAppActivity extends Activity
|
|||
public static final HTTPStream createHTTPStream (String address,
|
||||
boolean isPost, byte[] postData, String headers,
|
||||
int timeOutMs, int[] statusCode,
|
||||
StringBuffer responseHeaders)
|
||||
StringBuffer responseHeaders,
|
||||
int numRedirectsToFollow)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpURLConnection connection = (HttpURLConnection) (new URL(address)
|
||||
.openConnection());
|
||||
if (connection != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (isPost)
|
||||
{
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setConnectTimeout(timeOutMs);
|
||||
connection.setDoOutput(true);
|
||||
connection.setChunkedStreamingMode(0);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
out.write(postData);
|
||||
out.flush();
|
||||
}
|
||||
// timeout parameter of zero for HttpUrlConnection is a blocking connect (negative value for juce::URL)
|
||||
if (timeOutMs < 0)
|
||||
timeOutMs = 0;
|
||||
else if (timeOutMs == 0)
|
||||
timeOutMs = 30000;
|
||||
|
||||
return new HTTPStream (connection, statusCode, responseHeaders);
|
||||
}
|
||||
catch (Throwable e)
|
||||
// headers - if not empty, this string is appended onto the headers that are used for the request. It must therefore be a valid set of HTML header directives, separated by newlines.
|
||||
// So convert headers string to an array, with an element for each line
|
||||
String headerLines[] = headers.split("\\n");
|
||||
|
||||
for (;;)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection());
|
||||
|
||||
if (connection != null)
|
||||
{
|
||||
connection.disconnect();
|
||||
try
|
||||
{
|
||||
connection.setInstanceFollowRedirects (false);
|
||||
connection.setConnectTimeout (timeOutMs);
|
||||
connection.setReadTimeout (timeOutMs);
|
||||
|
||||
// Set request headers
|
||||
for (int i = 0; i < headerLines.length; ++i)
|
||||
{
|
||||
int pos = headerLines[i].indexOf (":");
|
||||
|
||||
if (pos > 0 && pos < headerLines[i].length())
|
||||
{
|
||||
String field = headerLines[i].substring (0, pos);
|
||||
String value = headerLines[i].substring (pos + 1);
|
||||
|
||||
if (value.length() > 0)
|
||||
connection.setRequestProperty (field, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (isPost)
|
||||
{
|
||||
connection.setRequestMethod ("POST");
|
||||
connection.setDoOutput (true);
|
||||
|
||||
if (postData != null)
|
||||
{
|
||||
OutputStream out = connection.getOutputStream();
|
||||
out.write(postData);
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders);
|
||||
|
||||
// Process redirect & continue as necessary
|
||||
int status = statusCode[0];
|
||||
|
||||
if (--numRedirectsToFollow >= 0
|
||||
&& (status == 301 || status == 302 || status == 303 || status == 307))
|
||||
{
|
||||
// Assumes only one occurrence of "Location"
|
||||
int pos1 = responseHeaders.indexOf ("Location:") + 10;
|
||||
int pos2 = responseHeaders.indexOf ("\n", pos1);
|
||||
|
||||
if (pos2 > pos1)
|
||||
{
|
||||
String newLocation = responseHeaders.substring(pos1, pos2);
|
||||
// Handle newLocation whether it's absolute or relative
|
||||
URL baseUrl = new URL (address);
|
||||
URL newUrl = new URL (baseUrl, newLocation);
|
||||
String transformedNewLocation = newUrl.toString();
|
||||
|
||||
if (transformedNewLocation != address)
|
||||
{
|
||||
address = transformedNewLocation;
|
||||
// Clear responseHeaders before next iteration
|
||||
responseHeaders.delete (0, responseHeaders.length());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return httpStream;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable e) {}
|
||||
catch (Throwable e) {}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public final void launchURL (String url)
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ struct AndroidThreadScope
|
|||
METHOD (setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \
|
||||
METHOD (excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \
|
||||
METHOD (renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \
|
||||
STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;I[ILjava/lang/StringBuffer;)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \
|
||||
STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;I[ILjava/lang/StringBuffer;I)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \
|
||||
METHOD (launchURL, "launchURL", "(Ljava/lang/String;)V") \
|
||||
METHOD (showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
|
||||
METHOD (showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class WebInputStream : public InputStream
|
|||
public:
|
||||
WebInputStream (String address, bool isPost, const MemoryBlock& postData,
|
||||
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers, int timeOutMs, StringPairArray* responseHeaders)
|
||||
const String& headers, int timeOutMs, StringPairArray* responseHeaders, const int numRedirectsToFollow)
|
||||
: statusCode (0)
|
||||
{
|
||||
if (! address.contains ("://"))
|
||||
|
|
@ -103,7 +103,8 @@ public:
|
|||
javaString (headers).get(),
|
||||
(jint) timeOutMs,
|
||||
statusCodeArray,
|
||||
responseHeaderBuffer.get()));
|
||||
responseHeaderBuffer.get(),
|
||||
(jint) numRedirectsToFollow));
|
||||
|
||||
jint* const statusCodeElements = env->GetIntArrayElements (statusCodeArray, 0);
|
||||
statusCode = statusCodeElements[0];
|
||||
|
|
|
|||
|
|
@ -74,12 +74,13 @@ class WebInputStream : public InputStream
|
|||
public:
|
||||
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
|
||||
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
|
||||
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders,
|
||||
const int maxRedirects)
|
||||
: statusCode (0), socketHandle (-1), levelsOfRedirection (0),
|
||||
address (address_), headers (headers_), postData (postData_), position (0),
|
||||
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
|
||||
finished (false), isPost (isPost_), timeOutMs (timeOutMs_), numRedirectsToFollow (maxRedirects)
|
||||
{
|
||||
statusCode = createConnection (progressCallback, progressCallbackContext);
|
||||
statusCode = createConnection (progressCallback, progressCallbackContext, numRedirectsToFollow);
|
||||
|
||||
if (responseHeaders != nullptr && ! isError())
|
||||
{
|
||||
|
|
@ -147,7 +148,7 @@ public:
|
|||
{
|
||||
closeSocket();
|
||||
position = 0;
|
||||
statusCode = createConnection (0, 0);
|
||||
statusCode = createConnection (0, 0, numRedirectsToFollow);
|
||||
}
|
||||
|
||||
skipNextBytes (wantedPos - position);
|
||||
|
|
@ -168,24 +169,27 @@ private:
|
|||
bool finished;
|
||||
const bool isPost;
|
||||
const int timeOutMs;
|
||||
const int numRedirectsToFollow;
|
||||
|
||||
void closeSocket()
|
||||
void closeSocket (bool resetLevelsOfRedirection = true)
|
||||
{
|
||||
if (socketHandle >= 0)
|
||||
close (socketHandle);
|
||||
|
||||
socketHandle = -1;
|
||||
levelsOfRedirection = 0;
|
||||
if (resetLevelsOfRedirection)
|
||||
levelsOfRedirection = 0;
|
||||
}
|
||||
|
||||
int createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
|
||||
int createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const int numRedirectsToFollow)
|
||||
{
|
||||
closeSocket();
|
||||
closeSocket (false);
|
||||
|
||||
uint32 timeOutTime = Time::getMillisecondCounter();
|
||||
|
||||
if (timeOutMs == 0)
|
||||
timeOutTime += 60000;
|
||||
timeOutTime += 30000;
|
||||
else if (timeOutMs < 0)
|
||||
timeOutTime = 0xffffffff;
|
||||
else
|
||||
|
|
@ -273,28 +277,28 @@ private:
|
|||
const int status = responseHeader.fromFirstOccurrenceOf (" ", false, false)
|
||||
.substring (0, 3).getIntValue();
|
||||
|
||||
//int contentLength = findHeaderItem (lines, "Content-Length:").getIntValue();
|
||||
//bool isChunked = findHeaderItem (lines, "Transfer-Encoding:").equalsIgnoreCase ("chunked");
|
||||
|
||||
String location (findHeaderItem (headerLines, "Location:"));
|
||||
|
||||
if (status >= 300 && status < 400
|
||||
if (++levelsOfRedirection <= numRedirectsToFollow
|
||||
&& status >= 300 && status < 400
|
||||
&& location.isNotEmpty() && location != address)
|
||||
{
|
||||
if (! location.startsWithIgnoreCase ("http://"))
|
||||
location = "http://" + location;
|
||||
|
||||
if (++levelsOfRedirection <= 3)
|
||||
if (! (location.startsWithIgnoreCase ("http://")
|
||||
|| location.startsWithIgnoreCase ("https://")
|
||||
|| location.startsWithIgnoreCase ("ftp://")))
|
||||
{
|
||||
address = location;
|
||||
return createConnection (progressCallback, progressCallbackContext);
|
||||
// The following is a bit dodgy. Ideally, we should do a proper transform of the relative URI to a target URI
|
||||
if (location.startsWithChar ('/'))
|
||||
location = URL (address).withNewSubPath (location).toString (true);
|
||||
else
|
||||
location = address + "/" + location;
|
||||
}
|
||||
|
||||
address = location;
|
||||
return createConnection (progressCallback, progressCallbackContext, numRedirectsToFollow);
|
||||
}
|
||||
else
|
||||
{
|
||||
levelsOfRedirection = 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
closeSocket();
|
||||
|
|
@ -363,10 +367,14 @@ private:
|
|||
writeValueIfNotPresent (header, userHeaders, "Connection:", "close");
|
||||
|
||||
if (isPost)
|
||||
{
|
||||
writeValueIfNotPresent (header, userHeaders, "Content-Length:", String ((int) postData.getSize()));
|
||||
|
||||
header << "\r\n" << userHeaders
|
||||
<< "\r\n" << postData;
|
||||
header << userHeaders << "\r\n" << postData;
|
||||
}
|
||||
else
|
||||
{
|
||||
header << "\r\n" << userHeaders << "\r\n";
|
||||
}
|
||||
|
||||
return header.getMemoryBlock();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& targetEmailA
|
|||
class URLConnectionState : public Thread
|
||||
{
|
||||
public:
|
||||
URLConnectionState (NSURLRequest* req)
|
||||
URLConnectionState (NSURLRequest* req, const int maxRedirects)
|
||||
: Thread ("http connection"),
|
||||
contentLength (-1),
|
||||
delegate (nil),
|
||||
|
|
@ -126,7 +126,9 @@ public:
|
|||
statusCode (0),
|
||||
initialised (false),
|
||||
hasFailed (false),
|
||||
hasFinished (false)
|
||||
hasFinished (false),
|
||||
numRedirectsToFollow (maxRedirects),
|
||||
numRedirects (0)
|
||||
{
|
||||
static DelegateClass cls;
|
||||
delegate = [cls.createInstance() init];
|
||||
|
|
@ -215,6 +217,19 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
NSURLRequest* willSendRequest (NSURLRequest* newRequest, NSURLResponse* redirectResponse)
|
||||
{
|
||||
if (redirectResponse != nullptr)
|
||||
{
|
||||
if (numRedirects >= numRedirectsToFollow)
|
||||
return nil; // Cancel redirect and allow connection to continue
|
||||
|
||||
++numRedirects;
|
||||
}
|
||||
|
||||
return newRequest;
|
||||
}
|
||||
|
||||
void didFailWithError (NSError* error)
|
||||
{
|
||||
DBG (nsStringToJuce ([error description])); (void) error;
|
||||
|
|
@ -263,6 +278,8 @@ public:
|
|||
NSDictionary* headers;
|
||||
int statusCode;
|
||||
bool initialised, hasFailed, hasFinished;
|
||||
const int numRedirectsToFollow;
|
||||
int numRedirects;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
|
|
@ -278,7 +295,7 @@ private:
|
|||
addMethod (@selector (connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:),
|
||||
connectionDidSendBodyData, "v@:@iii");
|
||||
addMethod (@selector (connectionDidFinishLoading:), connectionDidFinishLoading, "v@:@");
|
||||
addMethod (@selector (connection:willSendRequest:redirectResponse:), willSendRequest, "@@:@@");
|
||||
addMethod (@selector (connection:willSendRequest:redirectResponse:), willSendRequest, "@@:@@@");
|
||||
|
||||
registerClass();
|
||||
}
|
||||
|
|
@ -302,9 +319,9 @@ private:
|
|||
getState (self)->didReceiveData (newData);
|
||||
}
|
||||
|
||||
static NSURLRequest* willSendRequest (id, SEL, NSURLConnection*, NSURLRequest* request, NSURLResponse*)
|
||||
static NSURLRequest* willSendRequest (id self, SEL, NSURLConnection*, NSURLRequest* request, NSURLResponse* response)
|
||||
{
|
||||
return request;
|
||||
return getState (self)->willSendRequest (request, response);
|
||||
}
|
||||
|
||||
static void connectionDidSendBodyData (id self, SEL, NSURLConnection*, NSInteger, NSInteger totalBytesWritten, NSInteger totalBytesExpected)
|
||||
|
|
@ -328,23 +345,27 @@ class WebInputStream : public InputStream
|
|||
public:
|
||||
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
|
||||
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
|
||||
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders,
|
||||
const int numRedirectsToFollow_)
|
||||
: statusCode (0), address (address_), headers (headers_), postData (postData_), position (0),
|
||||
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
|
||||
finished (false), isPost (isPost_), timeOutMs (timeOutMs_), numRedirectsToFollow (numRedirectsToFollow_)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
createConnection (progressCallback, progressCallbackContext);
|
||||
|
||||
if (responseHeaders != nullptr && connection != nullptr && connection->headers != nil)
|
||||
if (connection != nullptr && connection->headers != nil)
|
||||
{
|
||||
statusCode = connection->statusCode;
|
||||
|
||||
NSEnumerator* enumerator = [connection->headers keyEnumerator];
|
||||
if (responseHeaders != nullptr)
|
||||
{
|
||||
NSEnumerator* enumerator = [connection->headers keyEnumerator];
|
||||
|
||||
while (NSString* key = [enumerator nextObject])
|
||||
responseHeaders->set (nsStringToJuce (key),
|
||||
nsStringToJuce ((NSString*) [connection->headers objectForKey: key]));
|
||||
while (NSString* key = [enumerator nextObject])
|
||||
responseHeaders->set (nsStringToJuce (key),
|
||||
nsStringToJuce ((NSString*) [connection->headers objectForKey: key]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -403,6 +424,7 @@ private:
|
|||
bool finished;
|
||||
const bool isPost;
|
||||
const int timeOutMs;
|
||||
const int numRedirectsToFollow;
|
||||
|
||||
void createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
|
||||
{
|
||||
|
|
@ -434,7 +456,7 @@ private:
|
|||
[req setHTTPBody: [NSData dataWithBytes: postData.getData()
|
||||
length: postData.getSize()]];
|
||||
|
||||
connection = new URLConnectionState (req);
|
||||
connection = new URLConnectionState (req, numRedirectsToFollow);
|
||||
|
||||
if (! connection->start (progressCallback, progressCallbackContext))
|
||||
connection = nullptr;
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@ class WebInputStream : public InputStream
|
|||
public:
|
||||
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
|
||||
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
|
||||
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders, int numRedirectsToFollow)
|
||||
: statusCode (0), connection (0), request (0),
|
||||
address (address_), headers (headers_), postData (postData_), position (0),
|
||||
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
|
||||
{
|
||||
for (int maxRedirects = 10; --maxRedirects >= 0;)
|
||||
while (numRedirectsToFollow-- >= 0)
|
||||
{
|
||||
createConnection (progressCallback, progressCallbackContext);
|
||||
|
||||
|
|
@ -88,9 +88,22 @@ public:
|
|||
{
|
||||
statusCode = (int) status;
|
||||
|
||||
if (status == 301 || status == 302 || status == 303 || status == 307)
|
||||
if (numRedirectsToFollow >= 0
|
||||
&& (statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 307))
|
||||
{
|
||||
const String newLocation (headers["Location"]);
|
||||
String newLocation (headers["Location"]);
|
||||
|
||||
// Check whether location is a relative URI - this is an incomplete test for relative path,
|
||||
// but we'll use it for now (valid protocols for this implementation are http, https & ftp)
|
||||
if (! (newLocation.startsWithIgnoreCase ("http://")
|
||||
|| newLocation.startsWithIgnoreCase ("https://")
|
||||
|| newLocation.startsWithIgnoreCase ("ftp://")))
|
||||
{
|
||||
if (newLocation.startsWithChar ('/'))
|
||||
newLocation = URL (address).withNewSubPath (newLocation).toString (true);
|
||||
else
|
||||
newLocation = address + "/" + newLocation;
|
||||
}
|
||||
|
||||
if (newLocation.isNotEmpty() && newLocation != address)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -334,7 +334,8 @@ InputStream* URL::createInputStream (const bool usePostCommand,
|
|||
String headers,
|
||||
const int timeOutMs,
|
||||
StringPairArray* const responseHeaders,
|
||||
int* statusCode) const
|
||||
int* statusCode,
|
||||
const int numRedirectsToFollow) const
|
||||
{
|
||||
MemoryBlock headersAndPostData;
|
||||
|
||||
|
|
@ -350,7 +351,8 @@ InputStream* URL::createInputStream (const bool usePostCommand,
|
|||
ScopedPointer<WebInputStream> wi (new WebInputStream (toString (! usePostCommand),
|
||||
usePostCommand, headersAndPostData,
|
||||
progressCallback, progressCallbackContext,
|
||||
headers, timeOutMs, responseHeaders));
|
||||
headers, timeOutMs, responseHeaders,
|
||||
numRedirectsToFollow));
|
||||
|
||||
if (statusCode != nullptr)
|
||||
*statusCode = wi->statusCode;
|
||||
|
|
|
|||
|
|
@ -266,6 +266,8 @@ public:
|
|||
in the response will be stored in this array
|
||||
@param statusCode if this is non-null, it will get set to the http status code, if one
|
||||
is known, or 0 if a code isn't available
|
||||
@param numRedirectsToFollow specifies the number of redirects that will be followed before
|
||||
returning a response (ignored for Android which follows up to 5 redirects)
|
||||
@returns an input stream that the caller must delete, or a null pointer if there was an
|
||||
error trying to open it.
|
||||
*/
|
||||
|
|
@ -275,7 +277,8 @@ public:
|
|||
String extraHeaders = String(),
|
||||
int connectionTimeOutMs = 0,
|
||||
StringPairArray* responseHeaders = nullptr,
|
||||
int* statusCode = nullptr) const;
|
||||
int* statusCode = nullptr,
|
||||
int numRedirectsToFollow = 5) const;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue