Пример #1
0
/*!
 * Handles incoming HTTP requests and dispatches them to the appropriate service.
 *
 * The \a requestID is an opaque value generated by the connector.
 *
 * Subclasses may override this function to perform preprocessing on each
 * request, but they must call the base class implementation in order to
 * generate and dispatch the appropriate events.
 *
 * To facilitate use with multi-threaded applications, the event will remain
 * valid until a response is posted.
 */
void QxtHttpSessionManager::incomingRequest(quint32 requestID, const QHttpRequestHeader& header, QxtWebContent* content)
{
    QMultiHash<QString, QString> cookies;
    foreach(const QString& cookie, header.allValues("cookie"))   // QHttpHeader is case-insensitive, thankfully
    {
        foreach(const QString& kv, cookie.split("; "))
        {
            int pos = kv.indexOf('=');
            if (pos == -1) continue;
            cookies.insert(kv.left(pos), kv.mid(pos + 1));
        }
    }

    int sessionID;
    QString sessionCookie = cookies.value(qxt_d().sessionCookieName);

    qxt_d().sessionLock.lock();
    if (qxt_d().sessionKeys.contains(sessionCookie))
    {
        sessionID = qxt_d().sessionKeys[sessionCookie];
        if(!sessionID && header.majorVersion() > 0 && qxt_d().autoCreateSession)
            sessionID = newSession();
    }
    else if (header.majorVersion() > 0 && qxt_d().autoCreateSession)
    {
        sessionID = newSession();
    }
    else
    {
        sessionID = 0;
    }

    QIODevice* device = connector()->getRequestConnection(requestID);
    QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[device];
    state.sessionID = sessionID;
    state.httpMajorVersion = header.majorVersion();
    state.httpMinorVersion = header.minorVersion();
    if (state.httpMajorVersion == 0 || (state.httpMajorVersion == 1 && state.httpMinorVersion == 0) || header.value("connection").toLower() == "close")
        state.keepAlive = false;
    else
        state.keepAlive = true;
    qxt_d().sessionLock.unlock();

    QxtWebRequestEvent* event = new QxtWebRequestEvent(sessionID, requestID, QUrl::fromEncoded(header.path().toUtf8()));
    qxt_d().eventLock.lock();
    qxt_d().pendingRequests.insert(QPair<int,int>(sessionID, requestID), event);
    qxt_d().eventLock.unlock();
    QTcpSocket* socket = qobject_cast<QTcpSocket*>(device);
    if (socket)
    {
        event->remoteAddress = socket->peerAddress();
#if defined(QT_SECURETRANSPORT) || !defined(QT_NO_OPENSSL)
        QSslSocket* sslSocket = qobject_cast<QSslSocket*>(socket);
        if(sslSocket) {
            event->isSecure = true;
            event->clientCertificate = sslSocket->peerCertificate();
        }
#endif
    }
    event->method = header.method();
    event->cookies = cookies;
    event->url.setScheme("http");
    if (event->url.host().isEmpty())
        event->url.setHost(header.value("host"));
    if (event->url.port() == -1)
        event->url.setPort(port());
    event->contentType = header.contentType();
    event->content = content;
    typedef QPair<QString, QString> StringPair;
    foreach(const StringPair& line, header.values())
    {
        if (line.first.toLower() == "cookie") continue;
        event->headers.insert(line.first, line.second);
    }
    event->headers.insert("X-Request-Protocol", "HTTP/" + QString::number(state.httpMajorVersion) + '.' + QString::number(state.httpMinorVersion));
    if (sessionID && session(sessionID))
    {
        QxtAbstractWebService *service = session(sessionID);
        if(content)
            content->setParent(service); // Set content ownership to the service
        service->pageRequestedEvent(event);
    }
    else if (qxt_d().staticService)
    {
        qxt_d().staticService->pageRequestedEvent(event);
    }
    else
    {
        postEvent(new QxtWebErrorEvent(0, requestID, 500, "Internal Configuration Error"));
    }
}