void uWSGI::processRequest(wsgi_request *req) { CachedRequest *cache = static_cast<CachedRequest *>(req->async_environ); // wsgi_req->uri containg the whole URI it /foo/bar?query=null // so we use path_info, maybe it would be better to just build our // Request->uri() from it, but we need to run a performance test uint16_t pos = notSlash(req->path_info, req->path_info_len); const QString path = QString::fromLatin1(req->path_info + pos, req->path_info_len - pos); const QString serverAddress = QString::fromLatin1(req->host, req->host_len); const QByteArray query = QByteArray::fromRawData(req->query_string, req->query_string_len); const QString method = QString::fromLatin1(req->method, req->method_len); const QString protocol = QString::fromLatin1(req->protocol, req->protocol_len); const QString remoteAddress = QString::fromLatin1(req->remote_addr, req->remote_addr_len); const QString remoteUser = QString::fromLatin1(req->remote_user, req->remote_user_len); quint16 remotePort = 0; Headers headers; // we scan the table in reverse, as updated values are at the end for (int i = req->var_cnt - 1; i > 0; i -= 2) { struct iovec &name = req->hvec[i - 1]; struct iovec &value = req->hvec[i]; if (!uwsgi_startswith(static_cast<char *>(name.iov_base), const_cast<char *>("HTTP_"), 5)) { headers.setHeader(QString::fromLatin1(static_cast<char *>(name.iov_base) + 5, name.iov_len - 5), QString::fromLatin1(static_cast<char *>(value.iov_base), value.iov_len)); } else if (!remotePort && !uwsgi_strncmp(const_cast<char *>("REMOTE_PORT"), 11, static_cast<char *>(name.iov_base), name.iov_len)) { remotePort = QByteArray::fromRawData(static_cast<char *>(value.iov_base), value.iov_len).toUInt(); } } if (req->content_type_len > 0) { headers.setContentType(QString::fromLatin1(req->content_type, req->content_type_len)); } if (req->encoding_len > 0) { headers.setContentEncoding(QString::fromLatin1(req->encoding, req->encoding_len)); } QIODevice *body; if (req->post_file) { // qCDebug(CUTELYST_UWSGI) << "Post file available:" << req->post_file; QFile *upload = cache->bodyFile; if (upload->open(req->post_file, QIODevice::ReadOnly)) { body = upload; } else { // qCDebug(CUTELYST_UWSGI) << "Could not open post file:" << upload->errorString(); body = cache->bodyBufferedUWSGI; body->open(QIODevice::ReadOnly | QIODevice::Unbuffered); } } else if (uwsgi.post_buffering) { // qCDebug(CUTELYST_UWSGI) << "Post buffering size:" << uwsgi.post_buffering; body = cache->bodyUWSGI; body->reset(); } else { // BodyBufferedUWSGI is an IO device which will // only consume the body when some of it's functions // is called, this is because here we can't seek // the body. body = cache->bodyBufferedUWSGI; body->open(QIODevice::ReadOnly | QIODevice::Unbuffered); } Engine::processRequest(method, path, query, protocol, req->https_len, serverAddress, remoteAddress, remotePort, remoteUser, headers, req->start_of_request, body, req); body->close(); }
Uploads MultiPartFormDataParserPrivate::execute(char *buffer, int bufferSize) { Uploads ret; QByteArray header; Headers headers; qint64 startOffset; int boundaryPos = 0; ParserState state = FindBoundary; while (!body->atEnd()) { qint64 len = body->read(buffer, bufferSize); int i = 0; while (i < len) { switch (state) { case FindBoundary: i += findBoundary(buffer + i, len - i, state, boundaryPos); break; case EndBoundaryCR: // TODO the "--" case if (buffer[i] != '\r') { // qCDebug(CUTELYST_MULTIPART) << "EndBoundaryCR return!"; return ret; } state = EndBoundaryLF; break; case EndBoundaryLF: if (buffer[i] != '\n') { // qCDebug(CUTELYST_MULTIPART) << "EndBoundaryLF return!"; return ret; } header.clear(); state = StartHeaders; break; case StartHeaders: // qCDebug(CUTELYST_MULTIPART) << "StartHeaders" << body->pos() - len + i; if (buffer[i] == '\r') { state = EndHeaders; } else if (buffer[i] == '-') { // qCDebug(CUTELYST_MULTIPART) << "StartHeaders return!"; return ret; } else { char *pch = strchr(buffer + i, '\r'); if (pch == NULL) { header.append(buffer + i, len - i); i = len; } else { header.append(buffer + i, pch - buffer - i); i = pch - buffer; state = FinishHeader; } } break; case FinishHeader: // qCDebug(CUTELYST_MULTIPART) << "FinishHeader" << header; if (buffer[i] == '\n') { int dotdot = header.indexOf(':'); headers.setHeader(QString::fromLatin1(header.left(dotdot)), QString::fromLatin1(header.mid(dotdot + 1).trimmed())); header.clear(); state = StartHeaders; } else { // qCDebug(CUTELYST_MULTIPART) << "FinishHeader return!"; return ret; } break; case EndHeaders: // qCDebug(CUTELYST_MULTIPART) << "EndHeaders"; if (buffer[i] == '\n') { state = StartData; } else { // qCDebug(CUTELYST_MULTIPART) << "EndHeaders return!"; return ret; } break; case StartData: // qCDebug(CUTELYST_MULTIPART) << "StartData" << body->pos() - len + i; startOffset = body->pos() - len + i; state = EndData; case EndData: i += findBoundary(buffer + i, len - i, state, boundaryPos); if (state == EndBoundaryCR) { // qCDebug(CUTELYST_MULTIPART) << "EndData" << body->pos() - len + i - boundaryLength - 1; UploadPrivate *priv = new UploadPrivate(body); priv->headers = headers; headers.clear(); priv->startOffset = startOffset; priv->endOffset = body->pos() - len + i - boundaryLength - 1; ret << new Upload(priv); } } ++i; } } return ret; }