mirror of
https://github.com/YACReader/yacreader
synced 2025-06-03 09:08:20 -04:00
integrada la nueva versi?n de qtwebapp
This commit is contained in:
parent
a39cc616f6
commit
d123df4f53
@ -16,7 +16,7 @@ HttpConnectionHandler::HttpConnectionHandler(QSettings* settings, HttpRequestHan
|
||||
this->settings=settings;
|
||||
this->requestHandler=requestHandler;
|
||||
currentRequest=0;
|
||||
busy = false; // pdiener: it is not busy if it is new
|
||||
busy = false;
|
||||
// execute signals in my own thread
|
||||
moveToThread(this);
|
||||
socket.moveToThread(this);
|
||||
@ -60,13 +60,14 @@ void HttpConnectionHandler::handleConnection(int socketDescriptor) {
|
||||
// Start timer for read timeout
|
||||
int readTimeout=settings->value("readTimeout",10000).toInt();
|
||||
readTimer.start(readTimeout);
|
||||
// delete previous request
|
||||
delete currentRequest;
|
||||
currentRequest=0;
|
||||
}
|
||||
|
||||
|
||||
bool HttpConnectionHandler::isBusy() {
|
||||
//return socket.isOpen();
|
||||
return busy; // pdiener: changed this from socket readout to bool variable
|
||||
return busy;
|
||||
}
|
||||
|
||||
void HttpConnectionHandler::setBusy() {
|
||||
@ -76,7 +77,10 @@ void HttpConnectionHandler::setBusy() {
|
||||
|
||||
void HttpConnectionHandler::readTimeout() {
|
||||
qDebug("HttpConnectionHandler (%p): read timeout occured",this);
|
||||
socket.write("HTTP/1.1 408 request timeout\r\nConnection: close\r\n\r\n408 request timeout\r\n");
|
||||
|
||||
//Commented out because QWebView cannot handle this.
|
||||
//socket.write("HTTP/1.1 408 request timeout\r\nConnection: close\r\n\r\n408 request timeout\r\n");
|
||||
|
||||
socket.disconnectFromHost();
|
||||
delete currentRequest;
|
||||
currentRequest=0;
|
||||
@ -86,15 +90,13 @@ void HttpConnectionHandler::readTimeout() {
|
||||
void HttpConnectionHandler::disconnected() {
|
||||
qDebug("HttpConnectionHandler (%p): disconnected", this);
|
||||
socket.close();
|
||||
delete currentRequest;
|
||||
currentRequest=0;
|
||||
readTimer.stop();
|
||||
busy = false; // pdiener: now we have finished
|
||||
busy = false;
|
||||
}
|
||||
|
||||
void HttpConnectionHandler::read() {
|
||||
#ifdef SUPERVERBOSE
|
||||
qDebug("HttpConnectionHandler (%x): read input",(unsigned int) this);
|
||||
qDebug("HttpConnectionHandler (%p): read input",this);
|
||||
#endif
|
||||
|
||||
// Create new HttpRequest object if necessary
|
||||
|
@ -44,15 +44,12 @@ public:
|
||||
/** Destructor */
|
||||
virtual ~HttpConnectionHandler();
|
||||
|
||||
/** Returns true, if this handler is busy */
|
||||
/** Returns true, if this handler is in use. */
|
||||
bool isBusy();
|
||||
|
||||
/** Mark this handler as busy */
|
||||
void setBusy();
|
||||
|
||||
/** This shows the busy-state from a very early time */
|
||||
bool busy;
|
||||
|
||||
private:
|
||||
|
||||
/** Configuration settings */
|
||||
@ -70,6 +67,9 @@ private:
|
||||
/** Dispatches received requests to services */
|
||||
HttpRequestHandler* requestHandler;
|
||||
|
||||
/** This shows the busy-state from a very early time */
|
||||
bool busy;
|
||||
|
||||
/** Executes the htreads own event loop */
|
||||
void run();
|
||||
|
||||
|
@ -13,27 +13,33 @@ HttpConnectionHandlerPool::HttpConnectionHandlerPool(QSettings* settings, HttpRe
|
||||
|
||||
HttpConnectionHandlerPool::~HttpConnectionHandlerPool() {
|
||||
foreach(HttpConnectionHandler* handler, pool) {
|
||||
delete handler;
|
||||
connect(handler,SIGNAL(finished()),handler,SLOT(deleteLater()));
|
||||
handler->quit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HttpConnectionHandler* HttpConnectionHandlerPool::getConnectionHandler() {
|
||||
HttpConnectionHandler* HttpConnectionHandlerPool::getConnectionHandler() {
|
||||
HttpConnectionHandler* freeHandler=0;
|
||||
mutex.lock();
|
||||
// find a free handler in pool
|
||||
foreach(HttpConnectionHandler* handler, pool) {
|
||||
if (!handler->isBusy()) {
|
||||
freeHandler=handler;
|
||||
freeHandler->setBusy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// create a new handler, if necessary
|
||||
if (!freeHandler) {
|
||||
//CAMBIADO
|
||||
int maxConnectionHandlers= 100;//settings->value("maxThreads",10).toInt();
|
||||
int maxConnectionHandlers=settings->value("maxThreads",100).toInt();
|
||||
if (pool.count()<maxConnectionHandlers) {
|
||||
freeHandler=new HttpConnectionHandler(settings,requestHandler);
|
||||
freeHandler->setBusy();
|
||||
pool.append(freeHandler);
|
||||
}
|
||||
}
|
||||
if (freeHandler) freeHandler->busy = true; // pdiener: set it to busy-state immediately
|
||||
mutex.unlock();
|
||||
return freeHandler;
|
||||
}
|
||||
|
||||
@ -42,6 +48,7 @@ HttpConnectionHandler* HttpConnectionHandlerPool::getConnectionHandler() {
|
||||
void HttpConnectionHandlerPool::cleanup() {
|
||||
int maxIdleHandlers=settings->value("minThreads",1).toInt();
|
||||
int idleCounter=0;
|
||||
mutex.lock();
|
||||
foreach(HttpConnectionHandler* handler, pool) {
|
||||
if (!handler->isBusy()) {
|
||||
if (++idleCounter > maxIdleHandlers) {
|
||||
@ -53,4 +60,5 @@ void HttpConnectionHandlerPool::cleanup() {
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QList>
|
||||
#include <QTimer>
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include "httpconnectionhandler.h"
|
||||
|
||||
/**
|
||||
@ -13,14 +14,14 @@
|
||||
Example for the required configuration settings:
|
||||
<code><pre>
|
||||
minThreads=1
|
||||
maxThreads=10
|
||||
maxThreads=100
|
||||
cleanupInterval=1000
|
||||
maxRequestSize=16000
|
||||
maxMultiPartSize=1000000
|
||||
</pre></code>
|
||||
The pool is empty initially and grows with the number of concurrent
|
||||
connections. A timer removes one idle connection handler at each
|
||||
interval, but a it leaves some spare handlers in memory to improve
|
||||
interval, but it leaves some spare handlers in memory to improve
|
||||
performance.
|
||||
@see HttpConnectionHandler for description of config settings readTimeout
|
||||
@see HttpRequest for description of config settings maxRequestSize and maxMultiPartSize
|
||||
@ -59,6 +60,9 @@ private:
|
||||
/** Timer to clean-up unused connection handler */
|
||||
QTimer cleanupTimer;
|
||||
|
||||
/** Used to synchronize threads */
|
||||
QMutex mutex;
|
||||
|
||||
private slots:
|
||||
|
||||
/** Received from the clean-up timer. */
|
||||
|
@ -50,7 +50,6 @@ void HttpListener::incomingConnection(int socketDescriptor) {
|
||||
QTcpSocket* socket=new QTcpSocket(this);
|
||||
socket->setSocketDescriptor(socketDescriptor);
|
||||
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
|
||||
//CAMBIADO 503 por 429
|
||||
socket->write("HTTP/1.1 503 too many connections\r\nConnection: close\r\n\r\nToo many connections\r\n");
|
||||
socket->disconnectFromHost();
|
||||
}
|
||||
|
@ -14,17 +14,6 @@ HttpRequest::HttpRequest(QSettings* settings) {
|
||||
expectedBodySize=0;
|
||||
maxSize=settings->value("maxRequestSize","16000").toInt();
|
||||
maxMultiPartSize=settings->value("maxMultiPartSize","1000000").toInt();
|
||||
|
||||
// Convert relative path to absolute, based on the directory of the config file.
|
||||
#ifdef Q_OS_WIN32
|
||||
if (QDir::isRelativePath(tempDir) && settings->format()!=QSettings::NativeFormat)
|
||||
#else
|
||||
if (QDir::isRelativePath(tempDir))
|
||||
#endif
|
||||
{
|
||||
QFileInfo configFile(settings->fileName());
|
||||
tempDir=QFileInfo(configFile.absolutePath(),tempDir).absoluteFilePath();
|
||||
}
|
||||
}
|
||||
|
||||
void HttpRequest::readRequest(QTcpSocket& socket) {
|
||||
@ -170,15 +159,22 @@ void HttpRequest::decodeRequestParams() {
|
||||
#ifdef SUPERVERBOSE
|
||||
qDebug("HttpRequest: extract and decode request parameters");
|
||||
#endif
|
||||
// Get URL parameters
|
||||
QByteArray rawParameters;
|
||||
if (headers.value("Content-Type")=="application/x-www-form-urlencoded") {
|
||||
rawParameters=bodyData;
|
||||
int questionMark=path.indexOf('?');
|
||||
if (questionMark>=0) {
|
||||
rawParameters=path.mid(questionMark+1);
|
||||
path=path.left(questionMark);
|
||||
}
|
||||
else {
|
||||
int questionMark=path.indexOf('?');
|
||||
if (questionMark>=0) {
|
||||
rawParameters=path.mid(questionMark+1);
|
||||
path=path.left(questionMark);
|
||||
// Get request body parameters
|
||||
QByteArray contentType=headers.value("Content-Type");
|
||||
if (!bodyData.isEmpty() && (contentType.isEmpty() || contentType.startsWith("application/x-www-form-urlencoded"))) {
|
||||
if (rawParameters.isEmpty()) {
|
||||
rawParameters.append('&');
|
||||
rawParameters.append(bodyData);
|
||||
}
|
||||
else {
|
||||
rawParameters=bodyData;
|
||||
}
|
||||
}
|
||||
// Split the parameters into pairs of value and name
|
||||
|
@ -111,8 +111,9 @@ public:
|
||||
|
||||
/**
|
||||
Decode an URL parameter.
|
||||
E.g. replace "%23" by '#' and replace '+' by ' '
|
||||
@param source The url encoded string
|
||||
E.g. replace "%23" by '#' and replace '+' by ' '.
|
||||
@param source The url encoded strings
|
||||
@see QUrl::toPercentEncoding for the reverse direction
|
||||
*/
|
||||
static QByteArray urlDecode(const QByteArray source);
|
||||
|
||||
@ -173,9 +174,6 @@ private:
|
||||
/** Maximum allowed size of multipart forms in bytes. */
|
||||
int maxMultiPartSize;
|
||||
|
||||
/** Directory for temp files */
|
||||
QString tempDir;
|
||||
|
||||
/** Current size */
|
||||
int currentSize;
|
||||
|
||||
|
@ -109,7 +109,6 @@ void HttpResponse::writeText(QString text, bool lastPart)
|
||||
write(text.toAscii(),lastPart);
|
||||
}
|
||||
|
||||
|
||||
bool HttpResponse::hasSentLastPart() const {
|
||||
return sentLastPart;
|
||||
}
|
||||
|
@ -7,15 +7,14 @@
|
||||
#include <QDateTime>
|
||||
#include <QUuid>
|
||||
|
||||
#include "comic.h"
|
||||
|
||||
HttpSession::HttpSession(bool canStore) {
|
||||
if (canStore) {
|
||||
dataPtr=new HttpSessionData();
|
||||
dataPtr->yacreaderSessionData.comic = 0;
|
||||
dataPtr->refCount=1;
|
||||
dataPtr->lastAccess=QDateTime::currentMSecsSinceEpoch();
|
||||
dataPtr->id=QUuid::createUuid().toString().toAscii();
|
||||
dataPtr->yacreaderSessionData.comic = 0;
|
||||
#ifdef SUPERVERBOSE
|
||||
qDebug("HttpSession: created new session data with id %s",dataPtr->id.data());
|
||||
#endif
|
||||
@ -159,7 +158,6 @@ void HttpSession::setLastAccess() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//AÑADIDO
|
||||
bool HttpSession::isComicOnDevice(const QString & hash)
|
||||
{
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
class Comic;
|
||||
|
||||
/**
|
||||
This class stores data for a single HTTP session.
|
||||
A session can store any number of key/value pairs. This class uses implicit
|
||||
@ -114,26 +115,26 @@ private:
|
||||
Comic * comic;
|
||||
};
|
||||
|
||||
struct HttpSessionData {
|
||||
struct HttpSessionData {
|
||||
|
||||
/** Unique ID */
|
||||
QByteArray id;
|
||||
/** Unique ID */
|
||||
QByteArray id;
|
||||
|
||||
/** Timestamp of last access, set by the HttpSessionStore */
|
||||
qint64 lastAccess;
|
||||
/** Timestamp of last access, set by the HttpSessionStore */
|
||||
qint64 lastAccess;
|
||||
|
||||
/** Reference counter */
|
||||
int refCount;
|
||||
/** Reference counter */
|
||||
int refCount;
|
||||
|
||||
/** Used to synchronize threads */
|
||||
QReadWriteLock lock;
|
||||
/** Used to synchronize threads */
|
||||
QReadWriteLock lock;
|
||||
|
||||
/** Storage for the key/value pairs; */
|
||||
QMap<QByteArray,QVariant> values;
|
||||
/** Storage for the key/value pairs; */
|
||||
QMap<QByteArray,QVariant> values;
|
||||
|
||||
YACReaderSessionData yacreaderSessionData;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
/** Pointer to the shared data. */
|
||||
HttpSessionData* dataPtr;
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
class HttpSessionStore : public QObject {
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(HttpSessionStore);
|
||||
Q_DISABLE_COPY(HttpSessionStore)
|
||||
public:
|
||||
|
||||
/** Constructor. */
|
||||
|
@ -42,14 +42,18 @@ void StaticFileController::service(HttpRequest& request, HttpResponse& response)
|
||||
}
|
||||
// Check if we have the file in cache
|
||||
qint64 now=QDateTime::currentMSecsSinceEpoch();
|
||||
mutex.lock();
|
||||
CacheEntry* entry=cache.object(path);
|
||||
if (entry && (cacheTimeout==0 || entry->created>now-cacheTimeout)) {
|
||||
if (entry && (cacheTimeout==0 || entry->created>now-cacheTimeout)) {
|
||||
QByteArray document=entry->document; //copy the cached document, because other threads may destroy the cached entry immediately after mutex unlock.
|
||||
mutex.unlock();
|
||||
qDebug("StaticFileController: Cache hit for %s",path.data());
|
||||
setContentType(path,response);
|
||||
response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000));
|
||||
response.write(entry->document);
|
||||
response.write(document);
|
||||
}
|
||||
else {
|
||||
mutex.unlock();
|
||||
qDebug("StaticFileController: Cache miss for %s",path.data());
|
||||
// The file is not in cache.
|
||||
// If the filename is a directory, append index.html.
|
||||
@ -65,11 +69,11 @@ void StaticFileController::service(HttpRequest& request, HttpResponse& response)
|
||||
fileName = getLocalizedFileName(fileName, request.getHeader("Accept-Language"), stringPath);
|
||||
QString newPath = stringPath.append(fileName);
|
||||
//END_TODO
|
||||
QFile file(docroot+newPath);
|
||||
QFile file(docroot+path);
|
||||
if (file.exists()) {
|
||||
qDebug("StaticFileController: Open file %s",qPrintable(file.fileName()));
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
setContentType(newPath,response);
|
||||
setContentType(path,response);
|
||||
response.setHeader("Cache-Control","max-age="+QByteArray::number(maxAge/1000));
|
||||
if (file.size()<=maxCachedFileSize) {
|
||||
// Return the file content and store it also in the cache
|
||||
@ -80,7 +84,9 @@ void StaticFileController::service(HttpRequest& request, HttpResponse& response)
|
||||
entry->document.append(buffer);
|
||||
}
|
||||
entry->created=now;
|
||||
mutex.lock();
|
||||
cache.insert(request.getPath(),entry,entry->document.size());
|
||||
mutex.unlock();
|
||||
}
|
||||
else {
|
||||
// Return the file content, do not store in cache
|
||||
@ -113,22 +119,23 @@ void StaticFileController::setContentType(QString fileName, HttpResponse& respon
|
||||
else if (fileName.endsWith(".gif")) {
|
||||
response.setHeader("Content-Type", "image/gif");
|
||||
}
|
||||
else if (fileName.endsWith(".pdf")) {
|
||||
response.setHeader("Content-Type", "application/pdf");
|
||||
}
|
||||
else if (fileName.endsWith(".txt")) {
|
||||
response.setHeader("Content-Type", qPrintable("text/plain; charset="+encoding));
|
||||
}
|
||||
else if (fileName.endsWith(".html") || fileName.endsWith(".htm")) {
|
||||
response.setHeader("Content-Type", qPrintable("text/html; charset=charset="+encoding));
|
||||
response.setHeader("Content-Type", qPrintable("text/html; charset="+encoding));
|
||||
}
|
||||
else if (fileName.endsWith(".js"))
|
||||
response.setHeader("Content-Type", qPrintable("text/javascript; charset=charset="+encoding));
|
||||
// Todo: add all of your content types
|
||||
}
|
||||
|
||||
bool StaticFileController::exists(QString localizedName, QString path) const
|
||||
{
|
||||
QString fileName=docroot+"/"+path + localizedName;
|
||||
QFile file(fileName);
|
||||
return file.exists();
|
||||
QString fileName=docroot+"/"+path + localizedName;
|
||||
QFile file(fileName);
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
//retorna fileName si no se encontró alternativa traducida ó fileName-locale.extensión si se encontró
|
||||
@ -164,4 +171,3 @@ QString StaticFileController::getLocalizedFileName(QString fileName, QString loc
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "httpresponse.h"
|
||||
#include "httprequesthandler.h"
|
||||
#include <QCache>
|
||||
#include <QMutex>
|
||||
|
||||
/**
|
||||
Delivers static files. It is usually called by the applications main request handler when
|
||||
@ -74,10 +75,13 @@ private:
|
||||
/** Cache storage */
|
||||
QCache<QString,CacheEntry> cache;
|
||||
|
||||
/** Used to synchronize cache access for threads */
|
||||
QMutex mutex;
|
||||
|
||||
/** Set a content-type header in the response depending on the ending of the filename */
|
||||
void setContentType(QString file, HttpResponse& response) const;
|
||||
|
||||
QString getLocalizedFileName(QString fileName, QString locales, QString path) const;
|
||||
QString StaticFileController::getLocalizedFileName(QString fileName, QString locales, QString path) const;
|
||||
|
||||
bool exists(QString localizedName, QString path) const;
|
||||
};
|
||||
|
@ -49,7 +49,7 @@ QString LogMessage::toString(const QString& msgFormat, const QString& timestampF
|
||||
}
|
||||
|
||||
QString threadId;
|
||||
threadId.setNum((qint64)QThread::currentThreadId());
|
||||
threadId.setNum((unsigned int)QThread::currentThreadId());
|
||||
decorated.replace("{thread}",threadId);
|
||||
|
||||
// Fill in variables
|
||||
|
@ -33,7 +33,7 @@ int Template::setVariable(QString name, QString value) {
|
||||
while (start>=0) {
|
||||
replace(start, variable.length(), value);
|
||||
count++;
|
||||
start=indexOf(variable,start+variable.length());
|
||||
start=indexOf(variable,start+value.length());
|
||||
}
|
||||
if (count==0 && warnings) {
|
||||
qWarning("Template: missing variable %s in %s",qPrintable(variable),qPrintable(sourceName));
|
||||
|
Loading…
x
Reference in New Issue
Block a user