/* * Just like simpleGet but with an explicit port number */ static bool get(MprTestGroup *gp, cchar *host, int port, cchar *uri, int expectCode) { MprHttp *http; int code; http = getHttp(gp); if (expectCode <= 0) { expectCode = 200; } if (host) { mprSetHttpDefaultHost(http, host); } if (port > 0) { mprSetHttpDefaultPort(http, getDefaultPort(gp) + port); } if (mprHttpRequest(http, "GET", uri, 0) < 0) { return 0; } code = mprGetHttpCode(http); assert(code == expectCode); if (code != expectCode) { mprLog(gp, 0, "get: HTTP response code %d, expected %d", code, expectCode); return 0; } assert(mprGetHttpError(http) != 0); assert(mprGetHttpContent(http) != 0); return 1; }
static int writeBody(MprHttp *http, MprList *fields, MprList *files) { MprFile *file; char buf[MPR_HTTP_BUFSIZE], *path, *pair; int bytes, next, count, rc, len; rc = 0; mprSetSocketBlockingMode(http->sock, 1); if (upload) { if (mprWriteHttpUploadData(http, files, fields) < 0) { mprError(http, "Can't write upload data %s", mprGetHttpError(http)); mprSetSocketBlockingMode(http->sock, 0); return MPR_ERR_CANT_WRITE; } } else { if (fields) { count = mprGetListCount(fields); for (next = 0; !rc && (pair = mprGetNextItem(fields, &next)) != 0; ) { len = (int) strlen(pair); if (next < count) { len = (int) strlen(pair); if (mprWriteSocket(http->sock, pair, len) != len || mprWriteSocket(http->sock, "&", 1) != 1) { return MPR_ERR_CANT_WRITE; } } else { if (mprWriteSocket(http->sock, pair, len) != len) { return MPR_ERR_CANT_WRITE; } } } } if (files) { mprAssert(mprGetListCount(files) == 1); for (rc = next = 0; !rc && (path = mprGetNextItem(files, &next)) != 0; ) { file = mprOpen(http, path, O_RDONLY | O_BINARY, 0); if (file == 0) { mprError(http, "Can't open \"%s\"", path); return MPR_ERR_CANT_OPEN; } if (verbose && upload) { mprPrintf(http, "uploading: %s\n", path); } while ((bytes = mprRead(file, buf, sizeof(buf))) > 0) { if (mprWriteHttp(http, buf, bytes) != bytes) { mprFree(file); return MPR_ERR_CANT_WRITE; } } mprFree(file); } } if (mprFinalizeHttpWriting(http) < 0) { return MPR_ERR_CANT_WRITE; } } mprSetSocketBlockingMode(http->sock, 0); return rc; }
static int doRequest(MprHttp *http, cchar *url, MprList *fields, MprList *files) { MprHttpResponse *resp; MprKeyValue *header; char buf[MPR_HTTP_BUFSIZE], seqBuf[16], *responseHeaders, *redirect; int64 contentLen; int code, next, count, bytes, transCount; mprAssert(url && *url); mprLog(http, MPR_DEBUG, "fetch: %s %s", method, url); /* * Send the request */ count = -1; transCount = 0; do { for (next = 0; (header = mprGetNextItem(headers, &next)) != 0; ) { mprSetHttpHeader(http, 0, header->key, header->value); } if (sequence) { static int next = 0; mprItoa(seqBuf, sizeof(seqBuf), next++, 10); mprSetHttpHeader(http, 1, "X-Http-Seq", seqBuf); } if (ranges) { mprSetHttpHeader(http, 1, "Range", ranges); } if (fields) { mprSetHttpHeader(http, 1, "Content-Type", "application/x-www-form-urlencoded"); } if (chunkSize) { mprSetHttpChunked(http, 1); } if (setContentLength(http, fields, files) < 0) { return MPR_ERR_CANT_OPEN; } if (mprStartHttpRequest(http, method, url) < 0) { mprError(http, "Can't process request for \"%s\". %s", url, mprGetHttpError(http)); return MPR_ERR_CANT_OPEN; } /* * This program does not do full-duplex writes with reads. ie. if you have a request that sends and receives * data in parallel -- http will do the writes first then read the response. */ if (files || fields) { if (writeBody(http, fields, files) < 0) { mprError(http, "Can't write body data to \"%s\". %s", url, mprGetHttpError(http)); return MPR_ERR_CANT_WRITE; } } else { if (chunkSize) { mprFinalizeHttpWriting(http); } mprWaitForHttpResponse(http, -1); } #if WIN _setmode(fileno(stdout), O_BINARY); #endif while ((bytes = mprReadHttp(http, buf, sizeof(buf))) > 0) { showOutput(http, buf, bytes); } mprWaitForHttp(http, MPR_HTTP_STATE_COMPLETE, -1); /* May not be complete if a disconnect occurs */ if (http->state >= MPR_HTTP_STATE_CONTENT) { if (mprNeedHttpRetry(http, &redirect)) { if (redirect) { url = resolveUrl(http, redirect); } count--; transCount++; continue; } break; } } while (++count < http->retries && transCount < 4 && !mprIsExiting(http)); if (count >= http->retries) { mprError(http, "http: failed \"%s\" request for %s after %d attempt(s)", method, url, count); return MPR_ERR_TOO_MANY; } if (mprIsExiting(http)) { return MPR_ERR_BAD_STATE; } /* * Request now complete */ code = mprGetHttpCode(http); contentLen = mprGetHttpContentLength(http); mprLog(http, 6, "Response code %d, content len %d", code, contentLen); if (http->response) { if (showCode) { mprPrintf(http, "%d\n", code); } if (showHeaders) { responseHeaders = mprGetHttpHeaders(http); resp = http->response; mprPrintf(http, "%s %d %s\n", resp->protocol, resp->code, resp->message); mprPrintf(http, "%s\n", responseHeaders); mprFree(responseHeaders); } } if (code < 0) { mprError(http, "Can't process request for \"%s\" %s", url, mprGetHttpError(http)); return MPR_ERR_CANT_READ; } else if (code == 0 && http->protocolVersion == 0) { ; } else if (!(200 <= code && code <= 206) && !(301 <= code && code <= 304)) { if (!showCode) { mprError(http, "Can't process request for \"%s\" (%d) %s", url, code, mprGetHttpError(http)); return MPR_ERR_CANT_READ; } } lock(); if (verbose && noout) { trace(http, url, fetchCount, method, code, (int) contentLen); } unlock(); return 0; }