找回密码
 立即注册
首页 业界区 业界 使用Scalar.AspNetCore来管理你的OpenApi

使用Scalar.AspNetCore来管理你的OpenApi

揿纰潦 昨天 18:20
一直觉得很好的一个组件,网上介绍少得可怜,没办法,只有自己爬官网了,又是对照git又是看doc文档,总算是玩明白了,现在完全抛弃那个谁谁谁了。因人喜好各取所长吧
先来官方参考地址:
https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/openapi/include-metadata?view=aspnetcore-9.0&tabs=minimal-apis
这是scalar的.net 集成文档地址
https://guides.scalar.com/scalar/scalar-api-references/integrations/net-aspnet-core/integration
github地址
https://github.com/scalar/scalar
先放个图,诱惑一下,集成了很多主题,还可以自定主题(留给前端去玩吧)
1.png

 
一、简单使用
1.建立一个API项目,(最小,mvc都可)
2.引用包
 dotnet add package Scalar.AspNetCore (当前版本2.9.0)
 dotnet add package Microsoft.AspNetCore.OpenApi(当前版本10.0)3.添加引用
using Scalar.AspNetCore;
4.添加配置,在Program.cs中添加下面配置
  1. builder.Services.AddOpenApi();
  2. if (app.Environment.IsDevelopment())
  3. {
  4.     app.MapOpenApi();
  5.     app.MapScalarApiReference();
  6. }
复制代码
现在运行一下,看看,localhost:xxxx/scalar
是不是看到列出漂亮的界面了?
二、基本配置
1.自定义路由
不想使用/salar,可以换成自己的地址
  1. app.MapScalarApiReference("/api-docs");
  2. app.MapScalarApiReference("/docs");
复制代码
2.多文当或版本控制
  1. // Chain multiple documents
  2. app.MapScalarApiReference(options =>
  3. {
  4.     options.AddDocument("v1", "Production API", "api/v1/openapi.json")
  5.            .AddDocument("v2-beta", "Beta API", "api/v2-beta/openapi.json", isDefault: true)
  6.            .AddDocument("internal", "Internal API", "internal/openapi.json");
  7. });
复制代码
  1. isDefault: true是默认打开的页面<br>3.自定义文档的默认调试语言
复制代码
  1. app.MapScalarApiReference(options =>
  2. {
  3.     options.WithDefaultHttpClient(ScalarTarget.CSharp, ScalarClient.HttpClient);
  4. });
复制代码
2.png

它对应右边窗口的语言,基本上都支持,java,php,rust,py,swift
三、高级配置
之前的老版本使用的硬编码option加配置,2.9.0以后,在界面右上角菜单栏上出现了一个编辑配置功能
3.png

根据自己的喜好,调试编辑完配置文件后,可以复制到文件中单独保存,真是太贴心了
  1. {
  2.   "title": "Aquxa API Documentation",
  3.   "slug": "aquxa-api-documentation",
  4.   "hideClientButton": true,
  5.   "servers": [
  6.     {
  7.       "url": "http://localhost:5215",
  8.       "description": "Development server"
  9.     }
  10.   ],
  11.   "showSidebar": true,
  12.   "showToolbar": "localhost",//这里特别说明一下,编辑完后,不想出现这个菜单栏,就在这里可以关闭showToolbar: "never"
  13.   "operationTitleSource": "summary",
  14.   "theme": "solarized",//主题可以自己选,喜欢哪个选哪个
  15.   "_integration": "dotnet",
  16.   "persistAuth": false,
  17.   "telemetry": true,
  18.   "layout": "modern",
  19.   "isEditable": false,
  20.   "isLoading": false,
  21.   "hideModels": true,
  22.   "documentDownloadType": "both",
  23.   "hideTestRequestButton": false,
  24.   "hideSearch": false,
  25.   "showOperationId": false,
  26.   "hideDarkModeToggle": false,
  27.   "favicon": "favicon.svg",
  28.   "withDefaultFonts": true,
  29.   "defaultOpenAllTags": false,
  30.   "expandAllModelSections": true,
  31.   "expandAllResponses": true,
  32.   "orderSchemaPropertiesBy": "alpha",
  33.   "orderRequiredPropertiesFirst": true,
  34.   "url": "http://localhost:5215/openapi/v1.json"
  35. }
复制代码
  1. PS:这里特别说明一下,编辑完后,不想出现这个菜单栏,就在这里可以关闭showToolbar: "never"
  2. 得到这个文件,保存到wwwroot/js/scalar-config.js,注意,一定要保存到能访问的静态目录里,并在program.cs添加静态目录的配置
复制代码
  1. app.UseStaticFiles(). //这个要放在scalar配置的前面,不然访问不到
复制代码
添加配置文件加载
  1. .WithJavaScriptConfiguration("/js/scalar-config.js")     
复制代码
 
4.png

这里费了好大的劲,查官方,看代码,因为官方文档还是老文档,只是简单的概括了一下。最后整出来了
四、文档的编辑
使用最重要的还是API文档编辑,其实它完全用的标准的OpenApi,只要参考这个表就可以完全配置了
5.png
  1. [ApiController]
  2.     [Route("api/[controller]")]
  3.     [ApiExplorerSettings(GroupName = "v1")]
  4.     [Tags("Admin")] // 为整个控制器添加标签
  5.     public class AdminController : ControllerBase
  6.     {
  7.         [HttpPost("reload-cache")]
  8.         public IActionResult ReloadCache()
  9.         {
  10.             // 模拟重新加载缓存的操作
  11.             return Ok("Cache reloaded successfully");
  12.         }
  13.         
  14.         [HttpGet("stats")]
  15.         public IActionResult GetStats()
  16.         {
  17.             return Ok(new { Users = 100, Requests = 1000 });
  18.         }
  19.     }
复制代码
下面说一下常用的特性
1.API分组
  1.     [ApiExplorerSettings]
复制代码
这个比较熟悉,它可以分组,分版本,当你分好版本后[ApiExplorerSettings(GroupName = "v1")]/[ApiExplorerSettings(GroupName = "v2")],会在scalar中左上角可以选择,当然,你也可以把它做为组来用
6.png

如果有不想显示的API也可以用[ApiExplorerSettings(IgnoreApi = true)]来排除显示
  1. [HttpGet("/private")]
  2. [ApiExplorerSettings(IgnoreApi = true)]
  3. public IActionResult PrivateEndpoint() {
  4.     return Ok("This is a private endpoint");
  5. }
复制代码
2.API分类
  1. [Tags]
复制代码
分类的API,会归档在一起,方便查询,这样看起来没有那么乱了
  1. [Tags(["Admin", "OtherAPI"])]
  2. [HttpGet("attributes")]
  3. public IResult Attributes()
  4. {
  5.     return Results.Ok("Hello world!");
  6. }
复制代码
7.png

3.描述
  1. [EndpointSummary("OtherApi")]
  2. [EndpointDescription("这是一个公开接口,无需认证")]
  3. [HttpGet("attributes")]
  4. public IResult Attributes()
  5. {
  6.     return Results.Ok("Hello world!");
  7. }
复制代码
8.png

更多编辑文档就看这里吧
https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/openapi/include-metadata?view=aspnetcore-9.0&tabs=controllers
五、认证授权
这里就使用自己的授权就可以,这里就偷懒找AI完成了。参考部分都有备注
  1. using Scalar.AspNetCore;
  2. using Microsoft.AspNetCore.Authentication;
  3. using Microsoft.Extensions.Options;
  4. using System.Security.Claims;
  5. using System.Text.Encodings.Web;
  6. using Microsoft.AspNetCore.Mvc;
  7. using MyWebApi; // 添加对WeatherForecast的引用
  8. var builder = WebApplication.CreateBuilder(args);
  9. // Add services to the container.
  10. // Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
  11. builder.Services.AddOpenApi("v1");
  12. builder.Services.AddOpenApi("v2");
  13. // 添加控制器服务
  14. builder.Services.AddControllers();
  15. // 添加身份验证服务
  16. builder.Services.AddAuthentication("BasicAuthentication")
  17.     .AddScheme("BasicAuthentication", null);
  18. // 添加授权服务
  19. builder.Services.AddAuthorization(options =>
  20. {
  21.     options.AddPolicy("ScalarAccess", policy => policy.RequireAuthenticatedUser());
  22. });
  23. // 配置服务器URL,避免端口冲突
  24. builder.WebHost.UseUrls("http://localhost:5215");
  25. var app = builder.Build();
  26. // Configure static file middleware to serve the JavaScript config file
  27. app.UseStaticFiles();
  28. // 添加身份验证和授权中间件
  29. app.UseAuthentication();
  30. app.UseAuthorization();
  31. // Configure the HTTP request pipeline.
  32. if (app.Environment.IsDevelopment())
  33. {
  34.     app.MapOpenApi();
  35.     // Add Scalar for API management with JavaScript configuration and authorization
  36.     app.MapScalarApiReference("/scalar", options =>
  37.     {
  38.         options.WithTitle("MyWebApi")
  39.                .WithJavaScriptConfiguration("/js/scalar-config.js")               
  40.                .AddDocument("v1", "Aquxa API Documentation",isDefault: true)
  41.                .AddDocument("v2", "Beta API");
  42.     })
  43.     .RequireAuthorization("ScalarAccess"); // 应用授权策略
  44. }
  45. // 添加控制器路由
  46. app.MapControllers();
  47. app.Run();
  48. // Basic Authentication Handler
  49. public class BasicAuthenticationHandler : AuthenticationHandler
  50. {
  51.     public BasicAuthenticationHandler(
  52.         IOptionsMonitor options,
  53.         ILoggerFactory logger,
  54.         UrlEncoder encoder)
  55.         : base(options, logger, encoder)
  56.     {
  57.     }
  58.     protected override async Task HandleAuthenticateAsync()
  59.     {
  60.         // 检查是否有Authorization头
  61.         if (!Request.Headers.ContainsKey("Authorization"))
  62.             return AuthenticateResult.NoResult();
  63.         try
  64.         {
  65.             // 解析Basic认证头
  66.             var authHeader = Request.Headers["Authorization"].ToString();
  67.             if (!authHeader.StartsWith("Basic "))
  68.                 return AuthenticateResult.NoResult();
  69.             var encodedCredentials = authHeader.Substring("Basic ".Length).Trim();
  70.             var decodedCredentials = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(encodedCredentials));
  71.             var credentials = decodedCredentials.Split(':', 2);
  72.             
  73.             var username = credentials[0];
  74.             var password = credentials[1];
  75.             // 验证用户名和密码(这里使用硬编码,实际应用中应从配置或数据库获取)
  76.             if (username == "admin" && password == "password123")
  77.             {
  78.                 var claims = new[] { new Claim(ClaimTypes.Name, username) };
  79.                 var identity = new ClaimsIdentity(claims, Scheme.Name);
  80.                 var principal = new ClaimsPrincipal(identity);
  81.                 var ticket = new AuthenticationTicket(principal, Scheme.Name);
  82.                
  83.                 return AuthenticateResult.Success(ticket);
  84.             }
  85.             
  86.             return AuthenticateResult.Fail("Invalid username or password");
  87.         }
  88.         catch
  89.         {
  90.             return AuthenticateResult.Fail("Invalid Authorization Header");
  91.         }
  92.     }
  93.    
  94.     protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
  95.     {
  96.         // 发送WWW-Authenticate头以触发浏览器的认证对话框
  97.         Response.Headers["WWW-Authenticate"] = "Basic realm="Scalar API Documentation"";
  98.         await base.HandleChallengeAsync(properties);
  99.     }
  100. }
复制代码
 
9.png

 
[code][/code]
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册