This commit is contained in:
2025-07-03 20:01:19 +03:00
parent 802598be79
commit dfa8542fb2
13 changed files with 423 additions and 218 deletions
+206 -12
View File
@@ -5,6 +5,7 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using WebmrAPI.Models;
using WebmrAPI.Services;
using WebmrAPI.Services.Scanners;
namespace WebmrAPI.Controllers
{
@@ -34,13 +35,41 @@ namespace WebmrAPI.Controllers
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IEnumerable<ProcessBaseInfo>))]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public IActionResult GetProcesses([FromQuery] bool pretty = false)
public IActionResult GetProcesses(
[FromQuery] bool pretty = false,
[FromQuery] string sortBy = "",
[FromQuery] bool desc = false,
[FromQuery] int limit = 0,
[FromQuery] int offset = 0
)
{
try
{
var processes = _monitor.GetBufferedProcesses();
return Content(GetFormattedJson(processes, pretty), "application/json");
var data = _monitor.GetBufferedProcesses();
if (data != null && !String.IsNullOrEmpty(sortBy))
{
sortBy = sortBy.ToLowerInvariant();
switch (sortBy)
{
case "pid": data = Sort(data, p => p.PID, desc); break;
case "memaddress": data = Sort(data, p => p.MemoryAddress, desc); break;
case "memsize": data = Sort(data, p => p.MemorySize, desc); break;
case "parentpid": data = Sort(data, p => p.ParentPID, desc); break;
case "name": data = Sort(data, p => p.Name, desc); break;
case "filename": data = Sort(data, p => p.FileName, desc); break;
case "commandline": data = Sort(data, p => p.CommandLine, desc); break;
case "threadcount": data = Sort(data, p => p.ThreadCount, desc); break;
case "status": data = Sort(data, p => p.Status, desc); break;
case "starttime": data = Sort(data, p => p.StartTime, desc); break;
case "cpuusage": data = Sort(data, p => p.CpuUsage, desc); break;
default: return StatusCode(StatusCodes.Status400BadRequest, $"Unexpected search filter {sortBy}.");
}
}
return Content(GetFormattedJson(Paginate(data, limit, offset), pretty), "application/json");
}
catch (Exception ex)
{
@@ -53,11 +82,13 @@ namespace WebmrAPI.Controllers
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ProcessInfo))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public IActionResult GetProcessById(int pid, [FromQuery] bool pretty = false)
async public Task<IActionResult> GetProcessById(int pid,
[FromQuery] bool pretty = false
)
{
try
{
var data = _monitor.GetProcessDetails(pid);
var data = await _monitor.GetProcessDetails(pid, ScanTarget.ProcessDetails);
if (data == null)
{
return NotFound($"The process with the PID {pid} was not found or its details could not be obtained.");
@@ -71,12 +102,175 @@ namespace WebmrAPI.Controllers
}
}
// TODO: Добавить эндпоинты для:
// - /api/Process/{pid}/memory_regions
// - /api/Process/{pid}/modules
// - /api/Process/{pid}/threads
// - Поиск по имени
// - Пагинация
// - Нагрузка на CPU
[HttpGet("{pid}/base_info")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ProcessBaseInfo))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
async public Task<IActionResult> GetProcessBaseInfoById(int pid,
[FromQuery] bool pretty = false
)
{
try
{
var data = await _monitor.GetProcessDetails(pid, 0);
if (data == null)
{
return NotFound($"The process with the PID {pid} was not found or its details could not be obtained.");
}
return Content(GetFormattedJson((ProcessBaseInfo)data, pretty), "application/json");
}
catch (Exception ex)
{
_logger.LogError(ex, $"An error occurred while receiving memory regions for PID {pid}.");
return StatusCode(StatusCodes.Status500InternalServerError, $"An internal server error occurred while receiving memory regions for PID {pid}.");
}
}
[HttpGet("{pid}/memory_regions")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IEnumerable<MemoryRegionInfo>))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
async public Task<IActionResult> GetProcessMemoryPagesById(int pid,
[FromQuery] bool pretty = false,
[FromQuery] string sortBy = "",
[FromQuery] bool desc = false,
[FromQuery] int limit = 0,
[FromQuery] int offset = 0
)
{
try
{
var data = (await _monitor.GetProcessDetails(pid, ScanTarget.MemoryRegions))?.MemoryRegions;
if (data == null)
{
return NotFound($"The process with the PID {pid} was not found or its details could not be obtained.");
}
if (!String.IsNullOrEmpty(sortBy))
{
sortBy = sortBy.ToLowerInvariant();
switch (sortBy)
{
case "state": data = Sort(data, p => p.MemoryState, desc); break;
case "protection": data = Sort(data, p => p.MemoryPageProtection, desc); break;
case "type": data = Sort(data, p => p.MemoryType, desc); break;
case "memaddress": data = Sort(data, p => p.MemoryAddress, desc); break;
case "memsize": data = Sort(data, p => p.MemorySize, desc); break;
default: return StatusCode(StatusCodes.Status400BadRequest, $"Unexpected search filter {sortBy}.");
}
}
return Content(GetFormattedJson(Paginate(data, limit, offset), pretty), "application/json");
}
catch (Exception ex)
{
_logger.LogError(ex, $"An error occurred while receiving memory regions for PID {pid}.");
return StatusCode(StatusCodes.Status500InternalServerError, $"An internal server error occurred while receiving memory regions for PID {pid}.");
}
}
[HttpGet("{pid}/modules")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IEnumerable<MemoryRegionInfo>))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
async public Task<IActionResult> GetProcessModulesById(int pid,
[FromQuery] bool pretty = false,
[FromQuery] string sortBy = "",
[FromQuery] bool desc = false,
[FromQuery] int limit = 0,
[FromQuery] int offset = 0
)
{
try
{
var data = (await _monitor.GetProcessDetails(pid, ScanTarget.Modules))?.Modules;
if (data == null)
{
return NotFound($"The process with the PID {pid} was not found or its details could not be obtained.");
}
if (!String.IsNullOrEmpty(sortBy))
{
sortBy = sortBy.ToLowerInvariant();
switch (sortBy)
{
case "name": data = Sort(data, p => p.ModuleName, desc); break;
case "filename": data = Sort(data, p => p.FileName, desc); break;
case "memaddress": data = Sort(data, p => p.MemoryAddress, desc); break;
case "entryaddress": data = Sort(data, p => p.EntrypointRawAddress, desc); break;
case "memsize": data = Sort(data, p => p.MemorySize, desc); break;
default: return StatusCode(StatusCodes.Status400BadRequest, $"Unexpected search filter {sortBy}.");
}
}
return Content(GetFormattedJson(Paginate(data, limit, offset), pretty), "application/json");
}
catch (Exception ex)
{
_logger.LogError(ex, $"An error occurred while receiving modules for PID {pid}.");
return StatusCode(StatusCodes.Status500InternalServerError, $"An internal server error occurred while receiving modules for PID {pid}.");
}
}
[HttpGet("{pid}/threads")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IEnumerable<MemoryRegionInfo>))]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
async public Task<IActionResult> GetProcessThreadsById(int pid,
[FromQuery] bool pretty = false,
[FromQuery] string sortBy = "",
[FromQuery] bool desc = false,
[FromQuery] int limit = 0,
[FromQuery] int offset = 0
)
{
try
{
var data = (await _monitor.GetProcessDetails(pid, ScanTarget.Threads))?.Threads;
if (data == null)
{
return NotFound($"The process with the PID {pid} was not found or its details could not be obtained.");
}
if (!String.IsNullOrEmpty(sortBy))
{
sortBy = sortBy.ToLowerInvariant();
switch (sortBy)
{
case "id": data = Sort(data, p => p.ID, desc); break;
case "priority": data = Sort(data, p => p.CurrentPriority, desc); break;
case "basepriority": data = Sort(data, p => p.BasePriority, desc); break;
case "cpuusage": data = Sort(data, p => p.CpuUsage, desc); break;
default: return StatusCode(StatusCodes.Status400BadRequest, $"Unexpected search filter {sortBy}.");
}
}
return Content(GetFormattedJson(Paginate(data, limit, offset), pretty), "application/json");
}
catch (Exception ex)
{
_logger.LogError(ex, $"An error occurred while receiving threads for PID {pid}.");
return StatusCode(StatusCodes.Status500InternalServerError, $"An internal server error occurred while receiving threads for PID {pid}.");
}
}
private static IEnumerable<T1> Sort<T1, T2>(IEnumerable<T1> data, Func<T1, T2> selector, bool desc)
{
return desc ? data.OrderByDescending(selector) : data.OrderBy(selector);
}
private IEnumerable<T> Paginate<T>(IEnumerable<T> data, int limit, int offset)
{
if (offset > 0) data = data.Skip(offset);
if (limit > 0) data = data.Take(limit);
return data;
}
}
}