use nswag to publish swagger

This commit is contained in:
SikongJueluo 2025-04-17 16:26:12 +08:00
parent d25f9882fc
commit acd6a68507
No known key found for this signature in database
6 changed files with 214 additions and 220 deletions

View File

@ -1,5 +1,3 @@
using System.Reflection;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
using NLog.Web; using NLog.Web;
@ -15,6 +13,7 @@ try
{ {
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
// Services Settings
// Add services to the container. // Add services to the container.
builder.Services.AddControllersWithViews(); builder.Services.AddControllersWithViews();
@ -32,27 +31,32 @@ try
}); });
// Add Swagger // Add Swagger
builder.Services.AddSwaggerGen(options => builder.Services.AddControllers();
builder.Services.AddOpenApiDocument(options =>
{ {
options.SwaggerDoc("v1", new OpenApiInfo options.PostProcess = document =>
{ {
document.Info = new NSwag.OpenApiInfo
{
Version = "v1",
Title = "FPGA Web Lab API", Title = "FPGA Web Lab API",
Description = "Use FPGA in the cloud", Description = "Use FPGA in the cloud",
Version = "v1" // TermsOfService = "https://example.com/terms",
}); // Contact = new NSwag.OpenApiContact
// Generate Doc and Example // {
options.IncludeXmlComments(Assembly.GetExecutingAssembly()); // Name = "Example Contact",
// var executingAssembly = Assembly.GetExecutingAssembly(); // Url = "https://example.com/contact"
// var xmlFilename = $"{executingAssembly.GetName().Name}.xml"; // },
// options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); // License = new NSwag.OpenApiLicense
// var referencedProjectsXmlDocPaths = // {
// executingAssembly.GetReferencedAssemblies() // Name = "Example License",
// .Where(assembly => assembly.Name != null && assembly.Name.StartsWith("server", StringComparison.InvariantCultureIgnoreCase)) // Url = "https://example.com/license"
// .Select(assembly => Path.Combine(AppContext.BaseDirectory, $"{assembly.Name}.xml")) // }
// .Where(path => File.Exists(path)); };
// foreach (var xmlDocPath in referencedProjectsXmlDocPaths) options.IncludeXmlComments(xmlDocPath); };
}); });
// Application Settings
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
app.UseExceptionHandler("/Home/Error"); app.UseExceptionHandler("/Home/Error");
@ -61,20 +65,12 @@ try
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseStaticFiles(); app.UseStaticFiles();
app.UseRouting(); app.UseRouting();
app.UseAuthorization(); app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
// if (app.Environment.IsDevelopment()) // if (app.Environment.IsDevelopment())
// { // {
app.UseSwagger(); app.UseOpenApi();
app.UseSwaggerUI(c => app.UseSwaggerUi();
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "FPAG WebLab API V1");
});
// } // }
// Setup Program // Setup Program
@ -83,15 +79,7 @@ try
// Router // Router
// API Get // API Get
app.MapGet("/", () => Results.Redirect("/swagger")); app.MapGet("/", () => Results.Redirect("/swagger"));
app.MapGet("/api/GetRecvDataArray", Router.API.GetRecvDataArray); app.MapControllers();
// API Post
app.MapPost("/api/SendString", Router.API.SendString);
app.MapPost("/api/SendBytes", Router.API.SendBytes);
app.MapPost("/api/SendAddrPackage", Router.API.SendAddrPackage);
app.MapPost("/api/SendDataPackage", Router.API.SendDataPackage);
// API Jtag
app.MapPost("/api/jtag/RunCommand", Router.API.Jtag.RunCommand);
app.MapGet("/api/jtag/GetIDCode", Router.API.Jtag.GetDeviceIDCode);
app.Run("http://localhost:5000"); app.Run("http://localhost:5000");
} }

View File

@ -18,7 +18,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.4.0" /> <PackageReference Include="NLog" Version="5.4.0" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.4.0" /> <PackageReference Include="NLog.Web.AspNetCore" Version="5.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" /> <PackageReference Include="NSwag.AspNetCore" Version="14.3.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

186
server/src/Controllers.cs Normal file
View File

@ -0,0 +1,186 @@
using System.Net;
using Common;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using WebProtocol;
namespace server.Controllers;
/// <summary>
/// UDP API
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class UDPController : ControllerBase
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private const string LOCALHOST = "127.0.0.1";
/// <summary>
/// 页面
/// </summary>
[HttpGet]
public string Index()
{
return "This is UDP Controller";
}
/// <summary>
/// 发送字符串
/// </summary>
/// <param name="address">IPV4 或者 IPV6 地址</param>
/// <param name="port">设备端口号</param>
/// <param name="text">发送的文本</param>
/// <response code="200">发送成功</response>
/// <response code="500">发送失败</response>
[HttpPost("SendString")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async ValueTask<IResult> SendString(string address = LOCALHOST, int port = 1234, string text = "Hello Server!")
{
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendStringAsync(endPoint, [text]);
if (ret) { return TypedResults.Ok(); }
else { return TypedResults.InternalServerError(); }
}
/// <summary>
/// 发送二进制数据
/// </summary>
/// <param name="address" example="127.0.0.1">IPV4 或者 IPV6 地址</param>
/// <param name="port" example="1234">设备端口号</param>
/// <param name="bytes" example="FFFFAAAA">16进制文本</param>
[HttpPost("SendBytes")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async ValueTask<IResult> SendBytes(string address, int port, string bytes)
{
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendBytesAsync(endPoint, Number.StringToBytes(bytes));
if (ret) { return TypedResults.Ok(); }
else { return TypedResults.InternalServerError(); }
}
/// <summary>
/// 发送地址包
/// </summary>
/// <param name="address">IP地址</param>
/// <param name="port">UDP 端口号</param>
/// <param name="opts">地址包选项</param>
[HttpPost("SendAddrPackage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async ValueTask<IResult> SendAddrPackage(
string address,
int port,
[FromBody] SendAddrPackOptions opts)
{
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts));
if (ret) { return TypedResults.Ok(); }
else { return TypedResults.InternalServerError(); }
}
/// <summary>
/// 发送数据包
/// </summary>
/// <param name="address">IP地址</param>
/// <param name="port">UDP 端口号</param>
/// <param name="data">16进制数据</param>
[HttpPost("SendDataPackage")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async ValueTask<IResult> SendDataPackage(string address, int port, string data)
{
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendDataPackAsync(endPoint,
new WebProtocol.SendDataPackage(Number.StringToBytes(data)));
if (ret) { return TypedResults.Ok(); }
else { return TypedResults.InternalServerError(); }
}
/// <summary>
/// 获取指定IP地址接受的数据列表
/// </summary>
/// <param name="address">IP地址</param>
[HttpGet("GetRecvDataArray")]
[ProducesResponseType(typeof(List<UDPData>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async ValueTask<IResult> GetRecvDataArray(string address)
{
var ret = await MsgBus.UDPServer.GetDataArrayAsync(address);
if (ret.HasValue)
{
var dataJson = JsonConvert.SerializeObject(ret.Value);
logger.Debug($"Get Receive Successfully: {dataJson}");
return TypedResults.Ok(ret.Value);
}
else
{
logger.Debug("Get Receive Failed");
return TypedResults.InternalServerError();
}
}
}
/// <summary>
/// Jtag API
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class JtagController : ControllerBase
{
/// <summary>
/// 页面
/// </summary>
[HttpGet]
public string Index()
{
return "This is Jtag Controller";
}
/// <summary>
/// 执行一个Jtag命令
/// </summary>
/// <param name="address"> 设备地址 </param>
/// <param name="port"> 设备端口 </param>
/// <param name="hexDevAddr"> 16进制设备目的地址(Jtag) </param>
/// <param name="hexCmd"> 16进制命令 </param>
[HttpPost("RunCommand")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async ValueTask<IResult> RunCommand(string address, int port, string hexDevAddr, string hexCmd)
{
var jtagCtrl = new JtagClient.Jtag(address, port);
var ret = await jtagCtrl.RunCommand(Convert.ToUInt32(hexDevAddr, 16), Convert.ToUInt32(hexCmd, 16));
if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); }
else { return TypedResults.InternalServerError(ret.Error); }
}
/// <summary>
/// 获取Jtag ID Code
/// </summary>
/// <param name="address"> 设备地址 </param>
/// <param name="port"> 设备端口 </param>
[HttpGet("GetDeviceIDCode")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async ValueTask<IResult> GetDeviceIDCode(string address, int port)
{
var jtagCtrl = new JtagClient.Jtag(address, port);
var ret = await jtagCtrl.ReadIDCode();
if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); }
else { return TypedResults.InternalServerError(ret.Error); }
}
}

View File

@ -3,7 +3,7 @@ using Common;
using DotNext; using DotNext;
using WebProtocol; using WebProtocol;
namespace JtagController; namespace JtagClient;
/// <summary> /// <summary>
/// Global Constant Jtag Address /// Global Constant Jtag Address

View File

@ -1,179 +0,0 @@
using System.Net;
using Common;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using WebProtocol;
namespace Router
{
/// <summary>
/// Custom Web Http Response
/// </summary>
public class Response
{
/// <summary>
/// 是否成功执行
/// </summary>
public bool IsSuccess { get; set; }
/// <summary>
/// 数据
/// </summary>
public object? Data { get; set; }
/// <summary>
/// 转换为Json格式的字符串
/// </summary>
/// <returns>Json字符串</returns>
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
/// <summary>
/// Web API
/// </summary>
class API
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private const string LOCALHOST = "127.0.0.1";
/// <summary>
/// 发送字符串
/// </summary>
/// <param name="address" example="127.0.0.1">IPV4 或者 IPV6 地址</param>
/// <param name="port" example="1234">设备端口号</param>
/// <param name="text" example="Hello Server!">Text for send</param>
[HttpPost("{address}/{port}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public static async ValueTask<IResult> SendString(string address, int port, string text)
{
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendStringAsync(endPoint, [text]);
if (ret) { return TypedResults.Ok(); }
else { return TypedResults.InternalServerError(); }
}
/// <summary>
/// 发送二进制数据
/// </summary>
/// <param name="address" example="127.0.0.1">IPV4 或者 IPV6 地址</param>
/// <param name="port" example="1234">设备端口号</param>
/// <param name="bytes" example="FFFFAAAA">16进制文本</param>
[HttpPost("{address}/{port}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public static async ValueTask<IResult> SendBytes(string address, int port, string bytes)
{
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendBytesAsync(endPoint, Number.StringToBytes(bytes));
if (ret) { return TypedResults.Ok(); }
else { return TypedResults.InternalServerError(); }
}
/// <summary>
/// 发送地址包
/// </summary>
/// <param name="address" example="127.0.0.1">IP地址</param>
/// <param name="port" example="1234">UDP 端口号</param>
/// <param name="opts">地址包选项</param>
[HttpPost("{address}/{port}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public static async ValueTask<IResult> SendAddrPackage(
string address,
int port,
[FromBody] SendAddrPackOptions opts)
{
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts));
if (ret) { return TypedResults.Ok(); }
else { return TypedResults.InternalServerError(); }
}
[HttpPost("{address}/{port}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public static async ValueTask<IResult> SendDataPackage(string address, int port, string data)
{
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendDataPackAsync(endPoint,
new WebProtocol.SendDataPackage(Number.StringToBytes(data)));
if (ret) { return TypedResults.Ok(); }
else { return TypedResults.InternalServerError(); }
}
[HttpGet("{address}")]
[ProducesResponseType(typeof(List<UDPData>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public static async ValueTask<IResult> GetRecvDataArray(string address)
{
var ret = await MsgBus.UDPServer.GetDataArrayAsync(address);
if (ret.HasValue)
{
var dataJson = JsonConvert.SerializeObject(ret.Value);
logger.Debug($"Get Receive Successfully: {dataJson}");
return TypedResults.Ok(ret.Value);
}
else
{
logger.Debug("Get Receive Failed");
return TypedResults.InternalServerError();
}
}
public class Jtag
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
/// <summary>
/// 执行一个Jtag命令
/// </summary>
/// <param name="address"> 设备地址 </param>
/// <param name="port"> 设备端口 </param>
/// <param name="hexDevAddr"> 16进制设备目的地址(Jtag) </param>
/// <param name="hexCmd"> 16进制命令 </param>
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public static async ValueTask<IResult> RunCommand(string address, int port, string hexDevAddr, string hexCmd)
{
var jtagCtrl = new JtagController.Jtag(address, port);
var ret = await jtagCtrl.RunCommand(Convert.ToUInt32(hexDevAddr, 16), Convert.ToUInt32(hexCmd, 16));
if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); }
else { return TypedResults.InternalServerError(ret.Error); }
}
/// <summary>
/// 获取Jtag ID Code
/// </summary>
/// <param name="address"> 设备地址 </param>
/// <param name="port"> 设备端口 </param>
[HttpGet]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public static async ValueTask<IResult> GetDeviceIDCode(string address, int port)
{
var jtagCtrl = new JtagController.Jtag(address, port);
var ret = await jtagCtrl.ReadIDCode();
if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); }
else { return TypedResults.InternalServerError(ret.Error); }
}
}
}
}

View File

@ -2,7 +2,6 @@ using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks;
using DotNext; using DotNext;
using DotNext.Threading; using DotNext.Threading;
using Newtonsoft.Json; using Newtonsoft.Json;