void KDSoapPendingCall::Private::parseReply() { if (parsed) { return; } QNetworkReply *reply = this->reply.data(); if (!reply->isFinished()) { qDebug() << "KDSoapPendingCall::parseReply: Reply is not finished. Bytes available" << reply->bytesAvailable() << "Error" << reply->error(); } parsed = true; if (reply->error()) { replyMessage.setFault(true); replyMessage.addArgument(QString::fromLatin1("faultcode"), QString::number(reply->error())); replyMessage.addArgument(QString::fromLatin1("faultstring"), reply->errorString()); if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 500) { qDebug() << "Status code:" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() << "Error:" << reply->errorString(); return; } } const QByteArray data = reply->readAll(); if (!data.isEmpty()) { KDSoapMessageReader reader; reader.xmlToMessage(data, &replyMessage, 0, &replyHeaders); } }
void KDSoapPendingCall::Private::parseReply() { if (parsed) return; parsed = true; const bool doDebug = qgetenv("KDSOAP_DEBUG").toInt(); QNetworkReply* reply = this->reply.data(); #if QT_VERSION >= 0x040600 if (!reply->isFinished()) { qWarning("KDSoap: Parsing reply before it finished!"); } #endif if (reply->error()) { replyMessage.setFault(true); replyMessage.addArgument(QString::fromLatin1("faultcode"), QString::number(reply->error())); replyMessage.addArgument(QString::fromLatin1("faultstring"), reply->errorString()); if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() != 500) { if (doDebug) { //qDebug() << reply->readAll(); qDebug() << reply->errorString(); } return; } // HTTP 500 is used to return faults, so parse the fault, below } const QByteArray data = reply->readAll(); if (doDebug) qDebug() << data; if (!data.isEmpty()) { KDSoapMessageReader reader; reader.xmlToMessage(data, &replyMessage, 0, &replyHeaders); } }
void KDSoapPendingCall::Private::parseReply() { if (parsed) { return; } const bool doDebug = qgetenv("KDSOAP_DEBUG").toInt(); QNetworkReply *reply = this->reply.data(); #if QT_VERSION >= 0x040600 if (!reply->isFinished()) { qWarning("KDSoap: Parsing reply before it finished!"); return; } #endif parsed = true; const QByteArray data = reply->readAll(); if (doDebug) { qDebug() << data; } if (!data.isEmpty()) { KDSoapMessageReader reader; reader.xmlToMessage(data, &replyMessage, 0, &replyHeaders, this->soapVersion); } if (reply->error()) { if (!replyMessage.isFault()) { replyHeaders.clear(); replyMessage = KDSoapMessage(); replyMessage.setFault(true); if (this->soapVersion == KDSoapClientInterface::SOAP1_2) { replyMessage.setNamespaceUri(QString::fromLatin1("http://www.w3.org/2003/05/soap-envelope")); KDSoapValueList codeValueList; codeValueList.addArgument(QString::fromLatin1("Value"), QString::number(reply->error())); replyMessage.addArgument(QString::fromLatin1("Code"), codeValueList); KDSoapValueList reasonValueList; reasonValueList.addArgument(QString::fromLatin1("Text"), reply->errorString()); replyMessage.addArgument(QString::fromLatin1("Reason"), reasonValueList); } else { replyMessage.addArgument(QString::fromLatin1("faultcode"), QString::number(reply->error())); replyMessage.addArgument(QString::fromLatin1("faultstring"), reply->errorString()); } } } }
void KDSoapServerSocket::slotReadyRead() { if (!m_socketEnabled) return; //qDebug() << this << QThread::currentThread() << "slotReadyRead!"; QByteArray buf(2048, ' '); qint64 nread = -1; while (nread != 0) { nread = read(buf.data(), buf.size()); if (nread < 0) { qDebug() << "Error reading from server socket:" << errorString(); return; } m_requestBuffer += buf.left(nread); } //qDebug() << "KDSoapServerSocket: request:" << m_requestBuffer; QByteArray receivedHttpHeaders, receivedData; const bool splitOK = splitHeadersAndData(m_requestBuffer, receivedHttpHeaders, receivedData); if (!splitOK) { //qDebug() << "Incomplete SOAP request, wait for more data"; //incomplete request, wait for more data return; } QMap<QByteArray, QByteArray> httpHeaders; httpHeaders = parseHeaders(receivedHttpHeaders); if (m_doDebug) { qDebug() << "headers received:" << receivedHttpHeaders; qDebug() << httpHeaders; qDebug() << "data received:" << receivedData; } const QByteArray contentLength = httpHeaders.value("content-length"); if (receivedData.size() < contentLength.toInt()) return; // incomplete request, wait for more data m_requestBuffer.clear(); const QByteArray requestType = httpHeaders.value("_requestType"); if (requestType != "GET" && requestType != "POST") { qWarning() << "Unknown HTTP request:" << requestType; //handleError(replyMsg, "Client.Data", QString::fromLatin1("Invalid request type '%1', should be GET or POST").arg(QString::fromLatin1(requestType.constData()))); //sendReply(0, replyMsg); const QByteArray methodNotAllowed = "HTTP/1.1 405 Method Not Allowed\r\nAllow: GET POST\r\nContent-Length: 0\r\n\r\n"; write(methodNotAllowed); return; } const QString path = QString::fromLatin1(httpHeaders.value("_path").constData()); KDSoapServerAuthInterface* serverAuthInterface = qobject_cast<KDSoapServerAuthInterface *>(m_serverObject); if (serverAuthInterface) { QByteArray authValue = httpHeaders.value("Authorization"); if (authValue.isEmpty()) authValue = httpHeaders.value("authorization"); // as sent by Qt-4.5 if (!serverAuthInterface->handleHttpAuth(authValue, path)) { // send auth request (Qt supports basic, ntlm and digest) const QByteArray unauthorized = "HTTP/1.1 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"example\"\r\nContent-Length: 0\r\n\r\n"; write(unauthorized); return; } } KDSoapServer* server = m_owner->server(); KDSoapMessage replyMsg; replyMsg.setUse(server->use()); KDSoapServerObjectInterface* serverObjectInterface = qobject_cast<KDSoapServerObjectInterface *>(m_serverObject); if (!serverObjectInterface) { const QString error = QString::fromLatin1("Server object %1 does not implement KDSoapServerObjectInterface!").arg(QString::fromLatin1(m_serverObject->metaObject()->className())); handleError(replyMsg, "Server.ImplementationError", error); sendReply(0, replyMsg); return; } else { serverObjectInterface->setServerSocket(this); } if (requestType == "GET") { if (path == server->wsdlPathInUrl() && handleWsdlDownload()) { return; } else if (handleFileDownload(serverObjectInterface, path)) { return; } // See http://www.ibm.com/developerworks/xml/library/x-tipgetr/ // We could implement it, but there's no SOAP request, just a query in the URL, // which we'd have to pass to a different virtual than processRequest. handleError(replyMsg, "Client.Data", QString::fromLatin1("Support for GET requests not implemented yet.")); sendReply(0, replyMsg); return; } //parse message KDSoapMessage requestMsg; KDSoapHeaders requestHeaders; KDSoapMessageReader reader; KDSoapMessageReader::XmlError err = reader.xmlToMessage(receivedData, &requestMsg, &m_messageNamespace, &requestHeaders); if (err == KDSoapMessageReader::PrematureEndOfDocumentError) { //qDebug() << "Incomplete SOAP message, wait for more data"; // This should never happen, since we check for content-size above. return; } //TODO handle parse errors? // check soap version and extract soapAction header QByteArray soapAction; const QByteArray contentType = httpHeaders.value("content-type"); if (contentType.startsWith("text/xml")) { // SOAP 1.1 soapAction = httpHeaders.value("soapaction"); // The SOAP standard allows quotation marks around the SoapAction, so we have to get rid of these. if (soapAction.startsWith('\"')) soapAction = soapAction.mid(1, soapAction.length() - 2); } else if (contentType.startsWith("application/soap+xml")) { // SOAP 1.2 // Example: application/soap+xml;charset=utf-8;action=ActionHex const QList<QByteArray> parts = contentType.split(';'); Q_FOREACH(const QByteArray& part, parts) { if (part.startsWith("action=")) { soapAction = part.mid(strlen("action=")); } } } m_method = requestMsg.name(); if (!replyMsg.isFault()) { makeCall(serverObjectInterface, requestMsg, replyMsg, requestHeaders, soapAction, path); } if (serverObjectInterface && m_delayedResponse) { // Delayed response. Disable the socket to make sure we don't handle another call at the same time. setSocketEnabled(false); } else { sendReply(serverObjectInterface, replyMsg); } }