mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-23 01:44:22 +00:00
Added http status code access for URL::createInputStream(). Also added threading + header display to the demo's http page.
This commit is contained in:
parent
14a5fcf410
commit
4889822eaf
11 changed files with 205 additions and 132 deletions
|
|
@ -589,10 +589,34 @@ public final class JuceDemo extends Activity
|
|||
//==============================================================================
|
||||
public static class HTTPStream
|
||||
{
|
||||
public HTTPStream (HttpURLConnection connection_) throws IOException
|
||||
public HTTPStream (HttpURLConnection connection_,
|
||||
int[] statusCode, StringBuffer responseHeaders) throws IOException
|
||||
{
|
||||
connection = connection_;
|
||||
inputStream = new BufferedInputStream (connection.getInputStream());
|
||||
|
||||
try
|
||||
{
|
||||
inputStream = new BufferedInputStream (connection.getInputStream());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
if (connection.getResponseCode() < org.apache.http.HttpStatus.SC_BAD_REQUEST)
|
||||
throw e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
statusCode[0] = connection.getResponseCode();
|
||||
}
|
||||
|
||||
if (statusCode[0] >= org.apache.http.HttpStatus.SC_BAD_REQUEST)
|
||||
inputStream = connection.getErrorStream();
|
||||
else
|
||||
inputStream = connection.getInputStream();
|
||||
|
||||
for (java.util.Map.Entry<String, java.util.List<String>> entry : connection.getHeaderFields().entrySet())
|
||||
if (entry.getKey() != null && entry.getValue() != null)
|
||||
responseHeaders.append (entry.getKey() + ": "
|
||||
+ android.text.TextUtils.join (",", entry.getValue()) + "\n");
|
||||
}
|
||||
|
||||
public final void release()
|
||||
|
|
@ -634,30 +658,31 @@ public final class JuceDemo extends Activity
|
|||
private long position;
|
||||
}
|
||||
|
||||
public static final HTTPStream createHTTPStream (String address, boolean isPost, byte[] postData,
|
||||
String headers, int timeOutMs,
|
||||
java.lang.StringBuffer responseHeaders)
|
||||
public static final HTTPStream createHTTPStream (String address,
|
||||
boolean isPost, byte[] postData, String headers,
|
||||
int timeOutMs, int[] statusCode,
|
||||
StringBuffer responseHeaders)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpURLConnection connection = (HttpURLConnection) (new URL (address).openConnection());
|
||||
|
||||
HttpURLConnection connection = (HttpURLConnection) (new URL(address)
|
||||
.openConnection());
|
||||
if (connection != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (isPost)
|
||||
{
|
||||
connection.setConnectTimeout (timeOutMs);
|
||||
connection.setDoOutput (true);
|
||||
connection.setChunkedStreamingMode (0);
|
||||
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setConnectTimeout(timeOutMs);
|
||||
connection.setDoOutput(true);
|
||||
connection.setChunkedStreamingMode(0);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
out.write (postData);
|
||||
out.write(postData);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
return new HTTPStream (connection);
|
||||
return new HTTPStream (connection, statusCode, responseHeaders);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
|
@ -665,8 +690,7 @@ public final class JuceDemo extends Activity
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{}
|
||||
catch (Throwable e) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,13 @@
|
|||
|
||||
//==============================================================================
|
||||
class NetworkingDemo : public Component,
|
||||
private Button::Listener
|
||||
private Button::Listener,
|
||||
private Thread
|
||||
{
|
||||
public:
|
||||
NetworkingDemo()
|
||||
: resultsBox (resultsDocument, nullptr)
|
||||
: Thread ("Network Demo"),
|
||||
resultsBox (resultsDocument, nullptr)
|
||||
{
|
||||
setOpaque (true);
|
||||
|
||||
|
|
@ -69,6 +71,37 @@ public:
|
|||
resultsBox.setBounds (area.reduced (8));
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
String result (getResultText (urlBox.getText()));
|
||||
|
||||
MessageManagerLock mml (this);
|
||||
|
||||
if (mml.lockWasGained())
|
||||
resultsBox.loadContent (result);
|
||||
}
|
||||
|
||||
String getResultText (const URL& url)
|
||||
{
|
||||
StringPairArray responseHeaders;
|
||||
int statusCode = 0;
|
||||
|
||||
ScopedPointer<InputStream> stream (url.createInputStream (false, nullptr, nullptr, String(),
|
||||
10000, // timeout in millisecs
|
||||
&responseHeaders, &statusCode));
|
||||
if (stream != nullptr)
|
||||
return (statusCode != 0 ? "Status code: " + String (statusCode) + newLine : String())
|
||||
+ "Response headers: " + newLine
|
||||
+ responseHeaders.getDescription() + newLine
|
||||
+ "----------------------------------------------------" + newLine
|
||||
+ stream->readEntireStreamAsString();
|
||||
|
||||
if (statusCode != 0)
|
||||
return "Failed to connect, status code = " + String (statusCode);
|
||||
|
||||
return "Failed to connect!";
|
||||
}
|
||||
|
||||
private:
|
||||
TextEditor urlBox;
|
||||
TextButton fetchButton;
|
||||
|
|
@ -76,16 +109,10 @@ private:
|
|||
CodeDocument resultsDocument;
|
||||
CodeEditorComponent resultsBox;
|
||||
|
||||
void downloadUrl()
|
||||
{
|
||||
URL url (urlBox.getText());
|
||||
resultsBox.loadContent (url.readEntireTextStream());
|
||||
}
|
||||
|
||||
void buttonClicked (Button* button) override
|
||||
{
|
||||
if (button == &fetchButton)
|
||||
downloadUrl();
|
||||
startThread();
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NetworkingDemo)
|
||||
|
|
|
|||
|
|
@ -133,7 +133,6 @@ namespace juce
|
|||
#include "network/juce_MACAddress.cpp"
|
||||
#include "network/juce_NamedPipe.cpp"
|
||||
#include "network/juce_Socket.cpp"
|
||||
#include "network/juce_URL.cpp"
|
||||
#include "network/juce_IPAddress.cpp"
|
||||
#include "streams/juce_BufferedInputStream.cpp"
|
||||
#include "streams/juce_FileInputSource.cpp"
|
||||
|
|
@ -219,5 +218,6 @@ namespace juce
|
|||
|
||||
#include "threads/juce_ChildProcess.cpp"
|
||||
#include "threads/juce_HighResolutionTimer.cpp"
|
||||
#include "network/juce_URL.cpp"
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -589,10 +589,34 @@ public final class JuceAppActivity extends Activity
|
|||
//==============================================================================
|
||||
public static class HTTPStream
|
||||
{
|
||||
public HTTPStream (HttpURLConnection connection_) throws IOException
|
||||
public HTTPStream (HttpURLConnection connection_,
|
||||
int[] statusCode, StringBuffer responseHeaders) throws IOException
|
||||
{
|
||||
connection = connection_;
|
||||
inputStream = new BufferedInputStream (connection.getInputStream());
|
||||
|
||||
try
|
||||
{
|
||||
inputStream = new BufferedInputStream (connection.getInputStream());
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
if (connection.getResponseCode() < org.apache.http.HttpStatus.SC_BAD_REQUEST)
|
||||
throw e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
statusCode[0] = connection.getResponseCode();
|
||||
}
|
||||
|
||||
if (statusCode[0] >= org.apache.http.HttpStatus.SC_BAD_REQUEST)
|
||||
inputStream = connection.getErrorStream();
|
||||
else
|
||||
inputStream = connection.getInputStream();
|
||||
|
||||
for (java.util.Map.Entry<String, java.util.List<String>> entry : connection.getHeaderFields().entrySet())
|
||||
if (entry.getKey() != null && entry.getValue() != null)
|
||||
responseHeaders.append (entry.getKey() + ": "
|
||||
+ android.text.TextUtils.join (",", entry.getValue()) + "\n");
|
||||
}
|
||||
|
||||
public final void release()
|
||||
|
|
@ -634,30 +658,31 @@ public final class JuceAppActivity extends Activity
|
|||
private long position;
|
||||
}
|
||||
|
||||
public static final HTTPStream createHTTPStream (String address, boolean isPost, byte[] postData,
|
||||
String headers, int timeOutMs,
|
||||
java.lang.StringBuffer responseHeaders)
|
||||
public static final HTTPStream createHTTPStream (String address,
|
||||
boolean isPost, byte[] postData, String headers,
|
||||
int timeOutMs, int[] statusCode,
|
||||
StringBuffer responseHeaders)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpURLConnection connection = (HttpURLConnection) (new URL (address).openConnection());
|
||||
|
||||
HttpURLConnection connection = (HttpURLConnection) (new URL(address)
|
||||
.openConnection());
|
||||
if (connection != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (isPost)
|
||||
{
|
||||
connection.setConnectTimeout (timeOutMs);
|
||||
connection.setDoOutput (true);
|
||||
connection.setChunkedStreamingMode (0);
|
||||
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setConnectTimeout(timeOutMs);
|
||||
connection.setDoOutput(true);
|
||||
connection.setChunkedStreamingMode(0);
|
||||
OutputStream out = connection.getOutputStream();
|
||||
out.write (postData);
|
||||
out.write(postData);
|
||||
out.flush();
|
||||
}
|
||||
|
||||
return new HTTPStream (connection);
|
||||
return new HTTPStream (connection, statusCode, responseHeaders);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
|
|
@ -665,8 +690,7 @@ public final class JuceAppActivity extends Activity
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{}
|
||||
catch (Throwable e) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ extern ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder;
|
|||
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;ILjava/lang/StringBuffer;)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \
|
||||
STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;I[ILjava/lang/StringBuffer;)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") \
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ public:
|
|||
WebInputStream (String address, bool isPost, const MemoryBlock& postData,
|
||||
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers, int timeOutMs, StringPairArray* responseHeaders)
|
||||
: statusCode (0)
|
||||
{
|
||||
if (! address.contains ("://"))
|
||||
address = "http://" + address;
|
||||
|
|
@ -91,6 +92,9 @@ public:
|
|||
// thread. You'll need to move your networking code to a background thread to keep it happy..
|
||||
jassert (Thread::getCurrentThread() != nullptr);
|
||||
|
||||
jintArray statusCodeArray = env->NewIntArray (1);
|
||||
jassert (statusCodeArray != 0);
|
||||
|
||||
stream = GlobalRef (env->CallStaticObjectMethod (JuceAppActivity,
|
||||
JuceAppActivity.createHTTPStream,
|
||||
javaString (address).get(),
|
||||
|
|
@ -98,8 +102,14 @@ public:
|
|||
postDataArray,
|
||||
javaString (headers).get(),
|
||||
(jint) timeOutMs,
|
||||
statusCodeArray,
|
||||
responseHeaderBuffer.get()));
|
||||
|
||||
jint* const statusCodeElements = env->GetIntArrayElements (statusCodeArray, 0);
|
||||
statusCode = statusCodeElements[0];
|
||||
env->ReleaseIntArrayElements (statusCodeArray, statusCodeElements, 0);
|
||||
env->DeleteLocalRef (statusCodeArray);
|
||||
|
||||
if (postDataArray != 0)
|
||||
env->DeleteLocalRef (postDataArray);
|
||||
|
||||
|
|
@ -135,6 +145,8 @@ public:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
bool isError() const { return stream == nullptr; }
|
||||
|
||||
bool isExhausted() override { return stream != nullptr && stream.callBooleanMethod (HTTPStream.isExhausted); }
|
||||
int64 getTotalLength() override { return stream != nullptr ? stream.callLongMethod (HTTPStream.getTotalLength) : 0; }
|
||||
int64 getPosition() override { return stream != nullptr ? stream.callLongMethod (HTTPStream.getPosition) : 0; }
|
||||
|
|
@ -162,18 +174,8 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
GlobalRef stream;
|
||||
int statusCode;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
|
||||
};
|
||||
|
||||
InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
|
||||
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
|
||||
{
|
||||
ScopedPointer <WebInputStream> wi (new WebInputStream (address, isPost, postData,
|
||||
progressCallback, progressCallbackContext,
|
||||
headers, timeOutMs, responseHeaders));
|
||||
|
||||
return wi->stream != 0 ? wi.release() : nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,11 +72,11 @@ public:
|
|||
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
|
||||
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
|
||||
: socketHandle (-1), levelsOfRedirection (0),
|
||||
: statusCode (0), socketHandle (-1), levelsOfRedirection (0),
|
||||
address (address_), headers (headers_), postData (postData_), position (0),
|
||||
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
|
||||
{
|
||||
createConnection (progressCallback, progressCallbackContext);
|
||||
statusCode = createConnection (progressCallback, progressCallbackContext);
|
||||
|
||||
if (responseHeaders != nullptr && ! isError())
|
||||
{
|
||||
|
|
@ -144,7 +144,7 @@ public:
|
|||
{
|
||||
closeSocket();
|
||||
position = 0;
|
||||
createConnection (0, 0);
|
||||
statusCode = createConnection (0, 0);
|
||||
}
|
||||
|
||||
skipNextBytes (wantedPos - position);
|
||||
|
|
@ -154,6 +154,8 @@ public:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
int statusCode;
|
||||
|
||||
private:
|
||||
int socketHandle, levelsOfRedirection;
|
||||
StringArray headerLines;
|
||||
|
|
@ -173,7 +175,7 @@ private:
|
|||
levelsOfRedirection = 0;
|
||||
}
|
||||
|
||||
void createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
|
||||
int createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext)
|
||||
{
|
||||
closeSocket();
|
||||
|
||||
|
|
@ -189,7 +191,7 @@ private:
|
|||
String hostName, hostPath;
|
||||
int hostPort;
|
||||
if (! decomposeURL (address, hostName, hostPath, hostPort))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
String serverName, proxyName, proxyPath;
|
||||
int proxyPort = 0;
|
||||
|
|
@ -199,7 +201,7 @@ private:
|
|||
if (proxyURL.startsWithIgnoreCase ("http://"))
|
||||
{
|
||||
if (! decomposeURL (proxyURL, proxyName, proxyPath, proxyPort))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
serverName = proxyName;
|
||||
port = proxyPort;
|
||||
|
|
@ -219,14 +221,14 @@ private:
|
|||
|
||||
struct addrinfo* result = nullptr;
|
||||
if (getaddrinfo (serverName.toUTF8(), String (port).toUTF8(), &hints, &result) != 0 || result == 0)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
socketHandle = socket (result->ai_family, result->ai_socktype, 0);
|
||||
|
||||
if (socketHandle == -1)
|
||||
{
|
||||
freeaddrinfo (result);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int receiveBufferSize = 16384;
|
||||
|
|
@ -241,7 +243,7 @@ private:
|
|||
{
|
||||
closeSocket();
|
||||
freeaddrinfo (result);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
freeaddrinfo (result);
|
||||
|
|
@ -254,7 +256,7 @@ private:
|
|||
progressCallback, progressCallbackContext))
|
||||
{
|
||||
closeSocket();
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -265,15 +267,15 @@ private:
|
|||
{
|
||||
headerLines = StringArray::fromLines (responseHeader);
|
||||
|
||||
const int statusCode = responseHeader.fromFirstOccurrenceOf (" ", false, false)
|
||||
.substring (0, 3).getIntValue();
|
||||
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 (statusCode >= 300 && statusCode < 400
|
||||
if (status >= 300 && status < 400
|
||||
&& location.isNotEmpty() && location != address)
|
||||
{
|
||||
if (! location.startsWithIgnoreCase ("http://"))
|
||||
|
|
@ -282,18 +284,18 @@ private:
|
|||
if (++levelsOfRedirection <= 3)
|
||||
{
|
||||
address = location;
|
||||
createConnection (progressCallback, progressCallbackContext);
|
||||
return;
|
||||
return createConnection (progressCallback, progressCallbackContext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
levelsOfRedirection = 0;
|
||||
return;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
closeSocket();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -437,14 +439,3 @@ private:
|
|||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
|
||||
};
|
||||
|
||||
InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
|
||||
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
|
||||
{
|
||||
ScopedPointer<WebInputStream> wi (new WebInputStream (address, isPost, postData,
|
||||
progressCallback, progressCallbackContext,
|
||||
headers, timeOutMs, responseHeaders));
|
||||
|
||||
return wi->isError() ? nullptr : wi.release();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ public:
|
|||
connection (nil),
|
||||
data ([[NSMutableData data] retain]),
|
||||
headers (nil),
|
||||
statusCode (0),
|
||||
initialised (false),
|
||||
hasFailed (false),
|
||||
hasFinished (false)
|
||||
|
|
@ -202,7 +203,11 @@ public:
|
|||
headers = nil;
|
||||
|
||||
if ([response isKindOfClass: [NSHTTPURLResponse class]])
|
||||
headers = [[((NSHTTPURLResponse*) response) allHeaderFields] retain];
|
||||
{
|
||||
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
|
||||
headers = [[httpResponse allHeaderFields] retain];
|
||||
statusCode = (int) [httpResponse statusCode];
|
||||
}
|
||||
}
|
||||
|
||||
void didFailWithError (NSError* error)
|
||||
|
|
@ -251,6 +256,7 @@ public:
|
|||
NSURLConnection* connection;
|
||||
NSMutableData* data;
|
||||
NSDictionary* headers;
|
||||
int statusCode;
|
||||
bool initialised, hasFailed, hasFinished;
|
||||
|
||||
private:
|
||||
|
|
@ -318,7 +324,7 @@ public:
|
|||
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
|
||||
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
|
||||
: address (address_), headers (headers_), postData (postData_), position (0),
|
||||
: statusCode (0), address (address_), headers (headers_), postData (postData_), position (0),
|
||||
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
|
|
@ -327,6 +333,8 @@ public:
|
|||
|
||||
if (responseHeaders != nullptr && connection != nullptr && connection->headers != nil)
|
||||
{
|
||||
statusCode = connection->statusCode;
|
||||
|
||||
NSEnumerator* enumerator = [connection->headers keyEnumerator];
|
||||
|
||||
while (NSString* key = [enumerator nextObject])
|
||||
|
|
@ -380,6 +388,8 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
int statusCode;
|
||||
|
||||
private:
|
||||
ScopedPointer<URLConnectionState> connection;
|
||||
String address, headers;
|
||||
|
|
@ -428,14 +438,3 @@ private:
|
|||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
|
||||
};
|
||||
|
||||
InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
|
||||
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
|
||||
{
|
||||
ScopedPointer<WebInputStream> wi (new WebInputStream (address, isPost, postData,
|
||||
progressCallback, progressCallbackContext,
|
||||
headers, timeOutMs, responseHeaders));
|
||||
|
||||
return wi->isError() ? nullptr : wi.release();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,41 +41,50 @@ public:
|
|||
WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_,
|
||||
URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers_, int timeOutMs_, StringPairArray* responseHeaders)
|
||||
: connection (0), request (0),
|
||||
: statusCode (0), connection (0), request (0),
|
||||
address (address_), headers (headers_), postData (postData_), position (0),
|
||||
finished (false), isPost (isPost_), timeOutMs (timeOutMs_)
|
||||
{
|
||||
createConnection (progressCallback, progressCallbackContext);
|
||||
|
||||
if (responseHeaders != nullptr && ! isError())
|
||||
if (! isError())
|
||||
{
|
||||
DWORD bufferSizeBytes = 4096;
|
||||
|
||||
for (;;)
|
||||
if (responseHeaders != nullptr)
|
||||
{
|
||||
HeapBlock<char> buffer ((size_t) bufferSizeBytes);
|
||||
DWORD bufferSizeBytes = 4096;
|
||||
|
||||
if (HttpQueryInfo (request, HTTP_QUERY_RAW_HEADERS_CRLF, buffer.getData(), &bufferSizeBytes, 0))
|
||||
for (;;)
|
||||
{
|
||||
StringArray headersArray;
|
||||
headersArray.addLines (String (reinterpret_cast<const WCHAR*> (buffer.getData())));
|
||||
HeapBlock<char> buffer ((size_t) bufferSizeBytes);
|
||||
|
||||
for (int i = 0; i < headersArray.size(); ++i)
|
||||
if (HttpQueryInfo (request, HTTP_QUERY_RAW_HEADERS_CRLF, buffer.getData(), &bufferSizeBytes, 0))
|
||||
{
|
||||
const String& header = headersArray[i];
|
||||
const String key (header.upToFirstOccurrenceOf (": ", false, false));
|
||||
const String value (header.fromFirstOccurrenceOf (": ", false, false));
|
||||
const String previousValue ((*responseHeaders) [key]);
|
||||
StringArray headersArray;
|
||||
headersArray.addLines (String (reinterpret_cast<const WCHAR*> (buffer.getData())));
|
||||
|
||||
responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
|
||||
for (int i = 0; i < headersArray.size(); ++i)
|
||||
{
|
||||
const String& header = headersArray[i];
|
||||
const String key (header.upToFirstOccurrenceOf (": ", false, false));
|
||||
const String value (header.fromFirstOccurrenceOf (": ", false, false));
|
||||
const String previousValue ((*responseHeaders) [key]);
|
||||
|
||||
responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
break;
|
||||
}
|
||||
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
break;
|
||||
}
|
||||
|
||||
DWORD status = 0;
|
||||
DWORD statusSize = sizeof (status);
|
||||
|
||||
if (HttpQueryInfo (request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &statusSize, 0))
|
||||
statusCode = (int) status;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -145,6 +154,8 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
int statusCode;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
HINTERNET connection, request;
|
||||
|
|
@ -305,17 +316,6 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream)
|
||||
};
|
||||
|
||||
InputStream* URL::createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
|
||||
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
|
||||
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
|
||||
{
|
||||
ScopedPointer <WebInputStream> wi (new WebInputStream (address, isPost, postData,
|
||||
progressCallback, progressCallbackContext,
|
||||
headers, timeOutMs, responseHeaders));
|
||||
|
||||
return wi->isError() ? nullptr : wi.release();
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
struct GetAdaptersInfoHelper
|
||||
|
|
|
|||
|
|
@ -330,7 +330,8 @@ InputStream* URL::createInputStream (const bool usePostCommand,
|
|||
void* const progressCallbackContext,
|
||||
String headers,
|
||||
const int timeOutMs,
|
||||
StringPairArray* const responseHeaders) const
|
||||
StringPairArray* const responseHeaders,
|
||||
int* statusCode) const
|
||||
{
|
||||
MemoryBlock headersAndPostData;
|
||||
|
||||
|
|
@ -343,9 +344,15 @@ InputStream* URL::createInputStream (const bool usePostCommand,
|
|||
if (! headers.endsWithChar ('\n'))
|
||||
headers << "\r\n";
|
||||
|
||||
return createNativeStream (toString (! usePostCommand), usePostCommand, headersAndPostData,
|
||||
progressCallback, progressCallbackContext,
|
||||
headers, timeOutMs, responseHeaders);
|
||||
ScopedPointer<WebInputStream> wi (new WebInputStream (toString (! usePostCommand),
|
||||
usePostCommand, headersAndPostData,
|
||||
progressCallback, progressCallbackContext,
|
||||
headers, timeOutMs, responseHeaders));
|
||||
|
||||
if (statusCode != nullptr)
|
||||
*statusCode = wi->statusCode;
|
||||
|
||||
return wi->isError() ? nullptr : wi.release();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -247,8 +247,10 @@ public:
|
|||
@param connectionTimeOutMs if 0, this will use whatever default setting the OS chooses. If
|
||||
a negative number, it will be infinite. Otherwise it specifies a
|
||||
time in milliseconds.
|
||||
@param responseHeaders if this is non-zero, all the (key, value) pairs received as headers
|
||||
@param responseHeaders if this is non-null, all the (key, value) pairs received as headers
|
||||
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
|
||||
@returns an input stream that the caller must delete, or a null pointer if there was an
|
||||
error trying to open it.
|
||||
*/
|
||||
|
|
@ -257,7 +259,8 @@ public:
|
|||
void* progressCallbackContext = nullptr,
|
||||
String extraHeaders = String(),
|
||||
int connectionTimeOutMs = 0,
|
||||
StringPairArray* responseHeaders = nullptr) const;
|
||||
StringPairArray* responseHeaders = nullptr,
|
||||
int* statusCode = nullptr) const;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -345,10 +348,6 @@ private:
|
|||
URL (const String&, int);
|
||||
void addParameter (const String&, const String&);
|
||||
|
||||
static InputStream* createNativeStream (const String& address, bool isPost, const MemoryBlock& postData,
|
||||
OpenStreamProgressCallback* progressCallback,
|
||||
void* progressCallbackContext, const String& headers,
|
||||
const int timeOutMs, StringPairArray* responseHeaders);
|
||||
JUCE_LEAK_DETECTOR (URL)
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue