Hello, I have some juce code to login to my woocommerce website.
It runs flawlessly on Mac, but I was testing it on Windows and it always fails to open the WebInputStream.
I cannot for the life of me figure out why it is failing either.
On windows it always fails to create the WebInputStream with status code 0.
I have some oddities in the debugger specifically in the juce::WebInputStream::connect(Listener* listener) method. For some reason the first time that the breakpoint is hit, hasCalledConnect is already set to true. I have a feeling that’s just a side effect of the threading though because it doesn’t do that if I try to create an input stream on the main thread.
If the code also didn’t work on Mac I’d believe I’m doing something wrong but it works fine on Mac. So I think there’s something wrong with the Windows networking implementation?
void AuthService::login(const juce::String& usernameOrEmail,
const juce::String& password,
std::function<void(LoginResponse)> callback)
{
auto loginUrl = "https://my-website.com";
// Create the form data
juce::StringPairArray postData;
postData.set("username", usernameOrEmail);
postData.set("password", password);
// Add WooCommerce authentication
postData.set("consumer_key", consumerKey);
postData.set("consumer_secret", consumerSecret);
// Start the async request in a separate thread
std::thread([callback, loginUrl, postData, this]() mutable {
LoginResponse result;
bool success = false;
int retryCount = 0;
const int maxRetries = 3;
while (!success && retryCount < maxRetries)
{
try
{
DBG("AuthService: Login attempt " + juce::String(retryCount + 1) + " of " + juce::String(maxRetries));
// Setup headers for form POST request
juce::StringPairArray headers;
headers.set("Content-Type", "application/x-www-form-urlencoded");
headers.set("User-Agent", "NNAudioHub/1.0");
int statusCode = 0;
auto options = juce::URL::InputStreamOptions(juce::URL::ParameterHandling::inPostData)
.withHttpRequestCmd("POST")
.withExtraHeaders(headers.getDescription())
.withConnectionTimeoutMs(60000) // Increased timeout to 60 seconds
.withStatusCode(&statusCode)
.withNumRedirectsToFollow(5); // Allow redirects
// Create the POST data string
j const auto& postKeys = postData.getAllKeys();
const auto& postValues = postData.getAllValues();
for (auto i = 0; i < postData.size(); ++i)
{
if (i > 0)
postDataString += "&";
postDataString += juce::URL::addEscapeChars(postKeys[i], true);
postDataString += "=";
postDataString += juce::URL::addEscapeChars(postValues[i], true);
}
// Create input stream with POST method
if (auto stream = juce::URL(loginUrl)
.withPOSTData(postDataString)
.createInputStream(options))
{
DBG("AuthService: Got response with status code: " + juce::String(statusCode));
// do stuff with the data
}
else
{
DBG("AuthService: Failed to create input stream, status code: " + juce::String(statusCode));
}
}
catch (const std::exception& e)
{
DBG("AuthService: Exception during login attempt: " + juce::String(e.what()));
}
retryCount++;
if (!success && retryCount < maxRetries)
{
auto delayMs = (1000 * (1 << retryCount)); // Exponential backoff
DBG("AuthService: Retrying in " + juce::String(delayMs) + "ms...");
juce::Thread::sleep(delayMs);
}
}
}
