This commit is contained in:
cjd
2025-11-04 21:09:16 +08:00
parent 8260e293c7
commit bb90a020dc
592 changed files with 61749 additions and 27 deletions

View File

@@ -0,0 +1,77 @@
using DouyinApi.Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DouyinApi.Gateway.Extensions
{
/// <summary>
/// 这里不需要,目前集成的是 DouyinApi.Extensions 下的接口处理器
/// 但是你可以单独在网关中使用这个。
/// </summary>
public class ApiResponseHandler : DelegatingHandler
{
JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
var contentType = response.Content.Headers.ContentType?.MediaType ?? "";
if (!contentType.Equals("application/json")) return response;
dynamic result = null;
var resultStr = await response.Content.ReadAsStringAsync();
try
{
result = JsonConvert.DeserializeObject<dynamic>(resultStr);
}
catch (Exception)
{
return response;
}
if (result != null && result.code == 500) resultStr = result.msg.ToString();
var apiResponse = new ApiResponse(StatusCode.CODE200).MessageModel;
if (response.StatusCode != HttpStatusCode.OK || result.code == (int)HttpStatusCode.InternalServerError)
{
var exception = new Exception(resultStr);
apiResponse = new ApiResponse(StatusCode.CODE500).MessageModel;
}
else if (result.code == (int)HttpStatusCode.Unauthorized)
{
apiResponse = new ApiResponse(StatusCode.CODE401).MessageModel;
}
else if (result.code == (int)HttpStatusCode.Forbidden)
{
apiResponse = new ApiResponse(StatusCode.CODE403).MessageModel;
}
else
{
}
var statusCode = apiResponse.status == 500 ? HttpStatusCode.InternalServerError
: apiResponse.status == 401 ? HttpStatusCode.Unauthorized
: apiResponse.status == 403 ? HttpStatusCode.Forbidden
: HttpStatusCode.OK;
response.StatusCode = statusCode;
response.Content = new StringContent(JsonConvert.SerializeObject(apiResponse, jsonSerializerSettings), Encoding.UTF8, "application/json");
return response;
}
}
}

View File

@@ -0,0 +1,53 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
namespace DouyinApi.Gateway.Extensions
{
public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public CustomAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
// 可以查询数据库等操作
// 获取当前用户不能放到token中的私密信息
var userPhone = "15010000000";
var claims = new List<Claim>()
{
new Claim("user-phone", userPhone),
new Claim("gw-sign", "gw")
};
var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, Scheme.Name));
var ticket = new AuthenticationTicket(principal, Scheme.Name);
await Task.CompletedTask;
return AuthenticateResult.Success(ticket);
}
protected virtual string GetTokenStringFromHeader()
{
var token = string.Empty;
string authorization = Request.Headers[HeaderNames.Authorization];
if (!string.IsNullOrEmpty(authorization) && authorization.StartsWith($"Bearer ", StringComparison.OrdinalIgnoreCase))
{
token = authorization["Bearer ".Length..].Trim();
}
return token;
}
}
}

View File

@@ -0,0 +1,34 @@
using DouyinApi.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.Provider.Nacos;
using Ocelot.Provider.Polly;
using System;
using System.Threading.Tasks;
namespace DouyinApi.Gateway.Extensions
{
public static class CustomOcelotSetup
{
public static void AddCustomOcelotSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
services.AddAuthentication_JWTSetup();
services.AddOcelot()
.AddDelegatingHandler<CustomResultHandler>()
//.AddNacosDiscovery()
//.AddConsul()
.AddPolly();
}
public static async Task<IApplicationBuilder> UseCustomOcelotMildd(this IApplicationBuilder app)
{
await app.UseOcelot();
return app;
}
}
}

View File

@@ -0,0 +1,62 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DouyinApi.Gateway.Extensions
{
public class CustomResultHandler : DelegatingHandler
{
JsonSerializerSettings _camelSettings = new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() };
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
var contentType = response.Content.Headers.ContentType?.MediaType ?? "";
if (!contentType.Equals("application/json")) return response;
dynamic result = null;
var resultStr = await response.Content.ReadAsStringAsync();
try
{
Console.WriteLine(resultStr);
result = JsonConvert.DeserializeObject<dynamic>(resultStr);
}
catch (Exception)
{
return response;
}
if (result != null && result.errorCode == 500) resultStr = result.message.ToString();
var exception = new Exception(resultStr);
if (response.StatusCode == HttpStatusCode.InternalServerError || result.errorCode == (int)HttpStatusCode.InternalServerError)
{
var apiResult = new
{
Result = false,
Message = "服务器内部错误",
ErrorCode = (int)HttpStatusCode.InternalServerError,
Data = new
{
exception.Message,
exception.StackTrace
}
};
response.Content = new StringContent(JsonConvert.SerializeObject(apiResult, _camelSettings), Encoding.UTF8, "application/json");
}
else
{
}
return response;
}
}
}

View File

@@ -0,0 +1,81 @@
using DouyinApi.Common;
using DouyinApi.Extensions.Middlewares;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.Filters;
using Swashbuckle.AspNetCore.SwaggerUI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using static DouyinApi.Extensions.CustomApiVersion;
namespace DouyinApi.Gateway.Extensions
{
public static class CustomSwaggerSetup
{
public static void AddCustomSwaggerSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
var basePath = AppContext.BaseDirectory;
services.AddMvc(option => option.EnableEndpointRouting = false);
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "自定义网关 接口文档",
});
var xmlPath = Path.Combine(basePath, "DouyinApi.Gateway.xml");
c.IncludeXmlComments(xmlPath, true);
c.OperationFilter<AddResponseHeadersFilter>();
c.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
c.OperationFilter<SecurityRequirementsOperationFilter>();
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
});
}
public static void UseCustomSwaggerMildd(this IApplicationBuilder app, Func<Stream> streamHtml)
{
if (app == null) throw new ArgumentNullException(nameof(app));
var apis = new List<string> { "blog-svc" };
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint($"/swagger/v1/swagger.json", "gateway");
apis.ForEach(m =>
{
c.SwaggerEndpoint($"/swagger/apiswg/{m}/swagger.json", m);
});
if (streamHtml.Invoke() == null)
{
var msg = "index.html的属性必须设置为嵌入的资源";
throw new Exception(msg);
}
c.IndexStream = streamHtml;
c.RoutePrefix = "";
});
}
}
}