Skip to content

Commit

Permalink
Startpunkt for felles http klient (#1169)
Browse files Browse the repository at this point in the history
* Startpunkt for felles http klient

* Eksempelklienter

* Litt omarbeiding for testbarhet

* Fjerner en del volatile som er beskyttet av synchronized
  • Loading branch information
jolarsen authored Sep 5, 2022
1 parent 8e167ca commit c696b4c
Show file tree
Hide file tree
Showing 33 changed files with 1,707 additions and 93 deletions.
26 changes: 26 additions & 0 deletions felles/klient/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>felles</artifactId>
<groupId>no.nav.foreldrepenger.felles</groupId>
<version>0.0.0-SNAPSHOT</version>
</parent>

<artifactId>felles-klient</artifactId>

<dependencies>
<dependency>
<groupId>no.nav.foreldrepenger.felles</groupId>
<artifactId>felles-feil</artifactId>
</dependency>
<dependency>
<groupId>no.nav.foreldrepenger.felles</groupId>
<artifactId>felles-log</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package no.nav.vedtak.klient.http;

import java.io.IOException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Optional;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import no.nav.vedtak.exception.IntegrasjonException;

public final class DefaultHttpKlient {

private static final Logger LOG = LoggerFactory.getLogger(DefaultHttpKlient.class);

private static DefaultHttpKlient CLIENT;

private final HttpClient httpClient;

private DefaultHttpKlient() {
this.httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(15)).proxy(HttpClient.Builder.NO_PROXY).build();
}

public static synchronized DefaultHttpKlient client() {
var inst= CLIENT;
if (inst == null) {
inst = new DefaultHttpKlient();
CLIENT = inst;
}
return inst;
}

public String send(HttpRequest request) {
return ResponseHandler.handleResponse(doSendExpectStringRetry(request), request.uri(), Set.of());
}

public String send(HttpRequest request, Set<Integer> permits) {
return ResponseHandler.handleResponse(doSendExpectStringRetry(request), request.uri(), permits);
}

public Optional<byte[]> sendHandleResponse(HttpRequest request) {
return Optional.ofNullable(ResponseHandler.handleResponse(doSendExpectBytearrayRetry(request), request.uri(), Set.of()));
}

public HttpResponse<String> sendNoResponseHandler(HttpRequest request) {
return doSendExpectStringRetry(request);
}

private HttpResponse<byte[]> doSendExpectBytearrayRetry(HttpRequest request) {
try {
return doSendExpectBytearray(request);
} catch (IntegrasjonException e) {
LOG.info("F-157390 IntegrasjonException ved første kall til endepunkt {}", request.uri(), e);
}
return doSendExpectBytearray(request);
}

private HttpResponse<String> doSendExpectStringRetry(HttpRequest request) {
try {
return doSendExpectString(request);
} catch (IntegrasjonException e) {
LOG.info("F-157390 IntegrasjonException ved første kall til endepunkt {}", request.uri(), e);
}
return doSendExpectString(request);
}

private HttpResponse<byte[]> doSendExpectBytearray(HttpRequest request) {
try {
return httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray());
} catch (IOException e) {
throw new IntegrasjonException("F-157391", "Uventet IO-exception mot endepunkt", e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IntegrasjonException("F-157392", "InterruptedException ved kall mot endepunkt", e);
}
}

private HttpResponse<String> doSendExpectString(HttpRequest request) {
try {
return httpClient.send(request, HttpResponse.BodyHandlers.ofString());
} catch (IOException e) {
throw new IntegrasjonException("F-157391", "Uventet IO-exception mot endepunkt", e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IntegrasjonException("F-157392", "InterruptedException ved kall mot endepunkt", e);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package no.nav.vedtak.klient.http;

import java.net.http.HttpRequest;
import java.time.Duration;
import java.util.function.Supplier;

import no.nav.vedtak.log.mdc.MDCOperations;

public final class DefaultRequest {

private static final String HEADER_NAV_CONSUMER_ID = "Nav-Consumer-Id";

private static final String AUTHORIZATION = "Authorization";
private static final String BASIC_AUTH_HEADER_PREFIX = "Basic ";

private static final String CONTENT_TYPE = "Content-Type";
private static final String APPLICATION_FORM_ENCODED = "application/x-www-form-urlencoded";

private static final String HEADER_NAV_CALLID = "Nav-Callid";
private static final String HEADER_NAV_CALL_ID = "nav-call-id";

private DefaultRequest() {
// NOSONAR
}

public static HttpRequest.Builder builder() {
return HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(10))
.header(HEADER_NAV_CALLID, MDCOperations.getCallId())
.header(HEADER_NAV_CALL_ID, MDCOperations.getCallId());
}

public static HttpRequest.Builder builderForBasicAuth(Supplier<String> authContent) {
return builder()
.header(CONTENT_TYPE, APPLICATION_FORM_ENCODED)
.header(AUTHORIZATION, BASIC_AUTH_HEADER_PREFIX + authContent.get());
}

public static HttpRequest.Builder builderForBasicAuth(Supplier<String> authContent, Supplier<String> consumerId) {
return builder()
.header(HEADER_NAV_CONSUMER_ID, consumerId.get())
.header(CONTENT_TYPE, APPLICATION_FORM_ENCODED)
.header(AUTHORIZATION, BASIC_AUTH_HEADER_PREFIX + authContent.get());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package no.nav.vedtak.klient.http;

import java.net.HttpURLConnection;
import java.net.URI;
import java.net.http.HttpResponse;
import java.util.Set;

import no.nav.vedtak.exception.IntegrasjonException;
import no.nav.vedtak.exception.ManglerTilgangException;

final class ResponseHandler {

private ResponseHandler() {
// NOSONAR
}

static <W> W handleResponse(final HttpResponse<W> response, URI endpoint, Set<Integer> permits) {
int status = response.statusCode();
if (status == HttpURLConnection.HTTP_NO_CONTENT) {
return null;
}
if ((status >= HttpURLConnection.HTTP_OK && status < HttpURLConnection.HTTP_MULT_CHOICE) || permits.contains(status)) {
return response.body();
}
if (status == HttpURLConnection.HTTP_FORBIDDEN) {
throw new ManglerTilgangException("F-468816", "Feilet mot " + endpoint);
}
throw new IntegrasjonException("F-468817", String.format("Uventet respons %s fra %s", status, endpoint));
}

}
6 changes: 6 additions & 0 deletions felles/klient/src/main/resources/META-INF/beans.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
version="2.0"
bean-discovery-mode="annotated">
</beans>
4 changes: 4 additions & 0 deletions felles/oidc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
<groupId>no.nav.foreldrepenger.felles</groupId>
<artifactId>felles-mapper</artifactId>
</dependency>
<dependency>
<groupId>no.nav.foreldrepenger.felles</groupId>
<artifactId>felles-klient</artifactId>
</dependency>
<dependency>
<groupId>no.nav.foreldrepenger</groupId>
<artifactId>konfig</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public final class OidcProviderConfig {
private final Set<OpenIDConfiguration> providers;
private final Map<String, OpenIDConfiguration> issuers;

private static volatile OidcProviderConfig instance; // NOSONAR
private static OidcProviderConfig instance;

private OidcProviderConfig() {
this(init());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class AzureSystemTokenKlient {
private static final Environment ENV = Environment.current();
private static final Logger LOG = LoggerFactory.getLogger(AzureSystemTokenKlient.class);

private static volatile AzureSystemTokenKlient INSTANCE; // NOSONAR
private static AzureSystemTokenKlient INSTANCE;

private final URI tokenEndpoint;
private final String clientId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public final class TokenXExchangeKlient {

private static final Logger LOG = LoggerFactory.getLogger(TokenXExchangeKlient.class);

private static volatile TokenXExchangeKlient INSTANCE; // NOSONAR
private static TokenXExchangeKlient INSTANCE;

private final Optional<OpenIDConfiguration> configuration;
private final String cluster;
Expand Down
6 changes: 6 additions & 0 deletions felles/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<module>log</module>
<module>util</module>
<module>mapper</module>
<module>klient</module>
<module>db</module>
<module>abac</module>
<module>xmlutils</module>
Expand Down Expand Up @@ -68,6 +69,11 @@
<artifactId>felles-mapper</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>no.nav.foreldrepenger.felles</groupId>
<artifactId>felles-klient</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>no.nav.foreldrepenger.felles</groupId>
<artifactId>felles-oidc</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

public class OidcTokenValidatorConfig {

private static volatile OidcTokenValidatorConfig instance; // NOSONAR
private static OidcTokenValidatorConfig instance;
private final Map<OpenIDProvider, OidcTokenValidator> validators;

private OidcTokenValidatorConfig() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

final class TokenXAssertionGenerator {

private static volatile TokenXAssertionGenerator INSTANCE; // NOSONAR
private static TokenXAssertionGenerator INSTANCE;

private final Optional<OpenIDConfiguration> configuration;
private final RSAKey privateKey;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package no.nav.vedtak.felles.integrasjon.arbeidsfordeling.rest;

import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

import no.nav.foreldrepenger.konfig.KonfigVerdi;
import no.nav.vedtak.exception.IntegrasjonException;
import no.nav.vedtak.felles.integrasjon.rest.NativeKlient;
import no.nav.vedtak.felles.integrasjon.rest.RestKlient;
import no.nav.vedtak.felles.integrasjon.rest.RestRequest;
import no.nav.vedtak.sikkerhet.oidc.token.SikkerhetContext;

@NativeKlient
@ApplicationScoped
public class ArbeidsfordelingNativeRestKlient implements Arbeidsfordeling {

private static final String DEFAULT_URI = "https://app.adeo.no/norg2/api/v1/arbeidsfordeling/enheter";
private static final String BEST_MATCH = "/bestmatch";

private RestKlient restKlient;
private URI alleEnheterUri;
private URI besteEnhetUri;

@Inject
public ArbeidsfordelingNativeRestKlient(RestKlient restKlient,
@KonfigVerdi(value = "arbeidsfordeling.rs.url", defaultVerdi = DEFAULT_URI) URI uri) {
this.restKlient = restKlient;
this.alleEnheterUri = uri;
this.besteEnhetUri = URI.create(uri + BEST_MATCH);
}

ArbeidsfordelingNativeRestKlient() {
// CDI proxyable
}

@Override
public List<ArbeidsfordelingResponse> hentAlleAktiveEnheter(ArbeidsfordelingRequest request) {
return hentEnheterFor(request, alleEnheterUri);
}

@Override
public List<ArbeidsfordelingResponse> finnEnhet(ArbeidsfordelingRequest request) {
return hentEnheterFor(request, besteEnhetUri);
}

private List<ArbeidsfordelingResponse> hentEnheterFor(ArbeidsfordelingRequest request, URI uri) {
try {
var httpRequest = restKlient.request().builder(SikkerhetContext.BRUKER)
.uri(uri)
.POST(RestRequest.serialiser(request))
.build();
var respons = restKlient.send(httpRequest, ArbeidsfordelingResponse[].class);
return Arrays.stream(respons)
.filter(response -> "AKTIV".equalsIgnoreCase(response.status()))
.collect(Collectors.toList());
} catch (Exception e) {
throw new IntegrasjonException("F-016913", String.format("NORG2 arbeidsfordeling feil ved oppslag mot %s", uri), e);
}
}

}
Loading

0 comments on commit c696b4c

Please sign in to comment.