Files
adas-core/adas-core/Controllers/ProxyDeviceController.cs
T
2026-06-26 10:29:23 +02:00

94 lines
4.9 KiB
C#

using System.Net;
using adas_core.Authentication.Attributes;
using adas_core.Domain.Enums;
using adas_core.module.ProxyDevices.Services;
using Microsoft.AspNetCore.Mvc;
namespace adas_core.Controllers;
[Route("proxy-devices")]
[ApiController]
public class ProxyDeviceController(IProxyDeviceService proxyDeviceService) : ControllerBase
{
/// <summary>
/// Retrieves a media stream for the specified device by delegating the request to the proxy device service.
/// When the proxy call is not successful, the upstream status code is returned as-is; otherwise the response
/// stream is forwarded with the original content type, falling back to "multipart/x-mixed-replace" when no
/// content type is provided, and the response content length is set when known.
/// </summary>
/// <param name="deviceId">The unique identifier of the device whose stream should be retrieved.</param>
/// <returns>A <see cref="FileStreamResult"/> containing the proxied device stream, or a <see cref="StatusCodeResult"/> reflecting the upstream HTTP status when the proxy call fails.</returns>
[HttpGet("{deviceId}")]
[AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
public async Task<IActionResult> GetStreamById(string deviceId)
{
var response = await proxyDeviceService.Process(deviceId);
if (!response.IsSuccessStatusCode) return new StatusCodeResult((int)response.StatusCode);
var stream = await response.Content.ReadAsStreamAsync();
if (response.Content.Headers.ContentLength > 0) Response.ContentLength = response.Content.Headers.ContentLength;
return new FileStreamResult(stream,
response.Content.Headers.ContentType?.ToString() ?? "multipart/x-mixed-replace"); // Set MIME type as needed
}
/// <summary>
/// Retrieves the content associated with the specified device by proxying the request through the device service.
/// Forwards the upstream content length and content type headers to the response when available, and returns the resulting content as a stream.
/// </summary>
/// <param name="deviceId">The unique identifier of the device whose content is being requested.</param>
/// <returns>An <see cref="IActionResult"/> containing the proxied content stream for the specified device.</returns>
[HttpGet("{deviceId}/content")]
[AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
public async Task<IActionResult> GetContentById(string deviceId)
{
var response = await proxyDeviceService.Process(deviceId);
var content = await response.Content.ReadAsStreamAsync();
if (response.Content.Headers.ContentLength > 0) Response.ContentLength = response.Content.Headers.ContentLength;
if (response.Content.Headers.ContentType != null)
Response.ContentType = response.Content.Headers.ContentType?.ToString() ?? "";
return Ok(content);
}
/// <summary>
/// Streams MJPEG video from the specified device by proxying the request through an external service and writing the response body to the client.
/// Forwards the upstream status code when the proxy call is not successful, defaults the response content type to <c>multipart/x-mixed-replace</c> when none is provided, and returns 404 (or the original status code) if the upstream request fails.
/// </summary>
/// <param name="deviceId">The identifier of the device whose MJPEG stream should be retrieved and forwarded to the caller.</param>
[HttpGet("{deviceId}/mjpeg-stream")]
[AuthorizeRoles(PermissionEnum.RolesType.AuthSome)]
public async Task GetAsMpegStreamById(string deviceId)
{
try
{
using var cts = CancellationTokenSource.CreateLinkedTokenSource(HttpContext.RequestAborted);
//cts.CancelAfter(TimeSpan.FromMinutes(5));
var response = await proxyDeviceService.Stream(deviceId);
if (!response.IsSuccessStatusCode)
{
Response.StatusCode = (int)response.StatusCode;
return;
}
if (response.Content.Headers.ContentType != null)
Response.ContentType = response.Content.Headers.ContentType?.ToString() ??
"multipart/x-mixed-replace;boundary=my-boundary";
await using var stream = await response.Content.ReadAsStreamAsync(cts.Token);
// Buffer for reading the stream
var buffer = new byte[4096];
int bytesRead;
while (!cts.Token.IsCancellationRequested && (bytesRead = await stream.ReadAsync(buffer, cts.Token)) > 0)
{
await Response.Body.WriteAsync(buffer.AsMemory(0, bytesRead), cts.Token);
await Response.Body.FlushAsync(cts.Token);
}
}
catch (HttpRequestException e)
{
Response.StatusCode = (int)(e.StatusCode ?? HttpStatusCode.NotFound);
}
}
}