public:
InternalServerReply(QNetworkAccessManager::Operation operation,
QNetworkRequest const & networkRequest,
- Publisher * publisher);
+ QIODevice * postData, Publisher * publisher);
// Forwarded to buffer
virtual bool atEnd() const;
using QNetworkReply::setHeader;
void clearResponse();
+ QByteArray postData() const;
+ QString postContentType() const;
protected:
virtual qint64 readData(char * data, qint64 maxSize);
virtual qint64 writeData(char const * data, qint64 maxSize);
- signals:
- void initSignal();
-
private slots:
- void initSlot();
+ void bufferPostData();
+ void postDataReadable();
+ void postDataComplete();
+ void processRequest();
+ void complete();
private:
+ bool readPostData();
+
+ Publisher * publisher_;
+ QIODevice * postDevice_;
QBuffer buffer_;
+ QBuffer postData_;
};
}}
prefix_ pykit::detail::InternalServerReply::
InternalServerReply(QNetworkAccessManager::Operation operation,
- QNetworkRequest const & networkRequest, Publisher * publisher)
+ QNetworkRequest const & networkRequest, QIODevice * postData,
+ Publisher * publisher)
+ : publisher_ (publisher), postDevice_ (postData)
{
setRequest(networkRequest);
setOperation(operation);
open(ReadWrite | Unbuffered);
buffer_.open(ReadWrite | Unbuffered);
+ if (postDevice_)
+ QMetaObject::invokeMethod(this, "bufferPostData", Qt::QueuedConnection);
+ else
+ QMetaObject::invokeMethod(this, "processRequest", Qt::QueuedConnection);
+}
+
+prefix_ void pykit::detail::InternalServerReply::bufferPostData()
+{
+ QVariant cl (request().header(QNetworkRequest::ContentLengthHeader));
+ std::cerr << "postdata contentlength: " << (cl.isValid() ? cl.toString().toStdString() : "invalid") << "\n";
+ connect(postDevice_, SIGNAL(readyRead()), this, SLOT(postDataReadable()));
+ connect(postDevice_, SIGNAL(readChannelFinished()), this, SLOT(postDataComplete()));
+ postData_.open(WriteOnly);
+ postDataReadable();
+}
+
+prefix_ bool pykit::detail::InternalServerReply::readPostData()
+{
+ while (true) {
+ qint64 n (postDevice_->bytesAvailable());
+ if (n <= 0)
+ n = 2048;
+ QByteArray data;
+ data.resize(n);
+ n = postDevice_->read(data.data(), n);
+ if (n < 0)
+ return true;
+ else {
+ data.resize(n);
+ postData_.write(data);
+ }
+ if (n == 0)
+ return false;
+ }
+}
+
+prefix_ void pykit::detail::InternalServerReply::postDataReadable()
+{
+ if (readPostData()) {
+ disconnect(postDevice_, SIGNAL(readyRead()), this, SLOT(postDataReadable()));
+ disconnect(postDevice_, SIGNAL(readChannelFinished()), this, SLOT(postDataComplete()));
+ processRequest();
+ }
+}
+
+prefix_ void pykit::detail::InternalServerReply::postDataComplete()
+{
+ readPostData();
+ disconnect(postDevice_, SIGNAL(readyRead()), this, SLOT(postDataReadable()));
+ disconnect(postDevice_, SIGNAL(readChannelFinished()), this, SLOT(postDataComplete()));
+ processRequest();
+}
+
+prefix_ void pykit::detail::InternalServerReply::processRequest()
+{
Request request (*this);
- publisher->publish(request);
+ publisher_->publish(request);
seek(0);
setHeader(QNetworkRequest::ContentLengthHeader, QVariant(size()));
- setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/html; charset=UTF-8"));
- // The following rigamole is needed to delay emitting readyRead() / finished() after until the
- // connections to those signals have been set up.
- //
- // We use a queued signal here. This will call initSlot after processing has returned to the
- // event loop.
- connect(this, SIGNAL(initSignal()), this, SLOT(initSlot()), Qt::QueuedConnection);
- emit initSignal();
+ QMetaObject::invokeMethod(this, "complete", Qt::QueuedConnection);
}
-prefix_ void pykit::detail::InternalServerReply::initSlot()
+prefix_ void pykit::detail::InternalServerReply::complete()
{
emit readyRead();
+ emit readChannelFinished();
emit finished();
}
buffer_.buffer().clear();
}
+prefix_ QByteArray pykit::detail::InternalServerReply::postData()
+ const
+{
+ return postData_.buffer();
+}
+
+prefix_ QString pykit::detail::InternalServerReply::postContentType()
+ const
+{
+ return request().header(QNetworkRequest::ContentTypeHeader).toString();
+}
+
///////////////////////////////////////////////////////////////////////////
// pykit::Request
return reply_.url();
}
+prefix_ QByteArray pykit::Request::postData()
+ const
+{
+ return reply_.postData();
+}
+
+prefix_ QByteArray pykit::Request::operation()
+ const
+{
+ static char const * const operationNames[]
+ = { "", "HEAD", "GET", "PUT", "POST", "DELETE", "" };
+ return operationNames[reply_.operation()];
+}
+
+prefix_ QString pykit::Request::postContentType()
+ const
+{
+ return reply_.postContentType();
+}
+
prefix_ pykit::Request::Request(detail::InternalServerReply & reply)
: reply_ (reply)
{}
if (request.url().scheme() != "srv")
return QNetworkAccessManager::createRequest(operation, request, device);
- return new detail::InternalServerReply(operation, request, publisher_);
+ return new detail::InternalServerReply(operation, request, device, publisher_);
}
#include "Publisher.moc"