static int prepRequest(HttpConn *conn, MprList *files, int retry) { MprKeyValue *header; char *seq; int next; httpPrepClientConn(conn, retry); for (next = 0; (header = mprGetNextItem(app->headers, &next)) != 0; ) { if (scaselessmatch(header->key, "User-Agent")) { httpSetHeaderString(conn, header->key, header->value); } else { httpAppendHeaderString(conn, header->key, header->value); } } if (app->text) { httpSetHeader(conn, "Accept", "text/plain"); } if (app->sequence) { static int next = 0; seq = itos(next++); httpSetHeaderString(conn, "X-Http-Seq", seq); } if (app->ranges) { httpSetHeaderString(conn, "Range", app->ranges); } if (app->formData) { httpSetContentType(conn, "application/x-www-form-urlencoded"); } if (setContentLength(conn, files) < 0) { return MPR_ERR_CANT_OPEN; } return 0; }
PUBLIC ssize espRenderError(HttpConn *conn, int status, cchar *fmt, ...) { va_list args; HttpRx *rx; ssize written; cchar *msg, *title, *text; va_start(args, fmt); rx = conn->rx; written = 0; if (!httpIsFinalized(conn)) { if (status == 0) { status = HTTP_CODE_INTERNAL_SERVER_ERROR; } title = sfmt("Request Error for \"%s\"", rx->pathInfo); msg = mprEscapeHtml(sfmtv(fmt, args)); if (rx->route->flags & HTTP_ROUTE_SHOW_ERRORS) { text = sfmt(\ "<!DOCTYPE html>\r\n<html>\r\n<head><title>%s</title></head>\r\n" \ "<body>\r\n<h1>%s</h1>\r\n" \ " <pre>%s</pre>\r\n" \ " <p>To prevent errors being displayed in the browser, " \ " set <b>ShowErrors off</b> in the appweb.conf file.</p>\r\n" \ "</body>\r\n</html>\r\n", title, title, msg); httpSetContentType(conn, "text/html"); written += espRenderString(conn, text); espFinalize(conn); httpTrace(conn, "esp.error", "error", "msg=\"%s\", status=%d, uri=\"%s\"", msg, status, rx->pathInfo); } } va_end(args); return written; }
PUBLIC ssize espSendRec(HttpConn *conn, EdiRec *rec, int flags) { httpSetContentType(conn, "application/json"); if (rec) { return espRender(conn, "{\n \"data\": %s, \"schema\": %s}\n", ediRecAsJson(rec, flags), ediGetRecSchemaAsJson(rec)); } return espRender(conn, "{}"); }
PUBLIC ssize espSendGrid(HttpConn *conn, EdiGrid *grid, int flags) { httpSetContentType(conn, "application/json"); if (grid) { return espRender(conn, "{\n \"data\": %s, \"schema\": %s}\n", ediGridAsJson(grid, flags), ediGetGridSchemaAsJson(grid)); } return espRender(conn, "{}"); }
/* Start the request (and complete it) */ static void startDir(HttpQueue *q) { HttpConn *conn; HttpTx *tx; HttpRx *rx; MprList *list; MprDirEntry *dp; HttpDir *dir; cchar *path; uint nameSize; int next; conn = q->conn; rx = conn->rx; tx = conn->tx; if ((dir = conn->reqData) == 0) { httpError(conn, HTTP_CODE_INTERNAL_SERVER_ERROR, "Cannot get directory listing"); return; } assert(tx->filename); if (!(rx->flags & (HTTP_GET | HTTP_HEAD))) { httpError(conn, HTTP_CODE_BAD_METHOD, "Bad method"); return; } httpSetContentType(conn, "text/html"); httpSetHeaderString(conn, "Cache-Control", "no-cache"); httpSetHeaderString(conn, "Last-Modified", conn->http->currentDate); parseQuery(conn); if ((list = mprGetPathFiles(tx->filename, MPR_PATH_RELATIVE)) == 0) { httpWrite(q, "<h2>Cannot get file list</h2>\r\n"); outputFooter(q); return; } if (dir->pattern) { filterDirList(conn, list); } sortList(conn, list); /* Get max filename size */ nameSize = 0; for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) { nameSize = max((int) strlen(dp->name), nameSize); } nameSize = max(nameSize, 22); path = rx->route->prefix ? sjoin(rx->route->prefix, rx->pathInfo, NULL) : rx->pathInfo; outputHeader(q, path, nameSize); for (next = 0; (dp = mprGetNextItem(list, &next)) != 0; ) { outputLine(q, dp, tx->filename, nameSize); } outputFooter(q); httpFinalize(conn); }
/* Respond to the request by asking for a client login */ PUBLIC void httpDigestLogin(HttpConn *conn) { HttpAuth *auth; char *nonce, *opaque; auth = conn->rx->route->auth; nonce = createDigestNonce(conn, conn->http->secret, auth->realm); /* Opaque is unused, set to anything */ opaque = "799d5"; if (smatch(auth->qop, "none")) { httpSetHeader(conn, "WWW-Authenticate", "Digest realm=\"%s\", nonce=\"%s\"", auth->realm, nonce); } else { /* Value of null defaults to "auth" */ httpSetHeader(conn, "WWW-Authenticate", "Digest realm=\"%s\", domain=\"%s\", " "qop=\"auth\", nonce=\"%s\", opaque=\"%s\", algorithm=\"MD5\", stale=\"FALSE\"", auth->realm, conn->host->name, nonce, opaque); } httpSetContentType(conn, "text/plain"); httpError(conn, HTTP_CODE_UNAUTHORIZED, "Access Denied. Login required"); }
PUBLIC bool espRenderView(HttpConn *conn, cchar *target, int flags) { HttpRx *rx; HttpRoute *route; EspRoute *eroute; EspViewProc viewProc; rx = conn->rx; route = rx->route; eroute = route->eroute; #if !ME_STATIC if (!eroute->combine && (route->update || !mprLookupKey(eroute->top->views, target))) { cchar *errMsg; /* WARNING: GC yield */ target = sclone(target); mprHold(target); if (espLoadModule(route, conn->dispatcher, "view", mprJoinPath(route->documents, target), &errMsg) < 0) { mprRelease(target); return 0; } mprRelease(target); } #endif if ((viewProc = mprLookupKey(eroute->views, target)) == 0) { return 0; } if (!(flags & ESP_DONT_RENDER)) { if (route->flags & HTTP_ROUTE_XSRF) { /* Add a new unique security token */ httpAddSecurityToken(conn, 1); } httpSetContentType(conn, "text/html"); httpSetFilename(conn, mprJoinPath(route->documents, target), 0); /* WARNING: may GC yield */ (viewProc)(conn); } return 1; }
static void handleTraceMethod(HttpStream *stream) { HttpTx *tx; HttpQueue *q; HttpPacket *traceData; tx = stream->tx; q = stream->writeq; /* Create a dummy set of headers to use as the response body. Then reset so the connector will create the headers in the normal fashion. Need to be careful not to have a content length in the headers in the body. */ tx->flags |= HTTP_TX_NO_LENGTH; httpDiscardData(stream, HTTP_QUEUE_TX); traceData = httpCreateDataPacket(q->packetSize); httpCreateHeaders1(q, traceData); tx->flags &= ~(HTTP_TX_NO_LENGTH | HTTP_TX_HEADERS_CREATED); httpSetContentType(stream, "message/http"); httpPutPacketToNext(q, traceData); httpFinalize(stream); }
void espSetContentType(HttpConn *conn, cchar *mimeType) { httpSetContentType(conn, mimeType); }