Example #1
0
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;
}