Comments
This commit is contained in:
@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.RateLimiting;
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Models.Settings;
|
using Models.Settings;
|
||||||
using Models.Requests;
|
using Models.Requests;
|
||||||
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
|
|
||||||
namespace Api.Controllers
|
namespace Api.Controllers
|
||||||
{
|
{
|
||||||
@@ -42,6 +43,13 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[EnableRateLimiting("contact")]
|
[EnableRateLimiting("contact")]
|
||||||
|
[SwaggerOperation(Summary = "Send contact message", Description = "Validates captcha and sends a contact message using the configured email sender.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Contact message sent")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid request or captcha verification failed")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status500InternalServerError, "Contact message could not be sent due to server error")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||||
public async Task<IActionResult> Send([FromBody] ContactRequest req, CancellationToken ct)
|
public async Task<IActionResult> Send([FromBody] ContactRequest req, CancellationToken ct)
|
||||||
{
|
{
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
@@ -76,6 +84,13 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
[HttpPost("subscribe")]
|
[HttpPost("subscribe")]
|
||||||
[EnableRateLimiting("contact")]
|
[EnableRateLimiting("contact")]
|
||||||
|
[SwaggerOperation(Summary = "Subscribe email", Description = "Validates captcha and subscribes an email address to the mailing list.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Subscription succeeded")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid request or captcha verification failed")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status500InternalServerError, "Subscription failed due to server error")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||||
public async Task<IActionResult> Subscribe([FromBody] SubscribeRequest req, CancellationToken ct)
|
public async Task<IActionResult> Subscribe([FromBody] SubscribeRequest req, CancellationToken ct)
|
||||||
{
|
{
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.AspNetCore.StaticFiles;
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
|
|
||||||
namespace Api.Controllers
|
namespace Api.Controllers
|
||||||
{
|
{
|
||||||
@@ -47,10 +48,19 @@ namespace Api.Controllers
|
|||||||
/// <response code="404">File not found</response>
|
/// <response code="404">File not found</response>
|
||||||
/// <response code="416">Requested range not satisfiable</response>
|
/// <response code="416">Requested range not satisfiable</response>
|
||||||
[HttpGet("{fileName?}")]
|
[HttpGet("{fileName?}")]
|
||||||
|
[SwaggerOperation(Summary = "Download file", Description = "Downloads a file with support for full and ranged (resumable) transfers.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Full file content returned")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status206PartialContent, "Partial file content returned for a range request")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status400BadRequest, "No file name provided and no default configured")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status404NotFound, "Requested file was not found")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status416RangeNotSatisfiable, "Requested byte range is invalid")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status500InternalServerError, "Unexpected server error while downloading")]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status206PartialContent)]
|
[ProducesResponseType(StatusCodes.Status206PartialContent)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ProducesResponseType(StatusCodes.Status416RangeNotSatisfiable)]
|
[ProducesResponseType(StatusCodes.Status416RangeNotSatisfiable)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||||
public async Task<IActionResult> DownloadFile(string? fileName = null)
|
public async Task<IActionResult> DownloadFile(string? fileName = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Models.Settings;
|
|||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
|
|
||||||
namespace Api.Controllers
|
namespace Api.Controllers
|
||||||
{
|
{
|
||||||
@@ -29,6 +30,9 @@ namespace Api.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>200 OK with the Tag Manager ID as a string.</returns>
|
/// <returns>200 OK with the Tag Manager ID as a string.</returns>
|
||||||
[HttpGet("tagmanager")]
|
[HttpGet("tagmanager")]
|
||||||
|
[SwaggerOperation(Summary = "Get Google Tag Manager ID", Description = "Returns the Google Tag Manager ID configured for frontend analytics.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Tag Manager ID returned")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public async Task<IActionResult> GetTagManagerId(CancellationToken ct)
|
public async Task<IActionResult> GetTagManagerId(CancellationToken ct)
|
||||||
{
|
{
|
||||||
return Ok(_googleSettings.TagManagerId);
|
return Ok(_googleSettings.TagManagerId);
|
||||||
@@ -41,6 +45,9 @@ namespace Api.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>200 OK with the maps API key as a string.</returns>
|
/// <returns>200 OK with the maps API key as a string.</returns>
|
||||||
[HttpGet("maps")]
|
[HttpGet("maps")]
|
||||||
|
[SwaggerOperation(Summary = "Get Google Maps key", Description = "Returns the Google Maps API key configured for frontend map features.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Maps API key returned")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public async Task<IActionResult> GetMapKey(CancellationToken ct)
|
public async Task<IActionResult> GetMapKey(CancellationToken ct)
|
||||||
{
|
{
|
||||||
return Ok(_googleSettings.MapKey);
|
return Ok(_googleSettings.MapKey);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
|
|
||||||
namespace Api.Controllers
|
namespace Api.Controllers
|
||||||
{
|
{
|
||||||
@@ -22,6 +23,9 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
// GET api/health/live
|
// GET api/health/live
|
||||||
[HttpGet("live")]
|
[HttpGet("live")]
|
||||||
|
[SwaggerOperation(Summary = "Liveness probe", Description = "Returns whether the API process is alive.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Service is alive")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public IActionResult Live() => Ok(new { status = "alive" });
|
public IActionResult Live() => Ok(new { status = "alive" });
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -33,6 +37,9 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
// GET api/health
|
// GET api/health
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
[SwaggerOperation(Summary = "Health check", Description = "Returns overall health status and current UTC time.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Health check succeeded")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public IActionResult Health() => Ok(new { status = "ok", time = DateTimeOffset.UtcNow });
|
public IActionResult Health() => Ok(new { status = "ok", time = DateTimeOffset.UtcNow });
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -43,6 +50,9 @@ namespace Api.Controllers
|
|||||||
/// <returns>200 OK with the same JSON payload provided in the request body.</returns>
|
/// <returns>200 OK with the same JSON payload provided in the request body.</returns>
|
||||||
// POST api/health/echo
|
// POST api/health/echo
|
||||||
[HttpPost("echo")]
|
[HttpPost("echo")]
|
||||||
|
[SwaggerOperation(Summary = "Echo payload", Description = "Returns the same JSON payload received in the request body.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Payload echoed successfully")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public IActionResult Echo(object payload) => Ok(payload);
|
public IActionResult Echo(object payload) => Ok(payload);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -55,6 +65,11 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
// GET api/health/ready
|
// GET api/health/ready
|
||||||
[HttpGet("ready")]
|
[HttpGet("ready")]
|
||||||
|
[SwaggerOperation(Summary = "Readiness probe", Description = "Returns whether the service is ready to accept traffic.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Service is ready")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status503ServiceUnavailable, "Service is not ready")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status503ServiceUnavailable)]
|
||||||
public IActionResult Ready()
|
public IActionResult Ready()
|
||||||
{
|
{
|
||||||
var ready = true;
|
var ready = true;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Api.Services.Contracts;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using CvMatcher.Models.Responses;
|
using CvMatcher.Models.Responses;
|
||||||
using Shared.Models.Requests;
|
using Shared.Models.Requests;
|
||||||
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
|
|
||||||
namespace Api.Controllers;
|
namespace Api.Controllers;
|
||||||
|
|
||||||
@@ -21,6 +22,11 @@ public sealed class CvController : ControllerBase
|
|||||||
|
|
||||||
[HttpPost("upload")]
|
[HttpPost("upload")]
|
||||||
[RequestSizeLimit(10 * 1024 * 1024)]
|
[RequestSizeLimit(10 * 1024 * 1024)]
|
||||||
|
[SwaggerOperation(Summary = "Upload CV document", Description = "Uploads a CV PDF and indexes it for matching.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "CV uploaded and indexed successfully")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid upload request")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
public async Task<ActionResult<CvUploadResponse>> Upload([FromForm] UploadFileRequest request, CancellationToken ct)
|
public async Task<ActionResult<CvUploadResponse>> Upload([FromForm] UploadFileRequest request, CancellationToken ct)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -39,6 +45,11 @@ public sealed class CvController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("find-jobs")]
|
[HttpPost("find-jobs")]
|
||||||
|
[SwaggerOperation(Summary = "Find matching jobs", Description = "Finds top matching jobs for a previously uploaded CV document.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Matching jobs returned")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid find jobs request")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
public async Task<ActionResult<FindJobsResponse>> FindJobs([FromBody] FindJobsRequest request, CancellationToken ct)
|
public async Task<ActionResult<FindJobsResponse>> FindJobs([FromBody] FindJobsRequest request, CancellationToken ct)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -56,6 +67,11 @@ public sealed class CvController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("match-job")]
|
[HttpPost("match-job")]
|
||||||
|
[SwaggerOperation(Summary = "Match CV to one job", Description = "Computes detailed match analysis between a CV and a single job description or URL.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Job match computed successfully")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid match job request")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
public async Task<ActionResult<JobMatchResponse>> MatchJob([FromBody] MatchJobRequest request, CancellationToken ct)
|
public async Task<ActionResult<JobMatchResponse>> MatchJob([FromBody] MatchJobRequest request, CancellationToken ct)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
|
|
||||||
namespace Api.Controllers
|
namespace Api.Controllers
|
||||||
{
|
{
|
||||||
@@ -19,6 +20,9 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
// GET api/health/live
|
// GET api/health/live
|
||||||
[HttpGet("live")]
|
[HttpGet("live")]
|
||||||
|
[SwaggerOperation(Summary = "Liveness probe", Description = "Returns whether the API process is alive.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Service is alive")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public IActionResult Live() => Ok(new { status = "alive" });
|
public IActionResult Live() => Ok(new { status = "alive" });
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -30,6 +34,9 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
// GET api/health
|
// GET api/health
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
[SwaggerOperation(Summary = "Health check", Description = "Returns overall health status and current UTC time.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Health check succeeded")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public IActionResult Health() => Ok(new { status = "ok", time = DateTimeOffset.UtcNow });
|
public IActionResult Health() => Ok(new { status = "ok", time = DateTimeOffset.UtcNow });
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -40,6 +47,9 @@ namespace Api.Controllers
|
|||||||
/// <returns>200 OK with the same JSON payload provided in the request body.</returns>
|
/// <returns>200 OK with the same JSON payload provided in the request body.</returns>
|
||||||
// POST api/health/echo
|
// POST api/health/echo
|
||||||
[HttpPost("echo")]
|
[HttpPost("echo")]
|
||||||
|
[SwaggerOperation(Summary = "Echo payload", Description = "Returns the same JSON payload received in the request body.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Payload echoed successfully")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public IActionResult Echo(object payload) => Ok(payload);
|
public IActionResult Echo(object payload) => Ok(payload);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -52,6 +62,11 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
// GET api/health/ready
|
// GET api/health/ready
|
||||||
[HttpGet("ready")]
|
[HttpGet("ready")]
|
||||||
|
[SwaggerOperation(Summary = "Readiness probe", Description = "Returns whether the service is ready to accept traffic.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Service is ready")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status503ServiceUnavailable, "Service is not ready")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status503ServiceUnavailable)]
|
||||||
public IActionResult Ready()
|
public IActionResult Ready()
|
||||||
{
|
{
|
||||||
var ready = true;
|
var ready = true;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
|
|
||||||
namespace Api.Controllers
|
namespace Api.Controllers
|
||||||
{
|
{
|
||||||
@@ -19,6 +20,9 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
// GET api/health/live
|
// GET api/health/live
|
||||||
[HttpGet("live")]
|
[HttpGet("live")]
|
||||||
|
[SwaggerOperation(Summary = "Liveness probe", Description = "Returns whether the API process is alive.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Service is alive")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public IActionResult Live() => Ok(new { status = "alive" });
|
public IActionResult Live() => Ok(new { status = "alive" });
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -30,6 +34,9 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
// GET api/health
|
// GET api/health
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
[SwaggerOperation(Summary = "Health check", Description = "Returns overall health status and current UTC time.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Health check succeeded")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public IActionResult Health() => Ok(new { status = "ok", time = DateTimeOffset.UtcNow });
|
public IActionResult Health() => Ok(new { status = "ok", time = DateTimeOffset.UtcNow });
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -40,6 +47,9 @@ namespace Api.Controllers
|
|||||||
/// <returns>200 OK with the same JSON payload provided in the request body.</returns>
|
/// <returns>200 OK with the same JSON payload provided in the request body.</returns>
|
||||||
// POST api/health/echo
|
// POST api/health/echo
|
||||||
[HttpPost("echo")]
|
[HttpPost("echo")]
|
||||||
|
[SwaggerOperation(Summary = "Echo payload", Description = "Returns the same JSON payload received in the request body.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Payload echoed successfully")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
public IActionResult Echo(object payload) => Ok(payload);
|
public IActionResult Echo(object payload) => Ok(payload);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -52,6 +62,11 @@ namespace Api.Controllers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
// GET api/health/ready
|
// GET api/health/ready
|
||||||
[HttpGet("ready")]
|
[HttpGet("ready")]
|
||||||
|
[SwaggerOperation(Summary = "Readiness probe", Description = "Returns whether the service is ready to accept traffic.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Service is ready")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status503ServiceUnavailable, "Service is not ready")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status503ServiceUnavailable)]
|
||||||
public IActionResult Ready()
|
public IActionResult Ready()
|
||||||
{
|
{
|
||||||
var ready = true;
|
var ready = true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Api.Services.Contracts;
|
using Api.Services.Contracts;
|
||||||
using Rag.Models.Requests;
|
using Rag.Models.Requests;
|
||||||
using Rag.Models.Responses;
|
using Rag.Models.Responses;
|
||||||
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
|
|
||||||
namespace Api.Controllers;
|
namespace Api.Controllers;
|
||||||
|
|
||||||
@@ -20,6 +21,11 @@ public sealed class RagController : ControllerBase
|
|||||||
|
|
||||||
[HttpPost("documents")]
|
[HttpPost("documents")]
|
||||||
[RequestSizeLimit(10 * 1024 * 1024)]
|
[RequestSizeLimit(10 * 1024 * 1024)]
|
||||||
|
[SwaggerOperation(Summary = "Index document (multipart)", Description = "Indexes a PDF file or raw text document using multipart/form-data payload.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Document indexed successfully")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid indexing request")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
public async Task<ActionResult<IndexDocumentResponse>> IndexDocument(
|
public async Task<ActionResult<IndexDocumentResponse>> IndexDocument(
|
||||||
[FromForm] IndexDocumentUploadRequest request,
|
[FromForm] IndexDocumentUploadRequest request,
|
||||||
CancellationToken ct)
|
CancellationToken ct)
|
||||||
@@ -56,6 +62,11 @@ public sealed class RagController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("documents/json")]
|
[HttpPost("documents/json")]
|
||||||
|
[SwaggerOperation(Summary = "Index document (JSON)", Description = "Indexes a text document sent as JSON.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "JSON document indexed successfully")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid JSON indexing request")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
public async Task<ActionResult<IndexDocumentResponse>> IndexJsonDocument([FromBody] IndexDocumentRequest request, CancellationToken ct)
|
public async Task<ActionResult<IndexDocumentResponse>> IndexJsonDocument([FromBody] IndexDocumentRequest request, CancellationToken ct)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -75,6 +86,11 @@ public sealed class RagController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("search")]
|
[HttpPost("search")]
|
||||||
|
[SwaggerOperation(Summary = "Semantic search", Description = "Performs semantic retrieval over indexed documents.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Search results returned")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid search request")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
public async Task<ActionResult<SearchResponse>> Search([FromBody] SearchRequest request, CancellationToken ct)
|
public async Task<ActionResult<SearchResponse>> Search([FromBody] SearchRequest request, CancellationToken ct)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -93,6 +109,11 @@ public sealed class RagController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("documents/{id}")]
|
[HttpGet("documents/{id}")]
|
||||||
|
[SwaggerOperation(Summary = "Get document details", Description = "Returns indexed document details for the provided document id.")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status200OK, "Document details returned")]
|
||||||
|
[SwaggerResponse(StatusCodes.Status404NotFound, "Document was not found")]
|
||||||
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public async Task<ActionResult<RagDocumentDetailsResponse>> GetDocument(string id, CancellationToken ct)
|
public async Task<ActionResult<RagDocumentDetailsResponse>> GetDocument(string id, CancellationToken ct)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Get document request received. DocumentId={DocumentId}", id);
|
_logger.LogInformation("Get document request received. DocumentId={DocumentId}", id);
|
||||||
|
|||||||
Reference in New Issue
Block a user