CheckKeywords:校验你的接口参数中是否使用了其他语言的关键字/保留字

WHY

不想看文字说明的可以看图片说明

img

前段时间公司在做一个新的项目,还是负责了 API 部分的开发,照常使用restful风格,照常的 需求评审->技术方案评审->接口定义->与web/app端开发评审接口定义->开发->联调->测试 项目流程。结果中间遇到一个有意思的问题。

有个参数的含义的是功能项的意思,查了下 codelf 挑了几个相对合适的与各端开发一起沟通了下,确定使用了 function ,然后 eolinker 也定义好了,对应的类也建好了(公司技术栈:后端 .NET Core,前端 React , APP swift/java),结果前端开发发现 functionjskeywords ,就民主的改为了 func ,改完没两天,IOS 的开发又发现 func 是 Swiftkeywords ,得,又要改一次。(ps 自己也写前端,上学时也用 Swift 写过 APP ,但是评审的时候也没注意到。)

问题虽然不大,却会很烦恼,因为已经评审过了,所以 eolinker 的定义,代码都要改。查了下有没有现成支持做这个校验的,就自己实现了下,刚好没用过 Blazor ,所以做了一个接口版本,也做了一个 Blazor 版本

2.0指路👉 CheckKeywords 2.0: Blazor + wasm + AntDesign + Xamarin = ?

HOW

项目已开源 Git 源码 ,程序整体上并不复杂,只列下几个注意的点

Blazor

Blazor 是一个用 .NET 生成交互式客户端 Web UI 框架。可以和 js 互操作,使用 .NET 库。

Blazor wasm 是 Blazor 对 WebAssembly的实现。一个 SPA 框架,可以纯静态部署,本项目是选择了wasm版本。

想了解更多关于Blazor的说明,可以看 官方文档

因为想用下Blazor和API共用类库,解决方案是这样的

  • CheckKeywordsBlazor
  • CheckKeywordsGateway
  • Shared(类库)
  • Test(单元测试)

HttpClient

因为支持swagger/openapi json url的解析,所以要用到http请求。在官方示例中,C# 和 HTML 都是写在razor里的,使用时像下边这样就可以。(Program.Main 需要注入 HttpClient )

index.razor

1
2
3
4
5
6
7
8
9
@using System.Net.Http
@inject HttpClient Http

@code {
private TodoItem[] todoItems;

protected override async Task OnInitializedAsync() =>
todoItems = await Http.GetFromJsonAsync<TodoItem[]>("api/TodoItems");
}

之前vs版本,对于Blazor格式化有点问题,所以就将类写成了partial class,想当然的写出来下边的代码,结果报错了。

1
2
3
4
5
6
7
8
9
10
11
public partial class Index
{
private readonly HttpClient _httpClient {get; set;}

public Index(HttpClient httpClient)
{
_httpClient = httpClient;
}

//使用_httpClient
}

看了下官方文档,改成这样就可以了

1
2
3
4
5
6
7
public partial class Index
{
[Inject]
protected HttpClient HttpClient { get; set; }

//使用HttpClient
}

部署

由于这个是单页面应用,会存在和其他单页面应用相同的问题,当访问 baseurl/xxx时,就会404。和James沟通过这个,非动态url也可以实现像umi静态化那样的发布时为每个路由生成html文件

  • IIS

    • 可以安装url-rewrite模块进行配置
  • Nginx

    1
    2
    3
    location / {
    try_files $uri $uri/ /index.html =404;
    }

EmbeddedResource

类库中的实现本来是这样的:把各个语言的关键词写到一个json文件,类库直接读文件放入内存中使用。在Blazor中不能直接读文件(需要改为http请求json),为了保证类库通用,将json文件改为嵌入的资源(EmbeddedResource),通过 GetManifestResourceStream 读取。

1
2
3
4
var assembly = Assembly.GetExecutingAssembly();
var configStream = assembly.GetManifestResourceStream("Shared.keywords.json");
var streamReader = new StreamReader(configStream);
var str = streamReader.ReadToEnd();

压缩

Blazor wasm 首次访问时需要下载引用的dll,可想而知要下载的文件有多大,所以还是要压缩下的。

  • IIS

  • github/静态部署
    index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <script src="decode.min.js"></script>
    <script src="_framework/Blazor.webassembly.js" autostart="false"></script>
    <script>
    Blazor.start({
    loadBootResource: function (type, name, defaultUri, integrity) {
    if (type !== 'dotnetjs' && location.hostname !== 'localhost') {
    return (async function () {
    const response = await fetch(defaultUri + '.br', {
    cache: 'no-cache'
    });
    if (!response.ok) {
    throw new Error(response.statusText);
    }
    const originalResponseBuffer = await response.arrayBuffer();
    const originalResponseArray = new Int8Array(originalResponseBuffer);
    const decompressedResponseArray = BrotliDecode(originalResponseArray);
    const contentType = type ===
    'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
    return new Response(decompressedResponseArray, {
    headers: {
    'content-type': contentType
    }
    });
    })();
    }
    }
    });
    </script>

    ps. git google/brotli上的decode.min.js有bug,对应issue, 我是自己压缩的,需要可以自取,或者自行压缩

压缩效果

不压缩 9.3M
压缩后 3.5M

Text.Json 的使用

微软官方文档中,关于.NET Core 的最佳实践,总会有建议用 System.Text.Json 替换其他的 Json 库,可能解析的太小,没有明显感觉到变快。附一个两个类库获取 Json 中所有的 key 的方法吧。

感谢 bill 和 shawn,对该部分的贡献。

Newtonsoft.Json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public override List<string> BuildNeedCheckWords(string str)
{
var words = new List<string>();
var jsonObject = JObject.Parse(str);
BuildJsonAllKey(jsonObject, words);

return words.Distinct().ToList();

}

private static void BuildJsonAllKey(JObject jObject, List<string> keys)
{
foreach (var item in jObject.Cast<KeyValuePair<string, JToken>>().ToList())
{
keys.Add(item.Key);

if (item.Value is JObject itemValueJObject)
{
BuildJsonAllKey(itemValueJObject, keys);
continue;
}
}
}

System.Text.Json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public override List<string> BuildNeedCheckWords(string str)
{
var jsonDocument = JsonDocument.Parse(str, new JsonDocumentOptions
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip
});

var words = new List<string>();
BuildJsonAllKey(jsonDocument.RootElement, words);

return words.Distinct().ToList();
}

private static void BuildJsonAllKey(JsonElement jsonElement, List<string> keys)
{
foreach (var jsonProperty in jsonElement.EnumerateObject())
{
keys.Add(jsonProperty.Name);

if (jsonProperty.Value.ValueKind == JsonValueKind.Object)
{
BuildJsonAllKey(jsonProperty.Value, keys);
}
}
}

terminal color

img

个人很喜欢使用 CLI ,所以在 API 有做转换,如果是 shell 请求不返回json,而是带有颜色标记的 text/plain ,该部分有参考 wttr.in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public string[] PLAIN_TEXT_AGENTS = {
"curl",
"httpie",
"lwp-request",
"wget",
"python-requests",
"openbsd ftp",
"powershell"
};
// check
var agent = HttpContext.Request.Headers[HeaderNames.UserAgent][0].ToLower();

if (PLAIN_TEXT_AGENTS.Any(t => agent.Contains(t)))
{
return Content(ConvertCLI(result));
}

//ConvertCLI
private string ConvertCLI(CheckResult checkResult)
{
var result = string.Empty;
if (checkResult.Result == (int)EnumCheckResult.Success)
{
result = "Perfect √\r\n";
}
else if (checkResult.Result == (int)EnumCheckResult.Available)
{
result = "Usable\r\n\r\nSavewords\r\n";
checkResult.Items.ForEach(
t =>
{
result += @$"Language:{t.Language}
SaveWords:{string.Join(',', t.Words)}
REF:{t.Ref}
";
});
}
//...
else
{
result = "System Error\r\n";
}
result += PLAIN_END;

return result;
}

项目地址

https://github.com/JiChao99/check-keywords

当前支持的语言

  • C#, JavaScript, C, Java, Python, C++, PHP, VB, R, Ruby, Go, Swift, Objective-C, Rust, Kotlin, Dart, TypeScript

如果有其他语言需要 欢迎PR,或者联系我添加。

REF

CheckKeywords:校验你的接口参数中是否使用了其他语言的关键字/保留字

https://blog.jichao.top/2020/10/25/CheckKeywords/

作者

Alec.ji

发布于

2020-10-25

更新于

2021-11-07

许可协议

评论