3 #include <QCoreApplication>
9 #include "qhttpserver.h"
10 #include "qhttprequest.h"
11 #include "qhttpresponse.h"
43 :
VFS_httpd(port,addr,ssl,sslCertPath,sslKeyPath)
44 , _dataRootPath(dataRootPath)
78 if (r->
_mode ==
"browse")
81 QString p = r->
_path.mid(strlen(
"/browse"));
82 p = QUrl::fromPercentEncoding(p.toUtf8());
86 else if (r->
_mode ==
"report")
89 QString p = r->
_path.mid(strlen(
"/report"));
90 p = QUrl::fromPercentEncoding(p.toUtf8());
94 else if (r->
_mode ==
"read")
97 QString p = r->
_path.mid(strlen(
"/read"));
98 p = QUrl::fromPercentEncoding(p.toUtf8());
200 , _needsToIssueRequest(false)
206 connect(
_m_req, SIGNAL(data(
const QByteArray&)),
this, SLOT(
accumulate(
const QByteArray&)), Qt::UniqueConnection);
207 connect(
_m_resp, SIGNAL(
done()),
this, SLOT(
done()), Qt::UniqueConnection);
293 if (
_path.startsWith(
"/browse"))
300 else if (
_path.startsWith(
"/report"))
307 else if (
_path.startsWith(
"/read"))
310 _mime =
"application/json";
314 else if (
_path.startsWith(
"/status"))
317 _mime =
"application/json";
320 else if (
_path.startsWith(
"/command"))
326 else if (!QFile::exists(
":/VFS_httpd_browser"+
_path))
335 QFileInfo info(
_path);
339 if (info.suffix().toLower()==
"rhtml")
_process =
true;
359 if (
_mode ==
"browse")
361 _path.remove(0, strlen(
"/browse"));
364 else if (
_mode ==
"report")
367 reply =
_data.toJson();
369 else if (
_mode ==
"read")
371 reply =
_data.toJson();
373 else if (
_mode ==
"status")
375 QStringList pp =
_path.split(
"/",Qt::SkipEmptyParts);
406 return QJsonDocument(o).toJson(QJsonDocument::Compact);
408 else if (pp[0]==
"requests")
414 return QJsonDocument(r).toJson(QJsonDocument::Compact);
416 else if (pp[0] ==
"outstanding")
418 QJsonObject oo {{
"outstanding",r[
"outstanding"]}};
419 return QJsonDocument(oo).toJson(QJsonDocument::Compact);
421 else if (pp[0] ==
"sample")
423 QJsonObject oo {{
"sample",r[
"sample"]}};
424 return QJsonDocument(oo).toJson(QJsonDocument::Compact);
427 else if (pp[0]==
"system")
433 return QJsonDocument(s).toJson(QJsonDocument::Compact);
435 else if (pp[0] ==
"cpu")
437 return QJsonDocument(s[
"cpu"].toObject()).toJson(QJsonDocument::Compact);
439 else if (pp[0] ==
"memory")
441 return QJsonDocument(s[
"memory"].toObject()).toJson(QJsonDocument::Compact);
443 else if (pp[0] ==
"uptime")
445 return QJsonDocument(s[
"uptime"].toObject()).toJson(QJsonDocument::Compact);
450 VFS::WARN( QString(
"unknown status request: %1").arg(
_path), 0,
"httpd_browser" );
453 else if (
_mode ==
"command")
455 _path.remove(0, strlen(
"/command/"));
458 { QCoreApplication::exit(0);
461 else if (
_path ==
"parameters")
468 VFS::WARN( QString(
"unknown command: %1").arg(
_path), 0,
"httpd_browser" );
472 else if (
_mode ==
"file")
474 QFile page(
":/VFS_httpd_browser"+
_path);
475 if (!page.open(QIODevice::ReadOnly))
482 reply = page.readAll();
508 QJsonObject o =
_data.object();
509 QJsonObject::iterator i = o.begin();
511 reply +=
"<ul class='dirListing'>\n";
518 reply += QString(
"\t<li class='vfs_node vfs_node_closed' path='"+
_path+
"/"+s+
"'>" + s +
"</li>\n").toUtf8();
553 QRegExp token(
"\\[###(.*)###\\]");
554 token.setMinimal(
true);
558 QByteArray processed;
560 while(token.indexIn(page) > -1)
562 QStringList commandArgs = token.capturedTexts()[1].split(
",");
563 QString command = commandArgs.takeFirst().toLower();
565 if (command==
"hostname") processed = QHostInfo::localHostName().toUtf8();
566 else if (command==
"port") processed = QString(
"%1").arg(
_port).toUtf8();
567 else if (command==
"app_path") processed = QCoreApplication::applicationFilePath().toUtf8();
568 else if (command==
"arguments") processed = QCoreApplication::arguments().join(
" ").toUtf8();
569 else if (command==
"version") processed = QCoreApplication::applicationVersion().toUtf8();
570 else if (command==
"starttime") processed = QDateTime::fromMSecsSinceEpoch(
VFS::starttime()).toString(Qt::TextDate).toUtf8();
573 else processed = QString(
"<div class='warning'>Unknown Command: <b>%1</b></div>").arg(command).toUtf8();
575 page = page.replace(token.pos(0),token.matchedLength(),processed);
595 QString kernel = QSysInfo::kernelType().toLower();
599 if (kernel ==
"linux")
601 if (which ==
"cpucount")
603 command =
"grep -c ^processor /proc/cpuinfo";
605 else if (which ==
"cpusample")
607 command =
"sar -u 1 1 | grep verage | perl -pe \"s/\\s+/+/g\" | cut -f 3,5 -d '+' | bc -l";
611 else if (which ==
"memtotal")
613 command =
"awk '( $1 == \"MemTotal:\" ) { print $2/1048576 }' /proc/meminfo";
616 else if (which ==
"memsample")
618 command =
"free -b | grep Mem | perl -pe \"s/\\s+/ /g\" | cut -f 2,4 -d \" \" | perl -pe \"s/\\s+/ \\/ /\" | perl -pe \"s/(.*)/scale=10; 100*(1-1\\/(\\1))/\" | bc -l";
622 else if (kernel ==
"darwin")
624 if (which ==
"cpucount")
626 command =
"sysctl -n hw.ncpu";
628 else if (which ==
"cpusample")
630 command =
"ps -A -o %cpu | awk '{s+=$1} END {print s}'";
633 else if (which ==
"memtotal")
635 command =
"awk '( $1 == \"MemTotal:\" ) { print $2/1048576 }' /proc/meminfo";
638 else if (which ==
"memsample")
641 command =
"memory_pressure | grep percentage | perl -pe \"s/([^\\d]*)(\\d+)([^\\d]*)/scale=20; \\2 \\/ 100\\n/\" | bc -l";
646 VFS::ERROR(QString(
"Unknown kernel: %1. Can't fetch system value.").arg(kernel),0,
"httpd_browser");
648 if (!command.isEmpty())
651 process.start(
"bash", QStringList() <<
"-c" << command);
652 process.waitForFinished(5000);
654 QString stdout = process.readAllStandardOutput();
655 QString stderr = process.readAllStandardError();
660 if (!stderr.isEmpty())
663 return stdout.trimmed()+suffix;
666 return QJsonValue::Null;
A subclass of VFS_request.
virtual void execute()
Execute the request now that it has been satisfied.
VFS_httpd_browser_responder * _m_responder
The responder object used during execute()
VFS_httpd_browser_request(VFS_request::requestType type, VFS_node *t, VFS_httpd_browser_responder *r)
virtual ~VFS_httpd_browser_request()
A subclass of VFS_httpd_responder.
QJsonValue getSystemValue(QString which)
Return information about the system running VFS.
virtual void respond()
based on http status, write page contents or an error to the responder
QByteArray fetchResponse()
Actually fetch and/or prep the response data.
QByteArray lsDir()
Convert an incoming json object to an html <ul> for display.
virtual void validatePath(QUrl url)
Based on the incoming url, decide what work needs to be done.
QJsonDocument _data
The response data, populated after a VFS_request is complete, or immediately if not asynchronous.
virtual ~VFS_httpd_browser_responder()
void done()
Mark the responder as _done, and schedule a deletion with deleteLater().
QByteArray processRHTML(QByteArray page)
Detokenize an .rhtml file.
QString _mode
either browse, report, command, or file. Used in fetchFile()
bool _process
A flag meaning that the response data must be detokenized. This is used for .rhtml files.
quint16 _port
The port that VFS_httpd_browser is listening on. Only used as a print value when processing ....
VFS_httpd_browser_responder(QHttpRequest *req, QHttpResponse *resp, VFS_node *node, quint16 port)
bool _needsToIssueRequest
A flag that means the request is asynchronous and will be satisfied after a VFS_request completes.
bool _done
If the _m_resp has finished, or was aborted or deleted, mark this as true.
Q_INVOKABLE VFS_httpd_browser(QString dataRootPath, quint16 port, QHostAddress addr=QHostAddress::Any, bool ssl=false, QString sslCertPath="", QString sslKeyPath="")
virtual void handle(QHttpRequest *req, QHttpResponse *resp)
Handle an incoming request.
VFS_node * dataRoot()
Resolve the _dataRootPath into a VFS_node.
virtual ~VFS_httpd_browser()
VFS_node * _dataRoot
The node found by resolving _dataRootPath.
QString _dataRootPath
The VFS root path to serve from.
Holds the request and response objects for future use.
QHttpResponse * _m_resp
http response object
virtual void accumulate(const QByteArray &)
This seems to be used during an http push request.
QString _path
path component of url
QHttpRequest * _m_req
http request object
virtual QByteArray errorPage()
The default error page.
QString _mime
mime type to send
Creates httpd server node for VFS.
static QHash< QString, QString > MIME_TYPES
The mime type map.
VFS_node is the base class from which all other VFS_node classes derive.
virtual void issueRequest(VFS_request *t)
A convenience function.
VFS_node * find(QString path)
Find a node by string path.
QString className()
Return the class name of a node.
The base class for all requests between nodes.
requestType
Requests perform one of these actions.
@ read
read full contents (4)
@ report
provide node report, for debugging (12)
@ ls
list children of a node (1)
static quint32 _sampleCount
A count of the number of VFS_requests since the last sample was taken.
QString _reason
if something (probably bad) happened, this is the reason
QString _path
the target path remnant... the remaining path element once the request has found its target
bool _success
if the request was successfully completed
QJsonDocument _data
the request payload
static long _refcount
A reference counter for VFS_request instances, used for debugging to ensure all instances are properl...
quint16 _port
TCP port to listen on, or 0 to find an available one.
static VFS * root()
Return the root node of the VFS filesystem.
static void LOG(QString message, int level=0, QString user="server")
Send a message to the VFS::_messages VFS_stream.
static void ERROR(QString message, int level=0, QString user="server")
Send a message to the VFS::_errors VFS_stream.
static QString uptimeString(bool ms=true)
Get the uptime of this VFS instance as a string.
static void WARN(QString message, int level=0, QString user="server")
Send a message to the VFS::_warnings VFS_stream.
static qint64 starttime()
Get the epoch start time of this VFS instance, in milliseconds.
static qint64 uptime()
Get the uptime of this VFS instance, in milliseconds.
static QJsonDocument parameters()
Fetch the parameters assigned to this VFS, as per the config file.
setter type
a setter DOCME