com.oracle.bmc.http.client.jersey.JerseyHttpRequest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of oci-java-sdk-common-httpclient-jersey Show documentation
Show all versions of oci-java-sdk-common-httpclient-jersey Show documentation
This project contains the HTTP client jersey implementation of the SDK used for Oracle Cloud Infrastructure
The newest version!
/**
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
*/
package com.oracle.bmc.http.client.jersey;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.oracle.bmc.http.client.HttpRequest;
import com.oracle.bmc.http.client.HttpResponse;
import com.oracle.bmc.http.client.Method;
import com.oracle.bmc.http.client.RequestInterceptor;
import com.oracle.bmc.http.client.io.DuplicatableInputStream;
import com.oracle.bmc.http.client.jersey.internal.ApacheDuplicatableInputStreamEntity;
import com.oracle.bmc.http.client.jersey.internal.ApacheInputStreamEntity;
import com.oracle.bmc.http.client.jersey.io.internal.LengthLimitedInputStream;
import com.oracle.bmc.serialization.jackson.JacksonSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.client.CompletionStageRxInvoker;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Variant;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Executor;
final class JerseyHttpRequest implements HttpRequest {
/**
* The boolean value indicating if extra logs related to operations that return streams are
* enabled/disabled. Disabling this will disable warnings to close the streams, logs about
* wrapping response stream in an auto-closeble stream. Default is true.
*/
static final boolean isExtraStreamLogsEnabled = isExtraStreamLogsEnabledViaSystemProperty();
private static boolean isExtraStreamLogsEnabledViaSystemProperty() {
String streamLogsEnabledString =
System.getProperty("oci.javasdk.extra.stream.logs.enabled");
if (streamLogsEnabledString != null && !streamLogsEnabledString.isEmpty()) {
String trimmedValue = streamLogsEnabledString.trim();
if ("false".equalsIgnoreCase(trimmedValue)) {
return false;
}
}
return true;
}
private static final Logger LOG = LoggerFactory.getLogger(JerseyHttpRequest.class);
private final JerseyHttpClient client;
private final Method method;
private Object processedBody;
private MediaType requestBodyType;
private Locale requestBodyLanguage;
private String requestBodyEncoding;
private WebTarget webTarget;
private final MultivaluedMap headers;
private final Map attributes;
JerseyHttpRequest(JerseyHttpClient client, Method method, WebTarget webTarget) {
this.client = client;
this.method = method;
this.webTarget = webTarget;
this.attributes = new HashMap<>();
this.headers = new MultivaluedHashMap();
}
private JerseyHttpRequest(JerseyHttpRequest from) {
this.client = from.client;
this.method = from.method;
this.processedBody = from.processedBody;
this.requestBodyType = from.requestBodyType;
this.requestBodyLanguage = from.requestBodyLanguage;
this.requestBodyEncoding = from.requestBodyEncoding;
this.webTarget = from.webTarget;
this.headers = new MultivaluedHashMap(from.headers);
this.attributes = new HashMap<>(from.attributes);
}
@Override
public Method method() {
return method;
}
private void logAvailable(InputStream body) {
if (isExtraStreamLogsEnabled) {
try {
final int bytesAvailable = body.available();
if (bytesAvailable == 0) {
LOG.warn(
"Stream size to upload is 0 bytes, "
+ "this could potentially lead to data corruption. If this is not intended, "
+ "please make sure all the OCI SDK dependencies point to the same version");
}
} catch (IOException e) {
LOG.warn(
"Error calling available on the stream to get the available number of bytes");
}
}
}
@Override
public HttpRequest body(Object body) {
if (body instanceof String) {
processedBody = body;
} else if (body instanceof InputStream) {
logAvailable((InputStream) body);
processedBody = body;
} else if (body == null) {
processedBody = "";
} else {
try {
processedBody = JacksonSerializer.getDefaultObjectMapper().writeValueAsString(body);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Unable to process JSON body", e);
}
}
return this;
}
@Override
public HttpRequest body(InputStream body, long contentLength) {
logAvailable(body);
InputStream limitedStream = new LengthLimitedInputStream(body, contentLength);
if (client.isApacheNonBufferingClient && contentLength > 0) {
// Customization for providing Apache HTTP Entity instead of InputStream. This is
// required to avoid
// buffering all the data in memory by Jersey Apache Connector. Create the HTTP entity
// only when a
// content length value can be retrieved from the request.
if (body instanceof DuplicatableInputStream) {
processedBody =
new ApacheDuplicatableInputStreamEntity(
(DuplicatableInputStream) body, contentLength);
} else {
processedBody = new ApacheInputStreamEntity(limitedStream, contentLength);
}
} else {
processedBody = body;
}
return this;
}
@Override
public Object body() {
return processedBody;
}
@Override
public HttpRequest appendPathPart(String encodedPathPart) {
webTarget = webTarget.path(encodedPathPart);
return this;
}
@Override
public HttpRequest query(String name, String value) {
webTarget = webTarget.queryParam(name, value);
return this;
}
@Override
public URI uri() {
return webTarget.getUri();
}
@Override
public HttpRequest header(String name, String value) {
headers.add(name, value);
if (name.equalsIgnoreCase("Content-Type")) {
requestBodyType = MediaType.valueOf(value);
}
if (name.equalsIgnoreCase("Content-Language")) {
requestBodyLanguage = Locale.forLanguageTag(value);
}
if (name.equalsIgnoreCase("Content-Encoding")) {
requestBodyEncoding = value;
}
return this;
}
@Override
public Map> headers() {
return headers;
}
@Override
public Object attribute(String name) {
return attributes.get(name);
}
@Override
public HttpRequest removeAttribute(String name) {
attributes.remove(name);
return this;
}
@Override
public HttpRequest attribute(String name, Object value) {
attributes.put(name, value);
return this;
}
@Override
public HttpRequest offloadExecutor(Executor executor) {
// can't offload for jersey
return this;
}
@Override
public HttpRequest copy() {
return new JerseyHttpRequest(this);
}
@Override
public void discard() {}
@Override
public CompletionStage execute() {
for (RequestInterceptor interceptor : client.requestInterceptors) {
interceptor.intercept(this);
}
CompletionStageRxInvoker invoker =
webTarget.request().headers(new MultivaluedHashMap(headers)).rx();
CompletionStage stage;
if (processedBody == null) {
stage = invoker.method(method.name());
} else {
Variant variant =
new Variant(requestBodyType, requestBodyLanguage, requestBodyEncoding);
stage = invoker.method(method.name(), Entity.entity(processedBody, variant));
}
return stage.thenApply(JerseyHttpResponse::new);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy