netcore vue grpc、http grpc

netcore vue grpc、http grpc

vue 前端

一、项目准备

  1. 创建 vue 项目
    $ cd E:\code
    
    # 创建 vue 项目
    $ vue create apricot-grpc
       -> 1、选择 Vue3
    
  2. 安装依赖
    $ npm install grpc-web --save
    
    $ npm install google-protobuf --save
    
  3. 安装 proto 转换依赖
    $ npm install -g protoc-gen-js protoc-gen-grpc-web grpc-tools
    

二、Proto 文件转换

  1. 复制 proto 文件

  2. 查看全局目录地址

    $ npm config get prefix
    
  3. 找到 protoc.exe

  4. 生成 js 文件

    • 将所有项目需要 .proto 转换成 .js
      # 转到 src 目录
      $ cd .\aproct-grpc\src
      
      # 创建 grpc-proto-js 目录(输出js目录)
      $ mkdir grpc-proto-js
      
      # 生成 file_grpc_web_pb.js、file_pb.js
      $ D:\nodejs\node_modules\grpc-tools\bin\protoc.exe --proto_path=. --js_out=import_style=commonjs,binary:./grpc-proto-js/ --grpc-web_out=import_style=commonjs,mode=grpcwebtext:./grpc-proto-js/ .\Protos\File\file.proto
      
      # 生成  google\protobuf\empty_pb.js
      $ D:\nodejs\node_modules\grpc-tools\bin\protoc.exe --proto_path=. --js_out=import_style=commonjs,binary:./grpc-proto-js/ --grpc-web_out=import_style=commonjs,mode=grpcwebtext:./grpc-proto-js/ .\Protos\google\protobuf\empty.proto
      
      # 生成  Params\id_pb.js
      $ D:\nodejs\node_modules\grpc-tools\bin\protoc.exe --proto_path=. --js_out=import_style=commonjs,binary:./grpc-proto-js/ --grpc-web_out=import_style=commonjs,mode=grpcwebtext:./grpc-proto-js/ .\Protos\Params\id.proto   
      
      # 生成  Params\query_pb.js
      $ D:\nodejs\node_modules\grpc-tools\bin\protoc.exe --proto_path=. --js_out=import_style=commonjs,binary:./grpc-proto-js/ --grpc-web_out=import_style=commonjs,mode=grpcwebtext:./grpc-proto-js/ .\Protos\Params\query.proto   
      
      # 生成  Results\result_pb.js
      $ D:\nodejs\node_modules\grpc-tools\bin\protoc.exe --proto_path=. --js_out=import_style=commonjs,binary:./grpc-proto-js/ --grpc-web_out=import_style=commonjs,mode=grpcwebtext:./grpc-proto-js/ .\Protos\Results\result.proto   
      
    • proto_path:proto 文件地址
    • mode:请求数据类型(Content-Type
    • grpc-proto-js:生成 .js 输出目录
  5. 使用 grpc

    <template>
     <div class="hello">
       <label for="grpc api">grpc api</label>:
       <input
          name="refulapi"
          type="button"
          value="grpc api"
          v-on:click="onGrpcApi"
       />
     </div>
    </template>
    
    <script>
      import { Empty } from "../grpc-proto-js/Protos/google/protobuf/empty_pb";
      import { FileServiceClient } from "../grpc-proto-js/Protos/File/file_grpc_web_pb";
    
       export default {
          name: "HelloWorld",
          props: {
             msg: String,
          },
          methods: {
             // eslint-disable-next-line
             onGrpcApi(event) {
                const client = new FileServiceClient("http://localhost:5211", null, null);
    
                // eslint-disable-next-line
                client.readFileAsync(new Empty(), {}, (err, response) => {
                   console.log(response);
                });
             },
          
          },
       };
    </script>
    
  6. 启动项目

    $ npm run serve
    
    • 可能会出现错误:not found Any_pb.js
    • 附图:
    • 解决:将 grpc-proto-js 下相关引用 Any_pb.js 改成 any_pb.js
  7. 请求跨域

  8. 待续

三、grpc http

  1. http 请求
    <template>
     <div class="hello">
        <label for="reful api">grpc http api</label>:
        <input
           name="refulapi"
           type="button"
           value="grpc http api"
           v-on:click="onGrpcHttpApi"
        />
    </template>
    
    <script>
      import { Empty } from "../grpc-proto-js/Protos/google/protobuf/empty_pb";
      import { FileServiceClient } from "../grpc-proto-js/Protos/File/file_grpc_web_pb";
    
       export default {
          name: "HelloWorld",
          props: {
             msg: String,
          },
          methods: {
             // eslint-disable-next-line
             onGrpcHttpApi(event) {
                var xhr = new XMLHttpRequest();
    
                xhr.responseType = "json";
    
                xhr.addEventListener("readystatechange", function () {
                // eslint-disable-next-line
                if (this.readyState === 4) {
                   console.log(this.response.data);
                }
                });
    
                //设置请求
                xhr.open("get", "http://localhost:5211/v1/electron/getbase64");
                xhr.setRequestHeader("Content-Type", "application/json");
    
                xhr.send();
             },
          }
       };
    </script>
    
  2. 待续

后端

一、grpc proxy

  1. 创建项目
  2. 安装依赖
    > dotnet add package Grpc.AspNetCore --version 2.71.0
    > dotnet add package protobuf-net --version 3.2.56
    > dotnet add package Yarp.ReverseProxy --version 2.3.0
    
  3. 创建 Proto
    • 跳过,参考上文
  4. 创建服务
    /// <summary>
    /// Grcp service
    /// </summary>
    public class FileService : Electron.Grpc.FileService.FileServiceBase
    {
       public override async Task<GetBufferResponse> ReadFileAsync(Empty request, ServerCallContext context)
       {
          using var fileStream = System.IO.File.OpenRead("C:\\Users\\Administrator\\Desktop\\2fdda3cc7cd98d1001e9f6a7b36eaf0e7bec54e73a51.jpg");
    
          var memeoryStream = new MemoryStream();
    
          await fileStream.CopyToAsync(memeoryStream);
    
          var buffer = memeoryStream.ToArray();
    
          var resp = new GetBufferResponse
          {
                Code = 200,
                Data = Convert.ToBase64String(buffer)
          };
    
          return resp;
       }
    }
    
  5. 服务配置
    using Apricot.Grpc.Proxy.Services;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // yarp proxy
    builder.Services.AddReverseProxy();
    
    // grpc
    builder.Services.AddGrpc();
    
    // cors
    builder.Services.AddCors(options =>
    {
       options.AddPolicy("AllowAll", policy =>
       {
          policy.SetIsOriginAllowed(_ => true)
                .AllowAnyMethod()
          .AllowAnyHeader()
          .AllowCredentials()
          .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding", "X-Grpc-Web", "User-Agent");
       });
    });
    
    
    var app = builder.Build();
    
    // route
    app.UseRouting();
    
    // grpc web 
    app.UseGrpcWeb();
    
    app.UseCors("AllowAll");
    
    // grpc service 
    app.MapGrpcService<FileService>().EnableGrpcWeb();
    
    // frontend(http://localhost:8081) proxy
    app.MapForwarder("/electron.FileService/{**catch-all}", "http://localhost:8081");
    
    app.Run();
    
    
  6. Yarp.ReverseProxy 跨域代理
    • 未找到更优方案,有更好方案评论区留言
    • 解决
       using Apricot.Grpc.Proxy.Services;
      
       var builder = WebApplication.CreateBuilder(args);
      
       // yarp proxy
       builder.Services.AddReverseProxy();
      
       // cors
       builder.Services.AddCors(options =>
       {
          options.AddPolicy("AllowAll", policy =>
          {
             policy.SetIsOriginAllowed(_ => true)
                   .AllowAnyMethod()
             .AllowAnyHeader()
             .AllowCredentials()
             .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding", "X-Grpc-Web", "User-Agent");
          });
       });
      
       var app = builder.Build();
      
       // use cors
       app.UseCors("AllowAll");
      
       // frontend(http://localhost:8081) proxy
       app.MapForwarder("/electron.FileService/{**catch-all}", "http://localhost:8081");
      
       app.Run();
      
  7. 处理 Unsupported Media Type
    • 参考
    • 解决
      // route
      app.UseRouting();
      
      // grpc web 
      app.UseGrpcWeb();
      
      // grpc service (EnableGrpcWeb)
      app.MapGrpcService<FileService>().EnableGrpcWeb();
      
  8. 待续

二、grpc http

  1. 安装依赖 [官网]
    > dotnet add package  Microsoft.AspNetCore.Grpc.JsonTranscoding --version 8.0.21
    
  2. 更改 proto 协议
    syntax = "proto3";
    option csharp_namespace = "Apricot.Electron.Grpc";
    
    package electron;
    
    // google protos
    import "google/protobuf/empty.proto";
    import "google/protobuf/Any.proto";
    import "google/api/annotations.proto";
    
    // results protos
    import "Protos/Results/result.proto";
    import "Protos/File/buffer.proto";
    
    // services
    service FileService{
    
       rpc ReadFileAsync(google.protobuf.Empty) returns(GetBufferResponse);
    
       rpc GetBase64Async(google.protobuf.Empty) returns(GetBufferResponse){
          option (google.api.http) = {
                get: "/v1/electron/getbase64"
          };
       }
    }
    
  3. 添加服务
    /// <summary>
    /// Grcp service
    /// </summary>
    public class FileService : Electron.Grpc.FileService.FileServiceBase
    {
       public override async Task<GetBufferResponse> GetBase64Async(Empty request, ServerCallContext context)
       {
           using var fileStream = System.IO.File.OpenRead("C:\\Users\\Administrator\\Desktop\\2fdda3cc7cd98d1001e9f6a7b36eaf0e7bec54e73a51.jpg");
    
           var memeoryStream = new MemoryStream();
    
           await fileStream.CopyToAsync(memeoryStream);
    
           var buffer = memeoryStream.ToArray();
    
           var resp = new GetBufferResponse
           {
               Code = 200,
               Data = Convert.ToBase64String(buffer)
           };
    
           return resp;
       }
    }
    
  4. 服务配置
    using Apricot.Grpc.Proxy.Services;
    
    var builder = WebApplication.CreateBuilder(args);
    // grpc
    builder.Services.AddGrpc().AddJsonTranscoding();
    
    // cors
    builder.Services.AddCors(options =>
    {
       options.AddPolicy("AllowAll", policy =>
       {
          policy.SetIsOriginAllowed(_ => true)
                .AllowAnyMethod()
          .AllowAnyHeader()
          .AllowCredentials()
          .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding", "X-Grpc-Web", "User-Agent");
       });
    });
    
    var app = builder.Build();
    
    // route
    app.UseRouting();
    
    // cors
    app.UseCors("AllowAll");
    
    // grpc service
    app.MapGrpcService<FileService>();
    
    app.Run();
    
  5. 待续

示例项目

  1. [前端]
  2. [后端]
posted @ 2025-10-25 12:15  1764564459  阅读(11)  评论(0)    收藏  举报