static int issueRequest(HttpConn *conn, cchar *url, MprList *files) { HttpRx *rx; HttpUri *target, *location; char *redirect; cchar *msg, *sep; int count, redirectCount, rc; httpSetRetries(conn, app->retries); httpSetTimeout(conn, app->timeout, app->timeout); for (redirectCount = count = 0; count <= conn->retries && redirectCount < 16 && !mprShouldAbortRequests(conn); count++) { if (prepRequest(conn, files, count) < 0) { return MPR_ERR_CANT_OPEN; } if (sendRequest(conn, app->method, url, files) < 0) { return MPR_ERR_CANT_WRITE; } if ((rc = httpWait(conn, HTTP_STATE_PARSED, conn->limits->requestTimeout)) == 0) { if (httpNeedRetry(conn, &redirect)) { if (redirect) { location = httpCreateUri(redirect, 0); target = httpJoinUri(conn->tx->parsedUri, 1, &location); url = httpUriToString(target, HTTP_COMPLETE_URI); count = 0; } /* Count redirects and auth retries */ redirectCount++; count--; } else { break; } } else if (!conn->error) { if (rc == MPR_ERR_TIMEOUT) { httpError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TIMEOUT, "Inactive request timed out, exceeded request timeout %d", app->timeout); } else { httpError(conn, HTTP_ABORT | HTTP_CODE_COMMS_ERROR, "Connection I/O error"); } } if ((rx = conn->rx) != 0) { if (rx->status == HTTP_CODE_REQUEST_TOO_LARGE || rx->status == HTTP_CODE_REQUEST_URL_TOO_LARGE || (rx->status == HTTP_CODE_UNAUTHORIZED && conn->authUser == 0)) { /* No point retrying */ break; } } mprLog(MPR_DEBUG, "retry %d of %d for: %s %s", count, conn->retries, app->method, url); } // MOB - comment out errorMsg as auth errors were returning errors here. if (conn->error /* || conn->errorMsg */) { msg = (conn->errorMsg) ? conn->errorMsg : ""; sep = (msg && *msg) ? "\n" : ""; mprError("http: failed \"%s\" request for %s after %d attempt(s).%s%s", app->method, url, count, sep, msg); return MPR_ERR_CANT_CONNECT; } return 0; }
/* function set retries(count: Number): Void */ static EjsObj *http_set_retries(Ejs *ejs, EjsHttp *hp, int argc, EjsObj **argv) { httpSetRetries(hp->conn, ejsGetInt(ejs, argv[0])); return 0; }
static int issueRequest(HttpConn *conn, cchar *url, MprList *files) { HttpRx *rx; HttpUri *target, *location; char *redirect; cchar *msg, *sep, *authType; int count, redirectCount, rc; httpSetRetries(conn, app->retries); httpSetTimeout(conn, app->timeout, app->timeout); authType = conn->authType; for (redirectCount = count = 0; count <= conn->retries && redirectCount < 10 && !mprShouldAbortRequests(conn); count++) { if (prepRequest(conn, files, count) < 0) { return MPR_ERR_CANT_OPEN; } if (sendRequest(conn, app->method, url, files) < 0) { return MPR_ERR_CANT_WRITE; } if ((rc = httpWait(conn, HTTP_STATE_PARSED, conn->limits->requestTimeout)) == 0) { if (httpNeedRetry(conn, &redirect)) { if (redirect) { httpRemoveHeader(conn, "Host"); location = httpCreateUri(redirect, 0); if (!location || !location->valid) { httpError(conn, HTTP_ABORT, "Invalid location URI"); break; } target = httpJoinUri(conn->tx->parsedUri, 1, &location); url = httpUriToString(target, HTTP_COMPLETE_URI); count = 0; } if (conn->rx && conn->rx->status == HTTP_CODE_UNAUTHORIZED && authType && smatch(authType, conn->authType)) { /* Supplied authentication details and failed */ break; } redirectCount++; count--; } else { break; } } else if (!conn->error) { if (rc == MPR_ERR_TIMEOUT) { httpError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TIMEOUT, "Inactive request timed out, exceeded request timeout %lld", app->timeout); } else { httpError(conn, HTTP_ABORT | HTTP_CODE_COMMS_ERROR, "Connection I/O error"); } } if ((rx = conn->rx) != 0) { if (rx->status == HTTP_CODE_REQUEST_TOO_LARGE || rx->status == HTTP_CODE_REQUEST_URL_TOO_LARGE || rx->status == HTTP_CODE_NOT_ACCEPTABLE || (rx->status == HTTP_CODE_UNAUTHORIZED && conn->username == 0)) { /* No point retrying */ break; } if (conn->sock->flags & MPR_SOCKET_CERT_ERROR) { break; } } mprDebug("http", 4, "retry %d of %d for: %s %s", count, conn->retries, app->method, url); } if (conn->error) { msg = (conn->errorMsg) ? conn->errorMsg : ""; sep = (msg && *msg) ? "\n" : ""; mprLog("error http", 0, "Failed \"%s\" request for %s%s%s", app->method, url, sep, msg); return MPR_ERR_CANT_CONNECT; } return 0; }