Example #1
0
std::vector<char> RestStatus::handleRequest(const Host & host, const RestRequest & request, const std::map<std::string, std::string> & headers, const std::vector<char> & body) {
    UNUSED(host);
    UNUSED(request);
    UNUSED(headers);
    UNUSED(body);
    
    if (request.getType() != RestRequestType::RRT_GET) {
        // not me, return empty
        return std::vector<char>();
    }

    if (request.getUri().substr(0, uriPattern.size()) != uriPattern) {
        // not me, return empty
        return std::vector<char>();
    }
    
    if (request.getUri() == uriPattern) {
        return basicStatus();
    }
    std::string rest = request.getUri().substr(uriPattern.size());
    if (rest == "/supports/protocol") {
        return supportedProtocols();
    }
    if (rest == "/supports/contentmanager") {
        return supportedContentManagers();
    }
    
    return std::vector<char>();
}
/*!
    \internal
 */
void QWebSocketServerPrivate::handshakeReceived()
{
    if (Q_UNLIKELY(!currentSender)) {
        return;
    }
    QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(currentSender->sender);
    if (Q_UNLIKELY(!pTcpSocket)) {
        return;
    }
    //When using Google Chrome the handshake in received in two parts.
    //Therefore, the readyRead signal is emitted twice.
    //This is a guard against the BEAST attack.
    //See: https://www.imperialviolet.org/2012/01/15/beastfollowup.html
    //For Safari, the handshake is delivered at once
    //FIXME: For FireFox, the readyRead signal is never emitted
    //This is a bug in FireFox (see https://bugzilla.mozilla.org/show_bug.cgi?id=594502)
    if (!pTcpSocket->canReadLine()) {
        return;
    }
    disconnect(pTcpSocket, &QTcpSocket::readyRead,
               this, &QWebSocketServerPrivate::handshakeReceived);
    Q_Q(QWebSocketServer);
    bool success = false;
    bool isSecure = false;

    if (m_pendingConnections.length() >= maxPendingConnections()) {
        pTcpSocket->close();
        pTcpSocket->deleteLater();
        setError(QWebSocketProtocol::CloseCodeAbnormalDisconnection,
                 QWebSocketServer::tr("Too many pending connections."));
        return;
    }

    QWebSocketHandshakeRequest request(pTcpSocket->peerPort(), isSecure);
    QTextStream textStream(pTcpSocket);
    request.readHandshake(textStream, MAX_HEADERLINE_LENGTH, MAX_HEADERLINES);

    if (request.isValid()) {
        QWebSocketCorsAuthenticator corsAuthenticator(request.origin());
        Q_EMIT q->originAuthenticationRequired(&corsAuthenticator);

        QWebSocketHandshakeResponse response(request,
                                             m_serverName,
                                             corsAuthenticator.allowed(),
                                             supportedVersions(),
                                             supportedProtocols(),
                                             supportedExtensions());

        if (response.isValid()) {
            QTextStream httpStream(pTcpSocket);
            httpStream << response;
            httpStream.flush();

            if (response.canUpgrade()) {
                QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket,
                                                                        request,
                                                                        response);
                if (pWebSocket) {
                    addPendingConnection(pWebSocket);
                    Q_EMIT q->newConnection();
                    success = true;
                } else {
                    setError(QWebSocketProtocol::CloseCodeAbnormalDisconnection,
                             QWebSocketServer::tr("Upgrade to WebSocket failed."));
                }
            }
            else {
                setError(response.error(), response.errorString());
            }
        } else {
            setError(QWebSocketProtocol::CloseCodeProtocolError,
                     QWebSocketServer::tr("Invalid response received."));
        }
    }
    if (!success) {
        pTcpSocket->close();
    }
}