Merge pull request #61 from jpirnay/fix-redirect

fix: Add redirection to KoReaderSyncs (eg behind Duckdns or others)
This commit is contained in:
jpirnay
2026-04-11 20:55:45 +02:00
committed by GitHub
2 changed files with 38 additions and 2 deletions
+36 -1
View File
@@ -117,6 +117,13 @@ esp_err_t httpEventHandler(esp_http_client_event_t* evt) {
LOG_ERR("KOSync", "Response buffer allocation failed (%d bytes)", evt->data_len);
}
}
if (evt->event_id == HTTP_EVENT_REDIRECT && buf) {
// A redirect is about to be followed. Clear any body already accumulated from
// the redirect response (e.g. Werkzeug HTML page) so the final response body
// accumulates cleanly without being prefixed by intermediate content.
buf->len = 0;
if (buf->data) buf->data[0] = '\0';
}
return ESP_OK;
}
@@ -223,6 +230,10 @@ esp_http_client_handle_t createClient(const char* url, ResponseBuffer* buf,
config.buffer_size_tx = HTTP_BUF_SIZE;
config.crt_bundle_attach = esp_crt_bundle_attach;
config.keep_alive_enable = g_keepSessionOpen;
// Follow up to 3 redirects (e.g. HTTP→HTTPS, path normalization, DuckDNS proxy).
// HTTP_EVENT_REDIRECT in httpEventHandler clears the buffer between hops so the
// intermediate HTML bodies don't contaminate the final JSON response.
config.max_redirection_count = 3;
esp_http_client_handle_t client = esp_http_client_init(&config);
if (!client) return nullptr;
@@ -307,6 +318,8 @@ KOReaderSyncClient::Error KOReaderSyncClient::registerUser() {
return NETWORK_ERROR;
}
if (httpCode >= 300 && httpCode < 400) return REDIRECT_ERROR;
if (httpCode == 201) {
return OK;
} else if (httpCode == 200) {
@@ -362,7 +375,25 @@ KOReaderSyncClient::Error KOReaderSyncClient::authenticate() {
LOG_DBG("KOSync", "Auth response: %d (err: %s)", httpCode, esp_err_to_name(err));
if (err != ESP_OK) return NETWORK_ERROR;
if (httpCode == 200) return OK;
if (httpCode >= 300 && httpCode < 400) return REDIRECT_ERROR;
if (httpCode == 200) {
// The kosync auth response is always a JSON object. Guard against a reverse
// proxy returning HTTP 200 + HTML (e.g. a login wall that followed all
// redirects and landed on an auth page instead of the API endpoint).
// Skip leading whitespace before checking for '{' so servers that emit
// a BOM or indent their JSON don't get incorrectly rejected.
if (!activeBuf->data) {
return SERVER_ERROR;
}
const char* p = activeBuf->data;
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') {
p++;
}
if (*p != '{') {
return SERVER_ERROR;
}
return OK;
}
if (httpCode == 401) return AUTH_FAILED;
return SERVER_ERROR;
}
@@ -431,6 +462,7 @@ KOReaderSyncClient::Error KOReaderSyncClient::getProgress(const std::string& doc
}
if (err != ESP_OK) return NETWORK_ERROR;
if (httpCode >= 300 && httpCode < 400) return REDIRECT_ERROR;
if (httpCode == 200 && activeBuf->data) {
JsonDocument doc;
@@ -543,6 +575,7 @@ KOReaderSyncClient::Error KOReaderSyncClient::updateProgress(const KOReaderProgr
}
if (err != ESP_OK) return NETWORK_ERROR;
if (httpCode >= 300 && httpCode < 400) return REDIRECT_ERROR;
if (httpCode == 200 || httpCode == 202) return OK;
if (httpCode == 401) return AUTH_FAILED;
return SERVER_ERROR;
@@ -597,6 +630,8 @@ const char* KOReaderSyncClient::errorString(Error error) {
return "Username is already taken";
case REGISTRATION_DISABLED:
return "Registration is disabled on this server";
case REDIRECT_ERROR:
return "Server redirected (check server URL)";
default:
return "Unknown error";
}
+2 -1
View File
@@ -39,7 +39,8 @@ class KOReaderSyncClient {
JSON_ERROR,
NOT_FOUND,
USER_EXISTS,
REGISTRATION_DISABLED
REGISTRATION_DISABLED,
REDIRECT_ERROR
};
/**