abpframework / abp

Open-source web application framework for ASP.NET Core! Offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET. Provides the fundamental infrastructure, cross-cutting-concern implementations, startup templates, application modules, UI themes, tooling and documentation.
https://abp.io
GNU Lesser General Public License v3.0
12.79k stars 3.41k forks source link

how to add custome header to HttpApi.Client request !? #12997

Closed RezaPouya closed 1 year ago

RezaPouya commented 2 years ago

how can i add custom header to outbound request of httpApi.Client for specific interface ?

maliming commented 2 years ago

Static proxy or dynamic proxy?

RezaPouya commented 2 years ago

dynamic proxy , I have an interface marker called InternalApiService , so , I want to add custom "X-Api-Key" which it value is stored in AppSetting per RemoteService , to be added to request ...

I tried by replacing ClientBaseProcxy<> and DynamicProxyHandler but it didnt work ( I don't know why )

We have multiple microservice , so I created a solution called []Famework and I put common configuration in every project of framework and then add the dll as module to microservices related module ...

for example , I Have this for HttpApi.Client

[DependsOn(typeof(AbpHttpClientModule))]
public class GajMarketFrameworkDomainHttpApiClientModule : AbpModule
{
    public override void PreConfigureServices(ServiceConfigurationContext context)
    {
    }

    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        context.Services.AddTransient(typeof(GajMarketClientBase<>));
        context.Services.AddTransient(typeof(DynamicHttpProxyInterceptorClientProxy<>));

        ServiceDescriptor gajMarketInternalHttpProxyInterceptorServiceDescriptor =
            new(typeof(DynamicHttpProxyInterceptor<>), typeof(GajMarketInternalHttpProxyInterceptor<>), ServiceLifetime.Transient);

        context.Services.Replace(gajMarketInternalHttpProxyInterceptorServiceDescriptor);

        ServiceDescriptor gajMarketDynamicInternalHttpProxyInterceptorClientProxy =
            new(typeof(DynamicHttpProxyInterceptorClientProxy<>), typeof(GajMarketDynamicInternalHttpProxyInterceptorClientProxy<>), ServiceLifetime.Transient);

        context.Services.Replace(gajMarketDynamicInternalHttpProxyInterceptorClientProxy);
    }
}

but it doesn't work

RezaPouya commented 2 years ago

one of main problem is that DynamicHttpProxyInterceptor, DynamicHttpProxyInterceptor , DynamicHttpProxyInterceptorClientProxy and many classes in source code in HttpApi.Clientmodule don't have interfaces , so when I wanted to use my own implementation , I was blocked because I couldn't inherit from them and then replace my own with it ( because actually I don't know how it really work so i can't confidentially replace it without fear of breaking code and I don't have time to dive deep in code ) , I did some workaround for this problem but it seems it doesn't work ...

from what I saw , replacing ClientBaseProxy<> with my own implementation is enough , but I can't do it !!!

In My opinion , the style of coding which is relaying on the class itself ( without having any proper interface to define functionality ) for auto dependency injection is not good in framework level .

RezaPouya commented 2 years ago

currently I Use this

public class CustomProxyHttpClientFactory : IProxyHttpClientFactory, ITransientDependency { private readonly IHttpClientFactory _httpClientFactory; private readonly IConfiguration configuration; private IRemoteServiceConfigurationProvider _remoteServiceConfigurationProvider;

public CustomProxyHttpClientFactory(IHttpClientFactory httpClientFactory,
    IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider,
    IConfiguration configuration)
{
    _httpClientFactory = httpClientFactory;
    _remoteServiceConfigurationProvider = remoteServiceConfigurationProvider;
    this.configuration = configuration;
}

public HttpClient Create()
{
    var client = _httpClientFactory.CreateClient();

    client.DefaultRequestHeaders.Add("X-Api-Key", configuration["App:ApiKey"]);

    return client;
}

public HttpClient Create(string name)
{
    var client = _httpClientFactory.CreateClient(name);

    client.DefaultRequestHeaders.Add("X-Api-Key", configuration["App:ApiKey"]);

    return client;
}

}

but I don't know how to get RemoteService Type and name in here so I could conditionally add apikey header and read apikey from something like this :

    if (x.GetType().IsAssignableTo(IInternalApiService))
    {
        client.DefaultRequestHeaders.Add("X-Api-Key", configuration[$"RemoteServiceApiKeys:{nameof(x)}"]);

    }
maliming commented 2 years ago

I think the DynamicHttpProxyInterceptorClientProxy<IInternalApiService> will works.

[ExposeServices(typeof(DynamicHttpProxyInterceptorClientProxy<IInternalApiService>))]
class MyDynamicHttpProxyInterceptorClientProxy : DynamicHttpProxyInterceptorClientProxy<IInternalApiService>

override AddHeaders()
RezaPouya commented 2 years ago

It didn't work ...

maliming commented 2 years ago

Can you share a project?

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.