APIController.cpp   APIController.cpp 
skipping to change at line 21 skipping to change at line 21
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*/ */
#include "APIController.hpp" #include "APIController.hpp"
#include "StelApp.hpp"
#include <QJsonDocument> #include <QJsonDocument>
#include <QThread>
int APIServiceResponse::metaTypeId = qRegisterMetaType<APIServiceResponse>(
);
int APIServiceResponse::parametersMetaTypeId = qRegisterMetaType<APIParamet
ers>();
APIController::APIController(int prefixLength, QObject* parent) : HttpReque stHandler(parent), m_prefixLength(prefixLength) APIController::APIController(int prefixLength, QObject* parent) : HttpReque stHandler(parent), m_prefixLength(prefixLength)
{ {
} }
APIController::~APIController() APIController::~APIController()
{ {
qDeleteAll(m_serviceMap); //Services are not deleted here
m_serviceMap.clear(); //use the QObject parent relationship for that
} }
void APIController::update(double deltaTime) void APIController::update(double deltaTime)
{ {
mutex.lock(); for(ServiceMap::iterator it = m_serviceMap.begin();it!=m_serviceMap.
foreach(AbstractAPIService* service, m_serviceMap) end();++it)
{
(*it)->update(deltaTime);
}
}
void APIController::registerService(RemoteControlServiceInterface *service)
{
QByteArray key = service->getPath().latin1();
if(m_serviceMap.contains(key))
{ {
service->update(deltaTime); qWarning()<<"Service"<<key<<"already registered, skipping...
";
return;
} }
mutex.unlock(); m_serviceMap.insert(key, service);
} }
void APIController::registerService(AbstractAPIService *service) void APIController::performGet(RemoteControlServiceInterface *service, cons t QByteArray &operation, const APIParameters &parameters, APIServiceRespons e *response)
{ {
m_serviceMap.insert(service->serviceName(), service); Q_ASSERT(QThread::currentThread() == StelApp::getInstance().thread()
);
service->get(operation, parameters, *response);
}
void APIController::performPost(RemoteControlServiceInterface *service, con
st QByteArray &operation, const APIParameters &parameters, const QByteArray
&data, APIServiceResponse *response)
{
Q_ASSERT(QThread::currentThread() == StelApp::getInstance().thread()
);
service->post(operation, parameters, data, *response);
} }
void APIController::service(HttpRequest &request, HttpResponse &response) void APIController::service(HttpRequest &request, HttpResponse &response)
{ {
//disable caching by default for services //disable caching by default for services
response.setHeader("Cache-Control","no-cache"); response.setHeader("Cache-Control","no-cache");
//default content type is text //default content type is text
response.setHeader("Content-Type","text/plain"); response.setHeader("Content-Type","text/plain");
//use the raw path here //use the raw path here
skipping to change at line 71 skipping to change at line 92
QByteArray serviceString = pathWithoutPrefix; QByteArray serviceString = pathWithoutPrefix;
QByteArray operation; QByteArray operation;
if(slashIdx>=0) if(slashIdx>=0)
{ {
serviceString = pathWithoutPrefix.mid(0,slashIdx); serviceString = pathWithoutPrefix.mid(0,slashIdx);
operation = pathWithoutPrefix.mid(slashIdx+1); operation = pathWithoutPrefix.mid(slashIdx+1);
} }
//try to find service //try to find service
//the mutex here is to prevent a very strange crash I had, in which
sv is an invalid pointer (but m_serviceMap is ok)
//probably caused by the foreach loop in update in the main thread?
mutex.lock();
ServiceMap::iterator it = m_serviceMap.find(serviceString); ServiceMap::iterator it = m_serviceMap.find(serviceString);
if(it!=m_serviceMap.end()) if(it!=m_serviceMap.end())
{ {
AbstractAPIService* sv = *it; RemoteControlServiceInterface* sv = *it;
mutex.unlock();
//create the response object //create the response object
APIServiceResponse apiresponse; APIServiceResponse apiresponse;
if(request.getMethod()=="GET") if(request.getMethod()=="GET")
{ {
#ifdef FORCE_THREADED_SERVICES #ifdef FORCE_THREADED_SERVICES
apiresponse = sv->get(operation, request.getParamete rMap()); sv->get(operation, request.getParameterMap(), apires ponse);
#else #else
if(sv->supportsThreadedOperation()) if(sv->isThreadSafe())
{ {
apiresponse = sv->get(operation, request.get ParameterMap()); sv->get(operation,request.getParameterMap(), apiresponse);
} }
else else
{ {
//invoke it in the main thread! //invoke it in the main thread!
QMetaObject::invokeMethod(sv,"get",Qt::Block QMetaObject::invokeMethod(this,"performGet",
ingQueuedConnection, Qt::BlockingQueuedConnection,
Q_RETURN_ARG(APISe Q_ARG(RemoteContro
rviceResponse, apiresponse), lServiceInterface*, sv),
Q_ARG(QByteArray, operation), Q_ARG(QByteArray, operation),
Q_ARG(APIParameter Q_ARG(APIParameter
s, request.getParameterMap())); s, request.getParameterMap()),
Q_ARG(APIServiceRe
sponse*, &apiresponse));
} }
#endif #endif
apiresponse.applyResponse(&response); applyAPIResponse(apiresponse,response);
} }
else if (request.getMethod()=="POST") else if (request.getMethod()=="POST")
{ {
#ifdef FORCE_THREADED_SERVICES #ifdef FORCE_THREADED_SERVICES
apiresponse = sv->post(operation, request.getParamet erMap(), request.getBody()); sv->post(operation, request.getParameterMap(), reque st.getBody(), apiresponse);
#else #else
if(sv->supportsThreadedOperation()) if(sv->isThreadSafe())
{ {
apiresponse = sv->post(operation, request.ge tParameterMap(), request.getBody()); sv->post(operation, request.getParameterMap( ), request.getBody(), apiresponse);
} }
else else
{ {
QMetaObject::invokeMethod(sv,"post",Qt::Bloc QMetaObject::invokeMethod(this,"performPost"
kingQueuedConnection, ,Qt::BlockingQueuedConnection,
Q_RETURN_ARG(APISe Q_ARG(RemoteContro
rviceResponse, apiresponse), lServiceInterface*, sv),
Q_ARG(QByteArray, operation), Q_ARG(QByteArray, operation),
Q_ARG(APIParameter s, request.getParameterMap()), Q_ARG(APIParameter s, request.getParameterMap()),
Q_ARG(QByteArray, Q_ARG(QByteArray,
request.getBody())); request.getBody()),
Q_ARG(APIServiceRe
sponse*, &apiresponse));
} }
#endif #endif
apiresponse.applyResponse(&response); applyAPIResponse(apiresponse,response);
} }
else else
{ {
response.setStatus(405,"Method Not allowed"); response.setStatus(405,"Method Not allowed");
QString str(QStringLiteral("Method %1 not allowed fo r service %2")); QString str(QStringLiteral("Method %1 not allowed fo r service %2"));
response.write(str.arg(QString::fromLatin1(request.g etMethod())).arg(QString::fromUtf8(pathWithoutPrefix)).toUtf8(),true); response.write(str.arg(QString::fromLatin1(request.g etMethod())).arg(QString::fromUtf8(pathWithoutPrefix)).toUtf8(),true);
} }
} }
else else
{ {
mutex.unlock();
response.setStatus(400,"Bad Request"); response.setStatus(400,"Bad Request");
QString str(QStringLiteral("Unknown service: '%1'\n\nAvailab le services:\n").arg(QString::fromUtf8(pathWithoutPrefix))); QString str(QStringLiteral("Unknown service: '%1'\n\nAvailab le services:\n").arg(QString::fromUtf8(pathWithoutPrefix)));
for(ServiceMap::iterator it = m_serviceMap.begin();it!=m_ser viceMap.end();++it) for(ServiceMap::iterator it = m_serviceMap.begin();it!=m_ser viceMap.end();++it)
{ {
str.append(QString::fromUtf8(it.key())); str.append(QString::fromUtf8(it.key()));
str.append("\n"); str.append("\n");
} }
response.write(str.toUtf8(),true); response.write(str.toUtf8(),true);
} }
} }
void APIController::applyAPIResponse(const APIServiceResponse &apiresponse,
HttpResponse &httpresponse)
{
if(apiresponse.status != -1)
{
httpresponse.setStatus(apiresponse.status, apiresponse.statu
sText);
}
//apply headers
httpresponse.getHeaders().unite(apiresponse.headers);
//send response data, if any
if(apiresponse.responseData.isEmpty())
{
httpresponse.getHeaders().clear();
httpresponse.setStatus(500,"Internal Server Error");
httpresponse.write("Service provided no response",true);
}
httpresponse.write(apiresponse.responseData,true);
}
 End of changes. 24 change blocks. 
35 lines changed or deleted 62 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/