Skip to content

Commit

Permalink
[pinpoint-apm#9242] Add http client 5.x plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
jaehong-kim authored and BillionaireDY committed Dec 29, 2022
1 parent a989774 commit e80a2af
Show file tree
Hide file tree
Showing 37 changed files with 1,726 additions and 2 deletions.
43 changes: 43 additions & 0 deletions agent-testweb/httpclient5-plugin-testweb/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?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>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-agent-testweb</artifactId>
<version>2.5.0-SNAPSHOT</version>
</parent>

<artifactId>pinpoint-httpclient5-plugin-testweb</artifactId>

<packaging>jar</packaging>

<properties>
<pinpoint.agent.jvmargument>
${pinpoint.agent.default.jvmargument}
</pinpoint.agent.jvmargument>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.1.3</version>
</dependency>

</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
package com.pinpoint.test.plugin;

import org.apache.hc.client5.http.async.methods.*;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.*;
import org.apache.hc.core5.http.io.HttpClientResponseHandler;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicHttpRequest;
import org.apache.hc.core5.http.nio.support.BasicRequestProducer;
import org.apache.hc.core5.http.protocol.BasicHttpContext;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.support.BasicRequestBuilder;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.reactor.IOReactorConfig;
import org.apache.hc.core5.util.Timeout;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.nio.CharBuffer;
import java.util.concurrent.Future;

@RestController
public class HttpClient5PluginController {

@GetMapping("/")
public Mono<String> weclome() {
return Mono.just("Welcome");
}

@GetMapping("/client/get")
public String httpGet() throws Exception {
final CloseableHttpClient httpClient = HttpClients.createDefault();
final HttpGet httpGet = new HttpGet("http://httpbin.org/get");

final HttpClientResponseHandler<String> responseHandler = new HttpClientResponseHandler<String>() {
@Override
public String handleResponse(ClassicHttpResponse classicHttpResponse) throws HttpException, IOException {
final int status = classicHttpResponse.getCode();
if (status >= HttpStatus.SC_SUCCESS && status < HttpStatus.SC_REDIRECTION) {
final HttpEntity entity = classicHttpResponse.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
}

return null;
}
};

final String responseBody = httpClient.execute(httpGet, responseHandler);
return responseBody;
}

@GetMapping("/client/local")
public String clientLocal() throws Exception {
final CloseableHttpClient httpClient = HttpClients.createDefault();
final HttpGet httpGet = new HttpGet("http://localhost:18080/");

final HttpClientResponseHandler<String> responseHandler = new HttpClientResponseHandler<String>() {
@Override
public String handleResponse(ClassicHttpResponse classicHttpResponse) throws HttpException, IOException {
final int status = classicHttpResponse.getCode();
if (status >= HttpStatus.SC_SUCCESS && status < HttpStatus.SC_REDIRECTION) {
final HttpEntity entity = classicHttpResponse.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
}

return null;
}
};

final String responseBody = httpClient.execute(httpGet, responseHandler);
return responseBody;
}

@GetMapping("/client/thread")
public String threadExecution() throws Exception {
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(10);

CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
final String[] urisToGet = {"http://hc.apache.org", "http://hc.apache.org/httpcomponents-core-ga/", "http://hc.apache.org/httpcomponents-client-ga/"};
final GetThread[] threads = new GetThread[urisToGet.length];

for (int i = 0; i < threads.length; i++) {
final HttpGet httpGet = new HttpGet(urisToGet[i]);
threads[i] = new GetThread(httpClient, httpGet, i + 1);
}

for (final GetThread thread : threads) {
thread.start();
}

for (final GetThread thread : threads) {
thread.join();
}

return "OK";
}

@GetMapping("/client/async")
public String asyncFuture() throws Exception {
final IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setSoTimeout(Timeout.ofSeconds(5)).build();
final CloseableHttpAsyncClient client = HttpAsyncClients.custom().setIOReactorConfig(ioReactorConfig).build();
client.start();

final HttpHost target = new HttpHost("httpbin.org");
final String[] requestUris = new String[]{"/", "/ip", "/user-agent", "/headers"};

final SimpleHttpRequest request = SimpleRequestBuilder.get().setHttpHost(target).setPath("/").build();
final Future<SimpleHttpResponse> future = client.execute(SimpleRequestProducer.create(request), SimpleResponseConsumer.create(), new FutureCallback<SimpleHttpResponse>() {
@Override
public void completed(SimpleHttpResponse response) {
}

@Override
public void failed(Exception e) {
}

@Override
public void cancelled() {
}
});
future.get();

client.close(CloseMode.GRACEFUL);
return "OK";
}

@GetMapping("/client/stream")
public String clientStream() throws Exception {
final IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setSoTimeout(Timeout.ofSeconds(5)).build();
final CloseableHttpAsyncClient client = HttpAsyncClients.custom().setIOReactorConfig(ioReactorConfig).build();
client.start();

final HttpHost target = new HttpHost("httpbin.org");
final String[] requestUris = new String[]{"/", "/ip", "/user-agent", "/headers"};

final BasicHttpRequest request = BasicRequestBuilder.get().setHttpHost(target).setPath(requestUris[0]).build();
final Future<Void> future = client.execute(new BasicRequestProducer(request, null), new AbstractCharResponseConsumer<Void>() {
@Override
protected void start(HttpResponse response, ContentType contentType) throws HttpException, IOException {
}

@Override
protected Void buildResult() throws IOException {
return null;
}

@Override
protected int capacityIncrement() {
return Integer.MAX_VALUE;
}

@Override
protected void data(CharBuffer src, boolean endOfStream) throws IOException {
while (src.hasRemaining()) {
}
if (endOfStream) {
}
}

@Override
public void releaseResources() {

}
}, null);
future.get();

client.close(CloseMode.GRACEFUL);
return "OK";
}

@GetMapping("/client/minimal")
public String asyncMinimal() throws Exception {
final CloseableHttpAsyncClient client = HttpAsyncClients.createMinimal();
client.start();

final HttpHost target = new HttpHost("httpbin.org");

final SimpleHttpRequest request = SimpleRequestBuilder.get().setHttpHost(target).setPath("/").build();
final Future<SimpleHttpResponse> future = client.execute(SimpleRequestProducer.create(request), SimpleResponseConsumer.create(), new FutureCallback<SimpleHttpResponse>() {
@Override
public void completed(SimpleHttpResponse response) {
}

@Override
public void failed(Exception e) {
}

@Override
public void cancelled() {
}
});
future.get();

client.close(CloseMode.GRACEFUL);
return "OK";
}

@GetMapping("/client/cookie")
public String httpCookie() throws Exception {
final CloseableHttpClient httpClient = HttpClients.createDefault();
final HttpGet httpGet = new HttpGet("http://localhost");
httpGet.addHeader("Cookie", "COOKIE");

final HttpClientResponseHandler<String> responseHandler = new HttpClientResponseHandler<String>() {
@Override
public String handleResponse(ClassicHttpResponse classicHttpResponse) throws HttpException, IOException {
final int status = classicHttpResponse.getCode();
if (status >= HttpStatus.SC_SUCCESS && status < HttpStatus.SC_REDIRECTION) {
final HttpEntity entity = classicHttpResponse.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
}
return null;
}
};

final String responseBody = httpClient.execute(httpGet, responseHandler);

return responseBody;
}

@GetMapping("/client/entity")
public String httpEntity() throws Exception {
final CloseableHttpClient httpClient = HttpClients.createDefault();
final HttpPost httpPost = new HttpPost("http://localhost");
httpPost.setEntity(new StringEntity("foo-bar"));

final HttpClientResponseHandler<String> responseHandler = new HttpClientResponseHandler<String>() {
@Override
public String handleResponse(ClassicHttpResponse classicHttpResponse) throws HttpException, IOException {
final int status = classicHttpResponse.getCode();
if (status >= HttpStatus.SC_SUCCESS && status < HttpStatus.SC_REDIRECTION) {
final HttpEntity entity = classicHttpResponse.getEntity();
return entity != null ? EntityUtils.toString(entity) : null;
}
return null;
}
};

final String responseBody = httpClient.execute(httpPost, responseHandler);
return responseBody;
}


static class GetThread extends Thread {

private final CloseableHttpClient httpClient;
private final HttpContext context;
private final HttpGet httpget;
private final int id;

public GetThread(final CloseableHttpClient httpClient, final HttpGet httpget, final int id) {
this.httpClient = httpClient;
this.context = new BasicHttpContext();
this.httpget = httpget;
this.id = id;
}

/**
* Executes the GetMethod and prints some status information.
*/
@Override
public void run() {
try {
try (CloseableHttpResponse response = httpClient.execute(httpget, context)) {
// get the response body as an array of bytes
final HttpEntity entity = response.getEntity();
if (entity != null) {
final byte[] bytes = EntityUtils.toByteArray(entity);
}
}
} catch (final Exception e) {
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.pinpoint.test.plugin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HttpClient5PluginTestStarter {

public static void main(String[] args) {
SpringApplication.run(HttpClient5PluginTestStarter.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Defined in commandlineArgument of agent-test pom.xml

server:
port: 18080

logging:
level:
root: info

springdoc:
swagger-ui:
path: /
1 change: 1 addition & 0 deletions agent-testweb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
<module>redis-lettuce-plugin-testweb</module>
<module>jetty-plugin-testweb</module>
<module>spring-data-r2dbc-plugin-testweb</module>
<module>httpclient5-plugin-testweb</module>
</modules>

<dependencyManagement>
Expand Down
Loading

0 comments on commit e80a2af

Please sign in to comment.