Edee.one · Dokumentace

HTTP Client

Tato knihovna se skládá z modulů:

  • Http Client System Module - základní systémový modul
  • Http Client Customization Module - modul umožňující komplikovanější konfigurace HTTP klientů

Konfigurace

Oba moduly mají z důvodu různých typů i různé možnosti konfigurace.

Http Client System Module

Tento modul lze konfigurovat pouze parametry v .properties souborech. Protože se jedná o systémový modul, nemá nikde XML konfiguraci.

ParametrPopisVýchozí hodnota
httpClient.default.timeoutTimeout pro všechny akce v ms.60 sec
httpClient.default.trackContentsZapnutí logování obsahu requestů.false vypnuto
httpClient.default.connectionTimeoutTimeout pro vytvoření spojení v ms.60 sec
httpClient.default.socketTimeoutTimeout mezi přijatými pakety v ms.60 sec
httpClient.default.connectionRequestTimeoutTimeout pro spojení z connection manageru v ms.60 sec
httpClient.default.connectionTimeToLiveMaximální doba po kterou může být otevřené spojení (connection) drženo v connection poolu.-1 (neomezená)
httpClient.default.connectionTimeToLiveTimeUnitTimeUnit pro parametr connectionTimeToLive.MILLISECONDS
httpClient.default.maxConnPerRouteMaximální počet connection pro každou route nebo cílového hostitele.2
httpClient.default.maxConnTotalMaximální počet connection v poolu.20
httpClient.default.proxy.hostnameAdresa proxy serveru.proxy vypnuta
httpClient.default.proxy.portPort proxy serveru.vybere system
httpClient.default.auth.hostnameAutentikovaná doména.autentikace na všechny domény
httpClient.default.auth.portAutentikovaný port.authentikace na všechny porty
httpClient.default.auth.usernameUživatelské jméno pro autentikaci.autentikace vypnuta
httpClient.default.auth.passwordHeslo pro autentikaci.autentikace vypnuta
httpClient.default.auth.preemptiveAuthenticationPříznak pro odesílání autorizace i bez předchozí výzvy k přihlášenífalse vypnuto

Http Client Customization Module

Modul slouží pro pokročilejší nastavení HTTP klientů.

Umožňuje konfiguovat pojmenované klienty standardním způsobem v XML konfiguraci. Například takto:

xml
<httpclientcustomizationmodule>
    <httpConnection name="default">        <proxy hostname="test-proxy.cz" port="80"/>    </httpConnection>
    <httpConnection name="auth">        <auth hostname="auth-server.cz" username="username" password="pass123"/>    </httpConnection>
    <httpConnection name="proxy">        <proxy hostname="other-proxy.cz" port="8080"/>    </httpConnection>
    <httpConnection name="mapping">        <dns>            <hostMapping from="www.my-url.com" to="internal-infrastructure-url"/>        </dns>        <port>            <portMapping hostname="www.my-url.com" from="80" to="8888"/>            <portMapping hostname="www.my-url.com" from="443" to="8889"/>        </port>    </httpConnection>
    <httpConnection name="timeout" timeout="30000"/>
    <httpConnection name="basic"/>
</httpclientcustomizationmodule>

Konfigurace je složena z tagů httpConnection, ty mají následující parametry:

ParametrPopisVýchozí hodnota
nameNázev konfigurace na který se odkazuje při získávání klienta.povinné
trackContentsZapnutí logování obsahu requestů.false vypnuto
timeoutTimeout pro všechny akce v ms.60 sec
connectionTimeoutTimeout pro vytvoření spojení.hodnota timeout
socketTimeoutTimeout mezi přijatými pakety.hodnota timeout
connectionRequestTimeoutTimeout pro spojení z connection manageru.hodnota timeout
connectionTimeToLiveMaximální doba po kterou může být otevřené spojení (connection) drženo v connection poolu.-1 (neomezená)
connectionTimeToLiveTimeUnitTimeUnit pro parametr connectionTimeToLive.MILLISECONDS
maxConnPerRouteMaximální počet connection pro každou route nebo cílového hostitele.2
maxConnTotalMaximální počet connection v poolu.20
cookieManagementPovolení zpracování cookies.true zapnuto
followRedirectsPovolení zpracování přesměrování.true zapnuto
maxRedirectsMaximální počet přesměrování zpracovaných v řadě.4
userAgentHodnota identifikace http klientavýchozí dle implementace klienta
retryCountHodnota pro opakování neúspěšného spojení - pokud je definováno použije se výchozí "retry handler"vypnuto

Pokud má parametr name hodnotu default je jím přenastavena konfigurace standardního klienta definovaná v systémovém modulu.

Každá konfigurace spojení může obsahovat jednu konfiguraci proxy:

ParametrPopisVýchozí hodnota
hostnameAdresa proxy serveru.povinný parametr
portPort proxy serveru.vybere system

Dále je u každého spojení možné definovat i více autentikačních konfigurací pro různé rozsahy domén či portů, a to pomocí tagu auth:

ParametrPopisVýchozí hodnota
hostnameAutentikovaná doména.autentikace na všechny domény
portAutentikovaný port.authentikace na všechny porty
usernameUživatelské jméno pro autentikaci.povinný parametr
passwordHeslo pro autentikaci.povinný parametr
preemptiveAuthenticationPříznak pro odesílání autorizace i bez předchozí výzvy k přihlášenífalse - vypnuto

Nastavené httpConnectiony nedědí vlastnosti HttpClientSystemModulu.

Každá konfigurace spojení může obsahovat jednu konfiguraci dns uvnitř pak jedno nebo více nastavení pro hostMapping:

ParametrPopisVýchozí hodnota
hostnameAdresa pro které mapování platí.povinný parametr
fromZdrojová hodnota portu.povinný parametr
toCílová přemapovaná hodnota.povinný parametr

Každá konfigurace spojení může obsahovat jednu konfiguraci port uvnitř pak jedno nebo více nastavení pro portMapping:

ParametrPopisVýchozí hodnota
hostnameAdresa pro které mapování platí.povinný parametr
fromZdrojová hodnota portu.povinný parametr
toCílová přemapovaná hodnota.povinný parametr

Modul s podporou konfigurace http clienta

Každý modul, který používá http klienta lze upravit, aby konfigurace těchti klientů šla modifikovat přímo v konfiguraci modulu. Konfigurace se pak vkládá do elementu httpClient. Konfigurace by pak měla obsahovat pouze nastavení platné pro daný modul.

xml
<fulltextmodule>    <httpClient>        <httpConnection name="fulltext">            <dns>                <hostMapping from="${fulltext.host.virtual}" to="${fulltext.host.name}"/>            </dns>            <auth preemptiveAuthentication="true" hostname="${fulltext.host.virtual}" username="${fulltext.host.username}" password="${fulltext.host.password}"/>        </httpConnection>    </httpClient></fulltextmodule>

Doplnění podpory vlastní konfigurace do modulu

Probíhá pomocí HttpClientConfigurationLoader v metodě setupModuleBeforeSpringInitialization

java
class MyModule extends CpsSpringModuleAbstract {    @Override    public void setupModuleBeforeSpringInitialization(Map<String,Object> params) {        // allow http client configuration        HttpClientConfigurationLoader.configureHttpClient(getModuleSupport());    }}

Získání http klienta

1. Pomocí HttpClientProvider

Modul poskytuje provider com.fg.httpclient.service.HttpClientProvider s veřejným rozhraním pro získání různých implementací http klienta.

Jsou podporovány:

  • Edee http client - com.fg.httpclient.model.EdeeHttpClient
  • Apache HttpClient v4 - org.apache.http.client.HttpClient
  • Google HTTP Client Library - com.google.api.client.http.HttpTransport, com.google.api.client.http.HttpRequestFactory
  • Spring Framework - org.springframework.web.client.RestTemplate, org.springframework.http.client.ClientHttpRequestFactory

Provider vrácí klienta pro danou konfiguraci určenou názvem, který odpovídá httpConnection#name. Opakované volání se stejným názvem vrací stejnou instanci klienta.

V případě, že konfigurace není zaregistrována v CentralHttpClientConfigurationManager, je klient vytvořen s výchozí konfigurací.

Příklad:

java
@Autowiredprivate final HttpClientProvider httpClientProvider;
private HttpClient createHttpClient() {    return httpClientProvider.getApacheHttpClient("myModule");}

Vlastní výchozí konfigurace

Vhodnější je spoléhat na výchozí nastavení a možnost jejího přenastavení, ale nic nebrání aplikační konfiguraci

java
@Autowiredprivate final CentralHttpClientConfigurationManager centralHttpClientConfigurationManager;
private void prepareConfiguration(String connectionName) {    if(centralHttpClientConfigurationManager.getHttpConnectionConfiguration(connectionName)==null) {        HttpConnectionConfiguration httpConnection=new HttpConnectionConfiguration();        httpConnection.setName(connectionName);        AuthenticationConfiguration authentication=new AuthenticationConfiguration();        authentication.setCredentials(new Credentials("userName","apiKey"));        httpConnection.addAuthentication(authentication);        centralHttpClientConfigurationManager.addHttpConnectionConfiguration(httpConnection);        }    }

2. Pomocí Factory Beany ve spring-contextu.

Knihovna poskytuje sjednocenou konfiguraci pro různé druhy implementací HTTP klienta. Instance jednotlivých implementací lze v modulech vytvářet pomocí Factory Bean.

Vždy je vhodné použít vlastní název pomocí atributu httpConnectionName. To umožní nezávisle konfigurovat nastavení klienta pomocí Http Client Customization Module.

Knihovna obsahuje následující Factory Beany:

  • Apache HttpClient - com.fg.httpclient.service.ApacheHttpClientFactoryBean vytváří instanci org.apache.http.client.HttpClient
  • Google HttpRequestFactory - com.fg.httpclient.service.GoogleHttpRequestFactoryFactoryBean vytváří instanci com.google.api.client.http.HttpRequestFactory
  • Google HttpTransport - com.fg.httpclient.service.GoogleHttpTransportFactoryBean vytváří instanci com.google.api.client.http.HttpTransport
  • Spring ClientHttpRequestFactory - com.fg.httpclient.service.SpringClientHttpRequestFactoryFactoryBean vytváří instanci org.springframework.http.client.ClientHttpRequestFactory
  • Spring RestTemplate - com.fg.httpclient.service.SpringRestTemplateFactoryBean vytváří instanci org.springframework.web.client.RestTemplate

Dědičnost nastavení klientů

Volání HttpClientProvider.getXXXHttpClient("myModule") vrátí:

  • klienta dle konfigurace httpConnection v rámci HttpClientCustomizationModule
  • pokud konfigurace neexistuje, pak klienta s výchozím nastavením HttpClientSystemModulu

Pokud vám některé z nastavení HttpClientSystemModulu nevyhovuje (například proxy), jednoduše si do HttpClientCustomizationModulu zaveďte vlastní httpConnection s vlastním nastavením.

Test podpora

V testech lze používat HttpClientProvider vytvořený pomocí com.fg.httpclient.test.HttpClientProviderMockFactoryBean

Pro EdeeHttpClient je připravena specifická mock podpora.

Monitoring

Všechny beany vytvořené pomocí Factory Bean jsou automaticky monitorované. Informace o requestech prováděných pomocí nich jsou jednak ukládána do in memory implementace com.fg.httpclient.monitoring.InMemoryHttpClientMonitoringManager, a jednak vypisována do logu. Vypisování neúspěšných requestů má úroveň logování error, zatímco úspěšné requesty se logují na úrovni debug.

Diagnostika v edee

V sekci diagnostika lze zobrazit statistiky - ty se vypočítávají za posledních 30 min, maximálně však za posledních 1000 requestů. Stejně je dostupný seznam posledních http požadavků.

Od verze Edee 9.1.0 je diagnostika součástí Edee UI a níže uvedený modul není nutné specifikovat (je doporučeno ho odstranit, nic nedělá).

xml
<!-- odstranit, od v9.1. není potřeba --><httpclientviewermodule>    <gui ramJetModuleName="edeeui" parentSection="edee" admin="true" defaultSetup="true"/></httpclientviewermodule>

Problémy, které mohou nastat a jejich řešení

V logu aplikace se může objevit následující chyba:

kód
I/O exception (org.apache.http.NoHttpResponseException) caught when processing request to {s}->https://127.11.16.1:443: The target server failed to respond

Chyba samozřejmě může znamenat, že opravdu došlo k situaci, kdy byl zavolán cílový server, který ale nevrátil odpověď. To se může stát, pokud by se požadavek trefil do restartu, nebo by po provedení požadavku vypadla komunikace a je třeba to ověřit. Nicméně pokud se chyba vyskytuje často, pak to pravděpodobně ukazuje na jiný problém. Connection pooling si totiž drží connection v podstatě neomezeně dlouhou dobu, ale cílový server toto nepodporuje a connections po určité době sám uzavírá. Do poolu se ale tato informace nedostane, takže se HTTP manager pokusí provést komunikaci na connection, která je ale už neplatná (stale connection). Uzavírání connections se běžně děje na našich serverech, kde je toto nakonfigurován v HAProxy.

Jak tento problém řešit? Jednou z možností je v poolingu nastavit parametr connectionTimeToLive, kterým se omezí doba platnosti connection v poolu. Hodnotu je vždy nutné nastavit po diskuzi s TA (či externím dodavatelem) a obecně by asi měla být nastavena vždy.

Další možností, která by měla být v poolingu standardně zapnutá, je využití ConnectionKeepAliveStrategy, kdy si aplikace přečte z response hlavičku keep-alive a hodnotu timeout použije pro nastavení idleDuration connection. Tím by měla být nastavená platnost connection, pokud se nepoužívá. Nicméně pokud se používá, tak dle dokumentace dochází k tomu, že se platnost nastaví vždy po zpracování každé odpovědi znovu a parametr max z keep-alive hlavičky je ignorován (alespoň aktuálně tomu tak je). Tj. i tak je asi vhodné nastavit i connectionTimeToLive, aby se connection čas od času obnovila.

Pokud výše uvedené nepomůže (např. proto, že cílový server je nestabilní/často přetížený), pak je možné ještě na poolingu zapnout RetryHandler viz parametr retryCount a automaticky opakovat požadavky. Jen pozor, pokud je výsledkem požadavku to, že na cílovém serveru přibudou nějaká data, pak se může stát, že díky opakovanému požadavku tam ta data vzniknou vícekrát.

Další možnosti

Makro akce

  • HTTP Request akce - slouží pro automatizované volání HTTP requestů s možností ukládání odpovědí do souborů

Edee http client