add grpc basket
This commit is contained in:
parent
568dabcea0
commit
fe0fd36e0f
@ -219,6 +219,7 @@ services:
|
|||||||
- MarketingUrlHC=http://marketing.api/hc
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
- PaymentUrlHC=http://payment.api/hc
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
- LocationUrlHC=http://locations.api/hc
|
- LocationUrlHC=http://locations.api/hc
|
||||||
|
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
|
||||||
ports:
|
ports:
|
||||||
- "5200:80"
|
- "5200:80"
|
||||||
volumes:
|
volumes:
|
||||||
@ -235,6 +236,7 @@ services:
|
|||||||
- MarketingUrlHC=http://marketing.api/hc
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
- PaymentUrlHC=http://payment.api/hc
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
- LocationUrlHC=http://locations.api/hc
|
- LocationUrlHC=http://locations.api/hc
|
||||||
|
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
|
||||||
ports:
|
ports:
|
||||||
- "5201:80"
|
- "5201:80"
|
||||||
volumes:
|
volumes:
|
||||||
@ -251,6 +253,7 @@ services:
|
|||||||
- MarketingUrlHC=http://marketing.api/hc
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
- PaymentUrlHC=http://payment.api/hc
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
- LocationUrlHC=http://locations.api/hc
|
- LocationUrlHC=http://locations.api/hc
|
||||||
|
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
|
||||||
ports:
|
ports:
|
||||||
- "5202:80"
|
- "5202:80"
|
||||||
volumes:
|
volumes:
|
||||||
@ -267,6 +270,7 @@ services:
|
|||||||
- MarketingUrlHC=http://marketing.api/hc
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
- PaymentUrlHC=http://payment.api/hc
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
- LocationUrlHC=http://locations.api/hc
|
- LocationUrlHC=http://locations.api/hc
|
||||||
|
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
|
||||||
ports:
|
ports:
|
||||||
- "5203:80"
|
- "5203:80"
|
||||||
volumes:
|
volumes:
|
||||||
@ -286,6 +290,7 @@ services:
|
|||||||
- MarketingUrlHC=http://marketing.api/hc
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
- PaymentUrlHC=http://payment.api/hc
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
- LocationUrlHC=http://locations.api/hc
|
- LocationUrlHC=http://locations.api/hc
|
||||||
|
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
|
||||||
ports:
|
ports:
|
||||||
- "5120:80"
|
- "5120:80"
|
||||||
|
|
||||||
@ -303,6 +308,7 @@ services:
|
|||||||
- MarketingUrlHC=http://marketing.api/hc
|
- MarketingUrlHC=http://marketing.api/hc
|
||||||
- PaymentUrlHC=http://payment.api/hc
|
- PaymentUrlHC=http://payment.api/hc
|
||||||
- LocationUrlHC=http://locations.api/hc
|
- LocationUrlHC=http://locations.api/hc
|
||||||
|
- IdentityUrlExternal=http://${ESHOP_EXTERNAL_DNS_NAME_OR_IP}:5105
|
||||||
ports:
|
ports:
|
||||||
- "5121:80"
|
- "5121:80"
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -36,7 +35,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the current basket
|
// Retrieve the current basket
|
||||||
var basket = await _basket.GetByIdAsync(data.BuyerId) ?? new BasketData(data.BuyerId);
|
var basket = await _basket.GetById(data.BuyerId) ?? new BasketData(data.BuyerId);
|
||||||
|
|
||||||
var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId));
|
var catalogItems = await _catalog.GetCatalogItemsAsync(data.Items.Select(x => x.ProductId));
|
||||||
|
|
||||||
@ -76,7 +75,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the current basket
|
// Retrieve the current basket
|
||||||
var currentBasket = await _basket.GetByIdAsync(data.BasketId);
|
var currentBasket = await _basket.GetById(data.BasketId);
|
||||||
if (currentBasket == null)
|
if (currentBasket == null)
|
||||||
{
|
{
|
||||||
return BadRequest($"Basket with id {data.BasketId} not found.");
|
return BadRequest($"Basket with id {data.BasketId} not found.");
|
||||||
@ -118,7 +117,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
//item.PictureUri =
|
//item.PictureUri =
|
||||||
|
|
||||||
// Step 2: Get current basket status
|
// Step 2: Get current basket status
|
||||||
var currentBasket = (await _basket.GetByIdAsync(data.BasketId)) ?? new BasketData(data.BasketId);
|
var currentBasket = (await _basket.GetById(data.BasketId)) ?? new BasketData(data.BasketId);
|
||||||
// Step 3: Merge current status with new product
|
// Step 3: Merge current status with new product
|
||||||
currentBasket.Items.Add(new BasketDataItem()
|
currentBasket.Items.Add(new BasketDataItem()
|
||||||
{
|
{
|
||||||
|
@ -32,7 +32,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Controllers
|
|||||||
return BadRequest("Need a valid basketid");
|
return BadRequest("Need a valid basketid");
|
||||||
}
|
}
|
||||||
// Get the basket data and build a order draft based on it
|
// Get the basket data and build a order draft based on it
|
||||||
var basket = await _basketService.GetByIdAsync(basketId);
|
var basket = await _basketService.GetById(basketId);
|
||||||
|
|
||||||
if (basket == null)
|
if (basket == null)
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS base
|
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
|
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
|
||||||
COPY scripts scripts/
|
COPY scripts scripts/
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters
|
||||||
{
|
{
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Swashbuckle.AspNetCore.Swagger;
|
using Microsoft.OpenApi.Models;
|
||||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -10,7 +10,7 @@
|
|||||||
{
|
{
|
||||||
public class AuthorizeCheckOperationFilter : IOperationFilter
|
public class AuthorizeCheckOperationFilter : IOperationFilter
|
||||||
{
|
{
|
||||||
public void Apply(Operation operation, OperationFilterContext context)
|
public void Apply(OpenApiOperation operation, OperationFilterContext context)
|
||||||
{
|
{
|
||||||
// Check for authorize attribute
|
// Check for authorize attribute
|
||||||
var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any() ||
|
var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any() ||
|
||||||
@ -18,14 +18,19 @@
|
|||||||
|
|
||||||
if (!hasAuthorize) return;
|
if (!hasAuthorize) return;
|
||||||
|
|
||||||
operation.Responses.TryAdd("401", new Response { Description = "Unauthorized" });
|
operation.Responses.TryAdd("401", new OpenApiResponse { Description = "Unauthorized" });
|
||||||
operation.Responses.TryAdd("403", new Response { Description = "Forbidden" });
|
operation.Responses.TryAdd("403", new OpenApiResponse { Description = "Forbidden" });
|
||||||
|
|
||||||
operation.Security = new List<IDictionary<string, IEnumerable<string>>>
|
var oAuthScheme = new OpenApiSecurityScheme
|
||||||
{
|
{
|
||||||
new Dictionary<string, IEnumerable<string>>
|
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }
|
||||||
|
};
|
||||||
|
|
||||||
|
operation.Security = new List<OpenApiSecurityRequirement>
|
||||||
|
{
|
||||||
|
new OpenApiSecurityRequirement
|
||||||
{
|
{
|
||||||
{ "oauth2", new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" } }
|
[ oAuthScheme ] = new [] { "Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator" }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
@ -8,18 +9,22 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure
|
||||||
{
|
{
|
||||||
public class HttpClientAuthorizationDelegatingHandler
|
public class HttpClientAuthorizationDelegatingHandler : DelegatingHandler
|
||||||
: DelegatingHandler
|
|
||||||
{
|
{
|
||||||
private readonly IHttpContextAccessor _httpContextAccesor;
|
private readonly IHttpContextAccessor _httpContextAccesor;
|
||||||
|
private readonly ILogger<HttpClientAuthorizationDelegatingHandler> _logger;
|
||||||
|
|
||||||
public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor)
|
public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor, ILogger<HttpClientAuthorizationDelegatingHandler> logger)
|
||||||
{
|
{
|
||||||
_httpContextAccesor = httpContextAccesor;
|
_httpContextAccesor = httpContextAccesor;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
request.Version = new System.Version(2, 0);
|
||||||
|
request.Method = HttpMethod.Get;
|
||||||
|
|
||||||
var authorizationHeader = _httpContextAccesor.HttpContext
|
var authorizationHeader = _httpContextAccesor.HttpContext
|
||||||
.Request.Headers["Authorization"];
|
.Request.Headers["Authorization"];
|
||||||
|
|
||||||
@ -35,6 +40,8 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastruct
|
|||||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("@@@@@@@@@@@@@@@@@ {@request}", request);
|
||||||
|
|
||||||
return await base.SendAsync(request, cancellationToken);
|
return await base.SendAsync(request, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!--<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>$(NetCoreTargetVersion)</TargetFramework>
|
<TargetFramework>$(NetCoreTargetVersion)</TargetFramework>
|
||||||
@ -17,6 +17,10 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="$(AspNetCore_HealthChecks_Uris)" />
|
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="$(AspNetCore_HealthChecks_Uris)" />
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="$(AspNetCore_HealthChecks_UI_Client)" />
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="$(AspNetCore_HealthChecks_UI_Client)" />
|
||||||
|
<PackageReference Include="Grpc.AspNetCore.Server.ClientFactory" Version="$(Grpc_AspNetCore_Server_ClientFactory)" />
|
||||||
|
<PackageReference Include="Google.Protobuf" Version="$(Google_Protobuf)" />
|
||||||
|
<PackageReference Include="Grpc.Core" Version="1.22.0" />
|
||||||
|
<PackageReference Include="Grpc.Tools" Version="$(Grpc_Tools)" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="$(Microsoft_AspNetCore_Diagnostics_HealthChecks)" />
|
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="$(Microsoft_AspNetCore_Diagnostics_HealthChecks)" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="$(Microsoft_Extensions_Diagnostics_HealthChecks)" />
|
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="$(Microsoft_Extensions_Diagnostics_HealthChecks)" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="$(Serilog_AspNetCore)" />
|
<PackageReference Include="Serilog.AspNetCore" Version="$(Serilog_AspNetCore)" />
|
||||||
@ -24,41 +28,16 @@
|
|||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(Swashbuckle_AspNetCore)" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(Swashbuckle_AspNetCore)" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="$(Microsoft_Extensions_Http_Polly)" />
|
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="$(Microsoft_Extensions_Http_Polly)" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(Microsoft_AspNetCore_Authentication_JwtBearer)" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="$(Microsoft_AspNetCore_Authentication_JwtBearer)" />
|
||||||
|
<PackageReference Include="System.Net.Http.WinHttpHandler" Version="4.5.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\Devspaces.Support\Devspaces.Support.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\Devspaces.Support\Devspaces.Support.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>-->
|
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
|
||||||
<AssemblyName>Mobile.Shopping.HttpAggregator</AssemblyName>
|
|
||||||
<RootNamespace>Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator</RootNamespace>
|
|
||||||
<DockerComposeProjectPath>..\..\..\docker-compose.dcproj</DockerComposeProjectPath>
|
|
||||||
<LangVersion>$(LangVersion)</LangVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="wwwroot\" />
|
<Protobuf Include="..\..\..\Services\Basket\Basket.API\Proto\basket.proto" GrpcServices="Client" />
|
||||||
</ItemGroup>
|
<Protobuf Include="..\..\..\Services\Catalog\Catalog.API\Proto\catalog.proto" GrpcServices="Client" />
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.Uris" Version="2.2.2" />
|
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.3" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="2.2.0" />
|
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="2.1.1" />
|
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="3.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="2.2.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\Devspaces.Support\Devspaces.Support.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,13 +1,21 @@
|
|||||||
using Microsoft.AspNetCore;
|
using Microsoft.AspNetCore;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
|
private static IConfiguration _configuration;
|
||||||
|
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
_configuration = GetConfiguration();
|
||||||
|
|
||||||
BuildWebHost(args).Run();
|
BuildWebHost(args).Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,6 +32,20 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
ReloadOnChange = false
|
ReloadOnChange = false
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
.ConfigureKestrel(options =>
|
||||||
|
{
|
||||||
|
var ports = GetDefinedPorts(_configuration);
|
||||||
|
|
||||||
|
options.Listen(IPAddress.Any, ports.httpPort, listenOptions =>
|
||||||
|
{
|
||||||
|
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
|
||||||
|
});
|
||||||
|
|
||||||
|
options.Listen(IPAddress.Any, ports.grpcPort, listenOptions =>
|
||||||
|
{
|
||||||
|
listenOptions.Protocols = HttpProtocols.Http2;
|
||||||
|
});
|
||||||
|
})
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
.UseSerilog((builderContext, config) =>
|
.UseSerilog((builderContext, config) =>
|
||||||
{
|
{
|
||||||
@ -33,5 +55,24 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
.WriteTo.Console();
|
.WriteTo.Console();
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
private static IConfiguration GetConfiguration()
|
||||||
|
{
|
||||||
|
var builder = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||||
|
.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
var config = builder.Build();
|
||||||
|
|
||||||
|
return builder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config)
|
||||||
|
{
|
||||||
|
var grpcPort = config.GetValue("GRPC_PORT", 5001);
|
||||||
|
var port = config.GetValue("PORT", 80);
|
||||||
|
return (port, grpcPort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,41 +1,130 @@
|
|||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
|
using grpc;
|
||||||
|
using Grpc.Net.Client;
|
||||||
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
|
||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Newtonsoft.Json;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using static grpc.Basket;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||||
{
|
{
|
||||||
public class BasketService : IBasketService
|
public class BasketService : IBasketService
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private readonly ILogger<BasketService> _logger;
|
|
||||||
private readonly UrlsConfig _urls;
|
private readonly UrlsConfig _urls;
|
||||||
|
private readonly ILogger<BasketService> _logger;
|
||||||
|
|
||||||
public BasketService(HttpClient httpClient, ILogger<BasketService> logger, IOptions<UrlsConfig> config)
|
public BasketService(HttpClient httpClient, IOptions<UrlsConfig> config, ILogger<BasketService> logger)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_logger = logger;
|
|
||||||
_urls = config.Value;
|
_urls = config.Value;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<BasketData> GetByIdAsync(string id)
|
public async Task<BasketData> GetById(string id)
|
||||||
{
|
{
|
||||||
var data = await _httpClient.GetStringAsync(_urls.Basket + UrlsConfig.BasketOperations.GetItemById(id));
|
_logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GetById @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
|
|
||||||
var basket = !string.IsNullOrEmpty(data) ? JsonConvert.DeserializeObject<BasketData>(data) : null;
|
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
|
||||||
|
|
||||||
return basket;
|
_logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Http2UnencryptedSupport disable @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
|
|
||||||
|
_httpClient.BaseAddress = new Uri("http://localhost:5001");
|
||||||
|
|
||||||
|
_logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ {_httpClient.BaseAddress} @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", _httpClient.BaseAddress);
|
||||||
|
|
||||||
|
var client = GrpcClient.Create<BasketClient>(_httpClient);
|
||||||
|
|
||||||
|
_logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ client create @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
|
|
||||||
|
var response = await client.GetBasketByIdAsync(new BasketRequest { Id = id });
|
||||||
|
|
||||||
|
_logger.LogInformation("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ call grpc server @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
|
|
||||||
|
_logger.LogInformation("############## DATA: {@a}", response.Buyerid);
|
||||||
|
|
||||||
|
//if (streaming.IsCompleted)
|
||||||
|
//{
|
||||||
|
// _logger.LogInformation("############## DATA: {@a}", streaming.GetResult());
|
||||||
|
//}
|
||||||
|
//var streaming = client.GetBasketById(new BasketRequest { Id = id });
|
||||||
|
|
||||||
|
|
||||||
|
//var status = streaming.GetStatus();
|
||||||
|
|
||||||
|
//if (status.StatusCode == Grpc.Core.StatusCode.OK)
|
||||||
|
//{
|
||||||
|
// return null;
|
||||||
|
//}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
//return MapToBasketData(response.ResponseStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateAsync(BasketData currentBasket)
|
public async Task UpdateAsync(BasketData currentBasket)
|
||||||
{
|
{
|
||||||
var basketContent = new StringContent(JsonConvert.SerializeObject(currentBasket), System.Text.Encoding.UTF8, "application/json");
|
_httpClient.BaseAddress = new Uri(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket());
|
||||||
|
|
||||||
var data = await _httpClient.PostAsync(_urls.Basket + UrlsConfig.BasketOperations.UpdateBasket(), basketContent);
|
var client = GrpcClient.Create<BasketClient>(_httpClient);
|
||||||
|
var request = MapToCustomerBasketRequest(currentBasket);
|
||||||
|
|
||||||
|
await client.UpdateBasketAsync(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BasketData MapToBasketData(CustomerBasketResponse customerBasketRequest)
|
||||||
|
{
|
||||||
|
if (customerBasketRequest == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var map = new BasketData
|
||||||
|
{
|
||||||
|
BuyerId = customerBasketRequest.Buyerid
|
||||||
|
};
|
||||||
|
|
||||||
|
customerBasketRequest.Items.ToList().ForEach(item => map.Items.Add(new BasketDataItem
|
||||||
|
{
|
||||||
|
Id = item.Id,
|
||||||
|
OldUnitPrice = (decimal)item.Oldunitprice,
|
||||||
|
PictureUrl = item.Pictureurl,
|
||||||
|
ProductId = item.Productid,
|
||||||
|
ProductName = item.Productname,
|
||||||
|
Quantity = item.Quantity,
|
||||||
|
UnitPrice = (decimal)item.Unitprice
|
||||||
|
}));
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CustomerBasketRequest MapToCustomerBasketRequest(BasketData basketData)
|
||||||
|
{
|
||||||
|
if (basketData == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var map = new CustomerBasketRequest
|
||||||
|
{
|
||||||
|
Buyerid = basketData.BuyerId
|
||||||
|
};
|
||||||
|
|
||||||
|
basketData.Items.ToList().ForEach(item => map.Items.Add(new BasketItemResponse
|
||||||
|
{
|
||||||
|
Id = item.Id,
|
||||||
|
Oldunitprice = (double)item.OldUnitPrice,
|
||||||
|
Pictureurl = item.PictureUrl,
|
||||||
|
Productid = item.ProductId,
|
||||||
|
Productname = item.ProductName,
|
||||||
|
Quantity = item.Quantity,
|
||||||
|
Unitprice = (double)item.UnitPrice
|
||||||
|
}));
|
||||||
|
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,37 @@
|
|||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
|
using CatalogApi;
|
||||||
|
using Grpc.Net.Client;
|
||||||
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
|
||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Models;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using static CatalogApi.Catalog;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
||||||
{
|
{
|
||||||
public class CatalogService : ICatalogService
|
public class CatalogService : ICatalogService
|
||||||
{
|
{
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private readonly ILogger<CatalogService> _logger;
|
|
||||||
private readonly UrlsConfig _urls;
|
private readonly UrlsConfig _urls;
|
||||||
|
|
||||||
public CatalogService(HttpClient httpClient, ILogger<CatalogService> logger, IOptions<UrlsConfig> config)
|
public CatalogService(HttpClient httpClient, IOptions<UrlsConfig> config)
|
||||||
{
|
{
|
||||||
_httpClient = httpClient;
|
_httpClient = httpClient;
|
||||||
_logger = logger;
|
|
||||||
_urls = config.Value;
|
_urls = config.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<CatalogItem> GetCatalogItemAsync(int id)
|
public async Task<CatalogItem> GetCatalogItemAsync(int id)
|
||||||
{
|
{
|
||||||
var stringContent = await _httpClient.GetStringAsync(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
|
_httpClient.BaseAddress = new Uri(_urls.Catalog + UrlsConfig.CatalogOperations.GetItemById(id));
|
||||||
var catalogItem = JsonConvert.DeserializeObject<CatalogItem>(stringContent);
|
|
||||||
|
|
||||||
return catalogItem;
|
var client = GrpcClient.Create<CatalogClient>(_httpClient);
|
||||||
|
var request = new CatalogItemRequest { Id = id };
|
||||||
|
var response = await client.GetItemByIdAsync(request);
|
||||||
|
|
||||||
|
return MapToCatalogItemResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<CatalogItem>> GetCatalogItemsAsync(IEnumerable<int> ids)
|
public async Task<IEnumerable<CatalogItem>> GetCatalogItemsAsync(IEnumerable<int> ids)
|
||||||
@ -37,5 +41,16 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
|||||||
|
|
||||||
return catalogItems;
|
return catalogItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CatalogItem MapToCatalogItemResponse(CatalogItemResponse catalogItemResponse)
|
||||||
|
{
|
||||||
|
return new CatalogItem
|
||||||
|
{
|
||||||
|
Id = catalogItemResponse.Id,
|
||||||
|
Name = catalogItemResponse.Name,
|
||||||
|
PictureUri = catalogItemResponse.PictureUri,
|
||||||
|
Price = (decimal)catalogItemResponse.Price
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Services
|
|||||||
{
|
{
|
||||||
public interface IBasketService
|
public interface IBasketService
|
||||||
{
|
{
|
||||||
Task<BasketData> GetByIdAsync(string id);
|
Task<BasketData> GetById(string id);
|
||||||
|
|
||||||
Task UpdateAsync(BasketData currentBasket);
|
Task UpdateAsync(BasketData currentBasket);
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Builder;
|
|||||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Config;
|
||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Filters.Basket.API.Infrastructure.Filters;
|
||||||
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure;
|
using Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure;
|
||||||
@ -14,9 +13,9 @@ using Microsoft.Extensions.Configuration;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
using Polly;
|
using Polly;
|
||||||
using Polly.Extensions.Http;
|
using Polly.Extensions.Http;
|
||||||
using Swashbuckle.AspNetCore.Swagger;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
@ -63,19 +62,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
app.UsePathBase(pathBase);
|
app.UsePathBase(pathBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseHealthChecks("/hc", new HealthCheckOptions()
|
|
||||||
{
|
|
||||||
Predicate = _ => true,
|
|
||||||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseHealthChecks("/liveness", new HealthCheckOptions
|
|
||||||
{
|
|
||||||
Predicate = r => r.Name.Contains("self")
|
|
||||||
});
|
|
||||||
|
|
||||||
app.UseCors("CorsPolicy");
|
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
@ -86,15 +72,31 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
app.UseHsts();
|
app.UseHsts();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseAuthentication();
|
app.UseCors("CorsPolicy");
|
||||||
app.UseHttpsRedirection();
|
app.UseHttpsRedirection();
|
||||||
app.UseMvc();
|
app.UseRouting();
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapDefaultControllerRoute();
|
||||||
|
endpoints.MapControllers();
|
||||||
|
endpoints.MapHealthChecks("/hc", new HealthCheckOptions()
|
||||||
|
{
|
||||||
|
Predicate = _ => true,
|
||||||
|
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
|
||||||
|
});
|
||||||
|
endpoints.MapHealthChecks("/liveness", new HealthCheckOptions
|
||||||
|
{
|
||||||
|
Predicate = r => r.Name.Contains("self")
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
app.UseSwagger().UseSwaggerUI(c =>
|
app.UseSwagger().UseSwaggerUI(c =>
|
||||||
{
|
{
|
||||||
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1");
|
c.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Purchase BFF V1");
|
||||||
|
|
||||||
c.OAuthClientId("Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregatorwaggerui");
|
c.OAuthClientId("mobileshoppingaggswaggerui");
|
||||||
c.OAuthClientSecret(string.Empty);
|
c.OAuthClientSecret(string.Empty);
|
||||||
c.OAuthRealm(string.Empty);
|
c.OAuthRealm(string.Empty);
|
||||||
c.OAuthAppName("Purchase BFF Swagger UI");
|
c.OAuthAppName("Purchase BFF Swagger UI");
|
||||||
@ -109,29 +111,32 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
services.AddOptions();
|
services.AddOptions();
|
||||||
services.Configure<UrlsConfig>(configuration.GetSection("urls"));
|
services.Configure<UrlsConfig>(configuration.GetSection("urls"));
|
||||||
|
|
||||||
services.AddMvc()
|
services.AddControllers()
|
||||||
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
|
.AddNewtonsoftJson();
|
||||||
|
|
||||||
services.AddSwaggerGen(options =>
|
services.AddSwaggerGen(options =>
|
||||||
{
|
{
|
||||||
options.DescribeAllEnumsAsStrings();
|
options.DescribeAllEnumsAsStrings();
|
||||||
options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
|
options.SwaggerDoc("v1", new OpenApiInfo
|
||||||
{
|
{
|
||||||
Title = "Shopping Aggregator for Mobile Clients",
|
Title = "Shopping Aggregator for Mobile Clients",
|
||||||
Version = "v1",
|
Version = "v1",
|
||||||
Description = "Shopping Aggregator for Mobile Clients",
|
Description = "Shopping Aggregator for Mobile Clients"
|
||||||
TermsOfService = "Terms Of Service"
|
|
||||||
});
|
});
|
||||||
|
options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
|
||||||
options.AddSecurityDefinition("oauth2", new OAuth2Scheme
|
|
||||||
{
|
{
|
||||||
Type = "oauth2",
|
Type = SecuritySchemeType.OAuth2,
|
||||||
Flow = "implicit",
|
Flows = new OpenApiOAuthFlows()
|
||||||
AuthorizationUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize",
|
|
||||||
TokenUrl = $"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token",
|
|
||||||
Scopes = new Dictionary<string, string>()
|
|
||||||
{
|
{
|
||||||
{ "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" }
|
Implicit = new OpenApiOAuthFlow()
|
||||||
|
{
|
||||||
|
AuthorizationUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize"),
|
||||||
|
TokenUrl = new Uri($"{configuration.GetValue<string>("IdentityUrlExternal")}/connect/token"),
|
||||||
|
Scopes = new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "mobileshoppingagg", "Shopping Aggregator for Mobile Clients" }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -152,7 +157,8 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
}
|
}
|
||||||
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
|
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
|
||||||
|
|
||||||
var identityUrl = configuration.GetValue<string>("urls:identity");
|
var identityUrl = configuration.GetValue<string>("urls:identity");
|
||||||
|
|
||||||
services.AddAuthentication(options =>
|
services.AddAuthentication(options =>
|
||||||
@ -166,15 +172,6 @@ namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator
|
|||||||
options.Authority = identityUrl;
|
options.Authority = identityUrl;
|
||||||
options.RequireHttpsMetadata = false;
|
options.RequireHttpsMetadata = false;
|
||||||
options.Audience = "mobileshoppingagg";
|
options.Audience = "mobileshoppingagg";
|
||||||
options.Events = new JwtBearerEvents()
|
|
||||||
{
|
|
||||||
OnAuthenticationFailed = async ctx =>
|
|
||||||
{
|
|
||||||
},
|
|
||||||
OnTokenValidated = async ctx =>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
{
|
{
|
||||||
|
"Kestrel": {
|
||||||
|
"EndpointDefaults": {
|
||||||
|
"Protocols": "Http2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"IncludeScopes": false,
|
"IncludeScopes": false,
|
||||||
"Debug": {
|
"Debug": {
|
||||||
|
@ -4,5 +4,20 @@
|
|||||||
"catalog": "http://localhost:55101",
|
"catalog": "http://localhost:55101",
|
||||||
"orders": "http://localhost:55102",
|
"orders": "http://localhost:55102",
|
||||||
"identity": "http://localhost:55105"
|
"identity": "http://localhost:55105"
|
||||||
|
},
|
||||||
|
"IdentityUrlExternal": "http://localhost:5105",
|
||||||
|
"IdentityUrl": "http://localhost:5105",
|
||||||
|
"Logging": {
|
||||||
|
"IncludeScopes": false,
|
||||||
|
"Debug": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Debug"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Console": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Debug"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,9 @@
|
|||||||
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="$(AspNetCore_HealthChecks_Redis)" />
|
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="$(AspNetCore_HealthChecks_Redis)" />
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="$(AspNetCore_HealthChecks_UI_Client)" />
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="$(AspNetCore_HealthChecks_UI_Client)" />
|
||||||
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="$(Autofac_Extensions_DependencyInjection)" />
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="$(Autofac_Extensions_DependencyInjection)" />
|
||||||
|
<PackageReference Include="Grpc.AspNetCore.Server" Version="$(Grpc_AspNetCore_Server)" />
|
||||||
|
<PackageReference Include="Google.Protobuf" Version="$(Google_Protobuf)" />
|
||||||
|
<PackageReference Include="Grpc.Tools" Version="$(Grpc_Tools)" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="$(Microsoft_ApplicationInsights_AspNetCore)" />
|
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="$(Microsoft_ApplicationInsights_AspNetCore)" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="$(Microsoft_ApplicationInsights_DependencyCollector)" />
|
<PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" Version="$(Microsoft_ApplicationInsights_DependencyCollector)" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="$(Microsoft_ApplicationInsights_Kubernetes)" />
|
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="$(Microsoft_ApplicationInsights_Kubernetes)" />
|
||||||
@ -39,6 +42,12 @@
|
|||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(Swashbuckle_AspNetCore)" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(Swashbuckle_AspNetCore)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Protobuf Include="Proto\basket.proto" GrpcServices="Server" Generator="MSBuild:Compile" />
|
||||||
|
<Content Include="@(Protobuf)" />
|
||||||
|
<None Remove="@(Protobuf)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||||
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
|
||||||
|
100
src/Services/Basket/Basket.API/Grpc/BasketService.cs
Normal file
100
src/Services/Basket/Basket.API/Grpc/BasketService.cs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
using Grpc.Core;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace grpc
|
||||||
|
{
|
||||||
|
public class BasketService : Basket.BasketBase
|
||||||
|
{
|
||||||
|
private readonly IBasketRepository _repository;
|
||||||
|
private readonly ILogger<BasketService> _logger;
|
||||||
|
|
||||||
|
public BasketService(IBasketRepository repository, ILogger<BasketService> logger)
|
||||||
|
{
|
||||||
|
_repository = repository;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<CustomerBasketResponse> GetBasketById(BasketRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Begin grpc call from method {context.Method} for basket id {request.Id}");
|
||||||
|
|
||||||
|
var data = await _repository.GetBasketAsync(request.Id);
|
||||||
|
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
context.Status = new Status(StatusCode.OK, $"Basket with id {request.Id} do exist");
|
||||||
|
|
||||||
|
return MapToCustomerBasketResponse(data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Status = new Status(StatusCode.NotFound, $"Basket with id {request.Id} do not exist");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<CustomerBasketResponse> UpdateBasket(CustomerBasketRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
_logger.LogInformation($"Begin grpc call BasketService.UpdateBasketAsync for buyer id {request.Buyerid}");
|
||||||
|
|
||||||
|
var customerBasket = MapToCustomerBasket(request);
|
||||||
|
|
||||||
|
var response = await _repository.UpdateBasketAsync(customerBasket);
|
||||||
|
|
||||||
|
if (response != null)
|
||||||
|
{
|
||||||
|
return MapToCustomerBasketResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Status = new Status(StatusCode.NotFound, $"Basket with buyer id {request.Buyerid} do not exist");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CustomerBasketResponse MapToCustomerBasketResponse(CustomerBasket customerBasket)
|
||||||
|
{
|
||||||
|
var response = new CustomerBasketResponse
|
||||||
|
{
|
||||||
|
Buyerid = customerBasket.BuyerId
|
||||||
|
};
|
||||||
|
|
||||||
|
customerBasket.Items.ForEach(item => response.Items.Add(new BasketItemResponse
|
||||||
|
{
|
||||||
|
Id = item.Id,
|
||||||
|
Oldunitprice = (double)item.OldUnitPrice,
|
||||||
|
Pictureurl = item.PictureUrl,
|
||||||
|
Productid = item.ProductId,
|
||||||
|
Productname = item.ProductName,
|
||||||
|
Quantity = item.Quantity,
|
||||||
|
Unitprice = (double)item.UnitPrice
|
||||||
|
}));
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CustomerBasket MapToCustomerBasket(CustomerBasketRequest customerBasketRequest)
|
||||||
|
{
|
||||||
|
var response = new CustomerBasket
|
||||||
|
{
|
||||||
|
BuyerId = customerBasketRequest.Buyerid
|
||||||
|
};
|
||||||
|
|
||||||
|
customerBasketRequest.Items.ToList().ForEach(item => response.Items.Add(new BasketItem
|
||||||
|
{
|
||||||
|
Id = item.Id,
|
||||||
|
OldUnitPrice = (decimal)item.Oldunitprice,
|
||||||
|
PictureUrl = item.Pictureurl,
|
||||||
|
ProductId = item.Productid,
|
||||||
|
ProductName = item.Productname,
|
||||||
|
Quantity = item.Quantity,
|
||||||
|
UnitPrice = (decimal)item.Unitprice
|
||||||
|
}));
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,7 +28,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Infrastructure.Reposit
|
|||||||
|
|
||||||
public IEnumerable<string> GetUsers()
|
public IEnumerable<string> GetUsers()
|
||||||
{
|
{
|
||||||
var server = GetServer();
|
var server = GetServer();
|
||||||
var data = server.Keys();
|
var data = server.Keys();
|
||||||
|
|
||||||
return data?.Select(k => k.ToString());
|
return data?.Select(k => k.ToString());
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
using Microsoft.AspNetCore;
|
using Microsoft.AspNetCore;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Basket.API
|
namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||||
{
|
{
|
||||||
@ -45,8 +46,21 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
|
private static IWebHost BuildWebHost(IConfiguration configuration, string[] args) =>
|
||||||
WebHost.CreateDefaultBuilder(args)
|
WebHost.CreateDefaultBuilder(args)
|
||||||
.CaptureStartupErrors(false)
|
.CaptureStartupErrors(false)
|
||||||
.UseFailing(options =>
|
.ConfigureKestrel(options =>
|
||||||
options.ConfigPath = "/Failing")
|
{
|
||||||
|
var ports = GetDefinedPorts(configuration);
|
||||||
|
|
||||||
|
options.Listen(IPAddress.Any, ports.httpPort, listenOptions =>
|
||||||
|
{
|
||||||
|
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
|
||||||
|
});
|
||||||
|
|
||||||
|
options.Listen(IPAddress.Any, ports.grpcPort, listenOptions =>
|
||||||
|
{
|
||||||
|
listenOptions.Protocols = HttpProtocols.Http2;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.UseFailing(options => options.ConfigPath = "/Failing")
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
.UseApplicationInsights()
|
.UseApplicationInsights()
|
||||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
@ -88,5 +102,12 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
|
|
||||||
return builder.Build();
|
return builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config)
|
||||||
|
{
|
||||||
|
var grpcPort = config.GetValue("GRPC_PORT", 5001);
|
||||||
|
var port = config.GetValue("PORT", 80);
|
||||||
|
return (port, grpcPort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
38
src/Services/Basket/Basket.API/Proto/basket.proto
Normal file
38
src/Services/Basket/Basket.API/Proto/basket.proto
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option csharp_namespace = "grpc";
|
||||||
|
|
||||||
|
package BasketApi;
|
||||||
|
|
||||||
|
service Basket {
|
||||||
|
rpc GetBasketById(BasketRequest) returns (CustomerBasketResponse) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/GetBasketById"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
rpc UpdateBasket(CustomerBasketRequest) returns (CustomerBasketResponse) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
message BasketRequest {
|
||||||
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CustomerBasketRequest {
|
||||||
|
string buyerid = 1;
|
||||||
|
repeated BasketItemResponse items = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CustomerBasketResponse {
|
||||||
|
string buyerid = 1;
|
||||||
|
repeated BasketItemResponse items = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BasketItemResponse {
|
||||||
|
string id = 1;
|
||||||
|
string productid = 2;
|
||||||
|
string productname = 3;
|
||||||
|
double unitprice = 4;
|
||||||
|
double oldunitprice = 5;
|
||||||
|
int32 quantity = 6;
|
||||||
|
string pictureurl = 7;
|
||||||
|
}
|
@ -4,6 +4,7 @@ using Basket.API.Infrastructure.Filters;
|
|||||||
using Basket.API.Infrastructure.Middlewares;
|
using Basket.API.Infrastructure.Middlewares;
|
||||||
using Basket.API.IntegrationEvents.EventHandling;
|
using Basket.API.IntegrationEvents.EventHandling;
|
||||||
using Basket.API.IntegrationEvents.Events;
|
using Basket.API.IntegrationEvents.Events;
|
||||||
|
using grpc;
|
||||||
using HealthChecks.UI.Client;
|
using HealthChecks.UI.Client;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
@ -32,6 +33,7 @@ using StackExchange.Redis;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Basket.API
|
namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||||
{
|
{
|
||||||
@ -47,6 +49,11 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public virtual IServiceProvider ConfigureServices(IServiceCollection services)
|
public virtual IServiceProvider ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
services.AddGrpc(options =>
|
||||||
|
{
|
||||||
|
options.EnableDetailedErrors = true;
|
||||||
|
});
|
||||||
|
|
||||||
RegisterAppInsights(services);
|
RegisterAppInsights(services);
|
||||||
|
|
||||||
services.AddControllers(options =>
|
services.AddControllers(options =>
|
||||||
@ -84,10 +91,9 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
options.OperationFilter<AuthorizeCheckOperationFilter>();
|
options.OperationFilter<AuthorizeCheckOperationFilter>();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
ConfigureAuthService(services);
|
ConfigureAuthService(services);
|
||||||
|
|
||||||
@ -192,6 +198,14 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
app.UsePathBase(pathBase);
|
app.UsePathBase(pathBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.UseSwagger()
|
||||||
|
.UseSwaggerUI(setup =>
|
||||||
|
{
|
||||||
|
setup.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Basket.API V1");
|
||||||
|
setup.OAuthClientId("basketswaggerui");
|
||||||
|
setup.OAuthAppName("Basket Swagger UI");
|
||||||
|
});
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
ConfigureAuth(app);
|
ConfigureAuth(app);
|
||||||
|
|
||||||
@ -202,6 +216,21 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
{
|
{
|
||||||
endpoints.MapDefaultControllerRoute();
|
endpoints.MapDefaultControllerRoute();
|
||||||
endpoints.MapControllers();
|
endpoints.MapControllers();
|
||||||
|
endpoints.MapGet("/_proto/", async ctx =>
|
||||||
|
{
|
||||||
|
ctx.Response.ContentType = "text/plain";
|
||||||
|
using var fs = new FileStream(Path.Combine(env.ContentRootPath, "Proto", "basket.proto"), FileMode.Open, FileAccess.Read);
|
||||||
|
using var sr = new StreamReader(fs);
|
||||||
|
while (!sr.EndOfStream)
|
||||||
|
{
|
||||||
|
var line = await sr.ReadLineAsync();
|
||||||
|
if (line != "/* >>" || line != "<< */")
|
||||||
|
{
|
||||||
|
await ctx.Response.WriteAsync(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
endpoints.MapGrpcService<BasketService>();
|
||||||
endpoints.MapHealthChecks("/hc", new HealthCheckOptions()
|
endpoints.MapHealthChecks("/hc", new HealthCheckOptions()
|
||||||
{
|
{
|
||||||
Predicate = _ => true,
|
Predicate = _ => true,
|
||||||
@ -212,15 +241,6 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
|||||||
Predicate = r => r.Name.Contains("self")
|
Predicate = r => r.Name.Contains("self")
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.UseSwagger()
|
|
||||||
.UseSwaggerUI(setup =>
|
|
||||||
{
|
|
||||||
setup.SwaggerEndpoint($"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json", "Basket.API V1");
|
|
||||||
setup.OAuthClientId("basketswaggerui");
|
|
||||||
setup.OAuthAppName("Basket Swagger UI");
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
ConfigureEventBus(app);
|
ConfigureEventBus(app);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Kestrel": {
|
||||||
|
"EndpointDefaults": {
|
||||||
|
"Protocols": "Http2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"SubscriptionClientName": "Basket",
|
"SubscriptionClientName": "Basket",
|
||||||
"ApplicationInsights": {
|
"ApplicationInsights": {
|
||||||
"InstrumentationKey": ""
|
"InstrumentationKey": ""
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
<Grpc_AspNetCore_Server>0.1.22-pre1</Grpc_AspNetCore_Server>
|
<Grpc_AspNetCore_Server>0.1.22-pre1</Grpc_AspNetCore_Server>
|
||||||
<Google_Protobuf>3.9.0-rc1</Google_Protobuf>
|
<Google_Protobuf>3.9.0-rc1</Google_Protobuf>
|
||||||
<Grpc_Tools>1.22.0</Grpc_Tools>
|
<Grpc_Tools>1.22.0</Grpc_Tools>
|
||||||
|
<Grpc_AspNetCore_Server_ClientFactory>0.1.22-pre2</Grpc_AspNetCore_Server_ClientFactory>
|
||||||
|
|
||||||
<Microsoft_Extensions_Hosting>3.0.0-preview7.19362.4</Microsoft_Extensions_Hosting>
|
<Microsoft_Extensions_Hosting>3.0.0-preview7.19362.4</Microsoft_Extensions_Hosting>
|
||||||
<Microsoft_VisualStudio_Azure_Containers_Tools_Targets>1.7.9</Microsoft_VisualStudio_Azure_Containers_Tools_Targets>
|
<Microsoft_VisualStudio_Azure_Containers_Tools_Targets>1.7.9</Microsoft_VisualStudio_Azure_Containers_Tools_Targets>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user