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.
| Parametr | Popis | Výchozí hodnota |
|---|---|---|
| httpClient.default.timeout | Timeout pro všechny akce v ms. | 60 sec |
| httpClient.default.trackContents | Zapnutí logování obsahu requestů. | false vypnuto |
| httpClient.default.connectionTimeout | Timeout pro vytvoření spojení v ms. | 60 sec |
| httpClient.default.socketTimeout | Timeout mezi přijatými pakety v ms. | 60 sec |
| httpClient.default.connectionRequestTimeout | Timeout pro spojení z connection manageru v ms. | 60 sec |
| httpClient.default.connectionTimeToLive | Maximální doba po kterou může být otevřené spojení (connection) drženo v connection poolu. | -1 (neomezená) |
| httpClient.default.connectionTimeToLiveTimeUnit | TimeUnit pro parametr connectionTimeToLive. | MILLISECONDS |
| httpClient.default.maxConnPerRoute | Maximální počet connection pro každou route nebo cílového hostitele. | 2 |
| httpClient.default.maxConnTotal | Maximální počet connection v poolu. | 20 |
| httpClient.default.proxy.hostname | Adresa proxy serveru. | proxy vypnuta |
| httpClient.default.proxy.port | Port proxy serveru. | vybere system |
| httpClient.default.auth.hostname | Autentikovaná doména. | autentikace na všechny domény |
| httpClient.default.auth.port | Autentikovaný port. | authentikace na všechny porty |
| httpClient.default.auth.username | Uživatelské jméno pro autentikaci. | autentikace vypnuta |
| httpClient.default.auth.password | Heslo pro autentikaci. | autentikace vypnuta |
| httpClient.default.auth.preemptiveAuthentication | Pří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:
<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:
| Parametr | Popis | Výchozí hodnota |
|---|---|---|
| name | Název konfigurace na který se odkazuje při získávání klienta. | povinné |
| trackContents | Zapnutí logování obsahu requestů. | false vypnuto |
| timeout | Timeout pro všechny akce v ms. | 60 sec |
| connectionTimeout | Timeout pro vytvoření spojení. | hodnota timeout |
| socketTimeout | Timeout mezi přijatými pakety. | hodnota timeout |
| connectionRequestTimeout | Timeout pro spojení z connection manageru. | hodnota timeout |
| connectionTimeToLive | Maximální doba po kterou může být otevřené spojení (connection) drženo v connection poolu. | -1 (neomezená) |
| connectionTimeToLiveTimeUnit | TimeUnit pro parametr connectionTimeToLive. | MILLISECONDS |
| maxConnPerRoute | Maximální počet connection pro každou route nebo cílového hostitele. | 2 |
| maxConnTotal | Maximální počet connection v poolu. | 20 |
| cookieManagement | Povolení zpracování cookies. | true zapnuto |
| followRedirects | Povolení zpracování přesměrování. | true zapnuto |
| maxRedirects | Maximální počet přesměrování zpracovaných v řadě. | 4 |
| userAgent | Hodnota identifikace http klienta | výchozí dle implementace klienta |
| retryCount | Hodnota 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:
| Parametr | Popis | Výchozí hodnota |
|---|---|---|
| hostname | Adresa proxy serveru. | povinný parametr |
| port | Port 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:
| Parametr | Popis | Výchozí hodnota |
|---|---|---|
| hostname | Autentikovaná doména. | autentikace na všechny domény |
| port | Autentikovaný port. | authentikace na všechny porty |
| username | Uživatelské jméno pro autentikaci. | povinný parametr |
| password | Heslo pro autentikaci. | povinný parametr |
| preemptiveAuthentication | Pří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:
| Parametr | Popis | Výchozí hodnota |
|---|---|---|
| hostname | Adresa pro které mapování platí. | povinný parametr |
| from | Zdrojová hodnota portu. | povinný parametr |
| to | Cí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:
| Parametr | Popis | Výchozí hodnota |
|---|---|---|
| hostname | Adresa pro které mapování platí. | povinný parametr |
| from | Zdrojová hodnota portu. | povinný parametr |
| to | Cí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.
<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
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:
@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
@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.ApacheHttpClientFactoryBeanvytváří instanciorg.apache.http.client.HttpClient - Google HttpRequestFactory -
com.fg.httpclient.service.GoogleHttpRequestFactoryFactoryBeanvytváří instancicom.google.api.client.http.HttpRequestFactory - Google HttpTransport -
com.fg.httpclient.service.GoogleHttpTransportFactoryBeanvytváří instancicom.google.api.client.http.HttpTransport - Spring ClientHttpRequestFactory -
com.fg.httpclient.service.SpringClientHttpRequestFactoryFactoryBeanvytváří instanciorg.springframework.http.client.ClientHttpRequestFactory - Spring RestTemplate -
com.fg.httpclient.service.SpringRestTemplateFactoryBeanvytváří instanciorg.springframework.web.client.RestTemplate
Dědičnost nastavení klientů
Volání HttpClientProvider.getXXXHttpClient("myModule") vrátí:
- klienta dle konfigurace
httpConnectionv rámciHttpClientCustomizationModule - 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á).
<!-- 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:
I/O exception (org.apache.http.NoHttpResponseException) caught when processing request to {s}->https://127.11.16.1:443: The target server failed to respondChyba 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
- Edee http client - http klient s jednoduchým použitím
