Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement HTTP API #3599

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions Server/mods/deathmatch/logic/CAPI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include "StdInc.h"
#include "CAPI.h"
#include "CGame.h"
#include "CMainConfig.h"
#include <SharedUtil.String.h>

namespace Endpoints
{
inline const std::string API_ENDPOINT = "/api";
namespace Server
{
inline const std::string PLAYERS = "/players";
inline const std::string MAX_PLAYERS = PLAYERS + "/max";
TracerDS marked this conversation as resolved.
Show resolved Hide resolved
}
}

const bool GetNextPathFragment(std::string& path) noexcept
TracerDS marked this conversation as resolved.
Show resolved Hide resolved
{
auto index = path.find('/', 1);
if (index == path.npos)
return false;

path = path.substr(index);
return true;
};

ResponseCode CAPI::HandleRequest(HttpRequest* request, HttpResponse* response)
{
response->oResponseHeaders["content-type"] = "application/json";

std::string uri = request->sOriginalUri;

if (!SharedUtil::StartsWith(uri, Endpoints::API_ENDPOINT))
return HTTPRESPONSECODE_404_NOTFOUND;

if (!GetNextPathFragment(uri))
return HTTPRESPONSECODE_404_NOTFOUND;

if (SharedUtil::StartsWith(uri, Endpoints::Server::PLAYERS))
{
return HandlePlayers(request, response);
}

std::string body("{\"error\": \"404: Not Found\"}");
response->SetBody(body.c_str(), body.size());
TracerDS marked this conversation as resolved.
Show resolved Hide resolved
return HTTPRESPONSECODE_404_NOTFOUND;
}

ResponseCode CAPI::HandlePlayers(HttpRequest* request, HttpResponse* response)
{
std::string uri = request->sOriginalUri;
// skip /api/server
if (!GetNextPathFragment(uri) && !GetNextPathFragment(uri))
{
std::string body("{\"error\": \"404: Not Found\"}");
response->SetBody(body.c_str(), body.size());
return HTTPRESPONSECODE_404_NOTFOUND;
}

if (!GetNextPathFragment(uri))
{
// /players

auto players = g_pGame->GetPlayerManager()->GetPlayers();
SString body("{\"players\": %llu}", players.size());
response->SetBody(body.c_str(), body.size());
return HTTPRESPONSECODE_200_OK;
}
if (uri == Endpoints::Server::MAX_PLAYERS)
{
// players/max

SString body("{\"max\": %llu}", g_pGame->GetConfig()->GetMaxPlayers());
response->SetBody(body.c_str(), body.size());
return HTTPRESPONSECODE_200_OK;
}

std::string body("{\"error\": \"404: Not Found\"}");
response->SetBody(body.c_str(), body.size());
return HTTPRESPONSECODE_404_NOTFOUND;
}
21 changes: 21 additions & 0 deletions Server/mods/deathmatch/logic/CAPI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: mods/deathmatch/logic/CAPI.h
* PURPOSE: API interface for HTTP
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/
#pragma once

#include <ehs/ehs.h>

class CAPI : public EHS {
public:
ResponseCode HandleRequest(HttpRequest* request, HttpResponse* response) override;

private:
ResponseCode HandlePlayers(HttpRequest* request, HttpResponse* response);
};
2 changes: 2 additions & 0 deletions Server/mods/deathmatch/logic/CGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,8 @@ bool CGame::Start(int iArgumentCount, char* szArguments[])
}
}

m_pHTTPD->StartAPI();

m_pFunctionUseLogger = new CFunctionUseLogger(m_pMainConfig->GetLoadstringLogFilename());

// Setup server id
Expand Down
24 changes: 23 additions & 1 deletion Server/mods/deathmatch/logic/CHTTPD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@

#include "StdInc.h"
#include "CHTTPD.h"
#include "CAPI.h"
#include "CGame.h"
#include "CAccountManager.h"
#include "CMainConfig.h"
#include <cryptopp/rsa.h>
#include <cryptopp/osrng.h>
#include <SharedUtil.Crypto.h>
#include <SharedUtil.String.h>

#ifndef WIN32
#ifndef _WIN32
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
Expand Down Expand Up @@ -91,6 +93,24 @@ bool CHTTPD::StartHTTPD(const char* szIP, unsigned int port)
return bResult;
}

void CHTTPD::StartAPI() noexcept
{
m_apiEHS = new CAPI;
TracerDS marked this conversation as resolved.
Show resolved Hide resolved

this->RegisterEHS(m_apiEHS, "api");
}

void CHTTPD::StopAPI() noexcept
{
if (!m_apiEHS)
return;

this->UnregisterEHS("api");

delete m_apiEHS;
m_apiEHS = nullptr;
}

// Called from worker thread. Careful now.
// Do some stuff before allowing EHS to do the proper routing
HttpResponse* CHTTPD::RouteRequest(HttpRequest* ipoHttpRequest)
Expand All @@ -113,6 +133,8 @@ HttpResponse* CHTTPD::RouteRequest(HttpRequest* ipoHttpRequest)
return poHttpResponse;
}



// Called from worker thread. g_pGame->Lock() has already been called.
// creates a page based on user input -- either displays data from
// form or presents a form for users to submit data.
Expand Down
7 changes: 7 additions & 0 deletions Server/mods/deathmatch/logic/CHTTPD.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <ehs/ehs.h>

class CResource;
class CAPI;

class CHTTPD : public EHS
{
Expand All @@ -40,9 +41,13 @@ class CHTTPD : public EHS
void SetDefaultResource(const char* szResourceName) { m_strDefaultResourceName = szResourceName ? szResourceName : ""; }
HttpStatusCode RequestLogin(HttpRequest* ipoHttpRequest, HttpResponse* ipoHttpResponse);

void StartAPI() noexcept;
void StopAPI() noexcept;

private:
CResource* m_resource{};
CHTTPD* m_server{};

std::string m_strDefaultResourceName; // default resource name

EHSServerParameters m_Parameters;
Expand All @@ -58,4 +63,6 @@ class CHTTPD : public EHS
std::mutex m_mutexLoggedInMap;
SString m_strWarnMessageForIp;
CElapsedTime m_WarnMessageTimer;

CAPI* m_apiEHS;
};
3 changes: 3 additions & 0 deletions Server/mods/deathmatch/logic/CPlayerManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class CPlayerManager
CPlayer* Get(const NetServerPlayerID& PlayerSocket);
CPlayer* Get(const char* szNick, bool bCaseSensitive = false);

CMappedList<CPlayer*>& GetPlayers() noexcept { return m_Players; }
const CMappedList<CPlayer*>& GetPlayers() const noexcept { return m_Players; }

std::list<CPlayer*>::const_iterator IterBegin() { return m_Players.begin(); };
std::list<CPlayer*>::const_iterator IterEnd() { return m_Players.end(); };

Expand Down
26 changes: 26 additions & 0 deletions Shared/sdk/SharedUtil.String.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: SharedUtil.String.h
* PURPOSE: String utilities
*
* Multi Theft Auto is available from http://www.multitheftauto.com/
*
*****************************************************************************/
#pragma once

#include <string>

namespace SharedUtil
{
inline bool StartsWith(const std::string& what, const std::string& with) noexcept
{
return !what.rfind(with, 0);
}

inline bool EndsWith(const std::string& what, const std::string& with) noexcept
{
return !what.compare(what.size() - with.size(), with.size(), with);
}
}
Loading