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;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -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 =>
 | 
				
			||||||
@ -88,7 +95,6 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
 | 
				
			|||||||
                options.OperationFilter<AuthorizeCheckOperationFilter>();
 | 
					                options.OperationFilter<AuthorizeCheckOperationFilter>();
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
            ConfigureAuthService(services);
 | 
					            ConfigureAuthService(services);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            services.AddCustomHealthCheck(Configuration);
 | 
					            services.AddCustomHealthCheck(Configuration);
 | 
				
			||||||
@ -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,
 | 
				
			||||||
@ -213,15 +242,6 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
 | 
				
			|||||||
                });
 | 
					                });
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            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