Skip to content

Commit 7b2126a

Browse files
authored
Add clojure http clients (#124)
* Add Clojure Http Clients * Add Clojure Http Clients * Fix cij http * Removed duplication * Added tests * fix scan * Bumped jacoco * Added jacoco profile
1 parent 99069f7 commit 7b2126a

11 files changed

Lines changed: 277 additions & 3 deletions

File tree

.github/workflows/maven.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ jobs:
7373
uses: actions/setup-java@v5
7474
with:
7575
distribution: 'adopt'
76-
java-version: '25'
76+
java-version: '21'
7777
cache: 'maven'
7878

7979
- name: Build, test and quality scan
8080
env:
8181
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
82-
run: mvn clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.organization=hakky54 -Dsonar.host.url=https://sonarcloud.io -Dsonar.login="$SONAR_TOKEN" --no-transfer-progress
82+
run: mvn clean verify -Pjacoco org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.organization=hakky54 -Dsonar.host.url=https://sonarcloud.io -Dsonar.login="$SONAR_TOKEN" --no-transfer-progress

README.MD

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,11 @@ All client examples use the same base ssl configuration created within the [SSLC
415415
* Groovy with Java Net -> [Client Configuration & Example request](https://github.com/Hakky54/mutual-tls-ssl/blob/master/client/src/main/java/nl/altindag/client/service/GroovyJavaNetClientService.groovy)
416416
* [Hyper Poet](https://github.com/tambapps/hyperpoet) -> [Client Configuration & Example request](https://github.com/Hakky54/mutual-tls-ssl/blob/master/client/src/main/java/nl/altindag/client/service/HyperPoetService.groovy)
417417

418+
**Clojure**
419+
* [cj-http](https://github.com/dakrone/clj-http) -> [Client Configuration & Example request](https://github.com/Hakky54/mutual-tls-ssl/blob/master/client/src/main/java/nl/altindag/client/service/ClojureCljHttpClientService.clj)
420+
* JDK Http Client -> [Client Configuration & Example request](https://github.com/Hakky54/mutual-tls-ssl/blob/master/client/src/main/java/nl/altindag/client/service/ClojureJdkHttpClientService.clj)
421+
* Old JDK Http Client -> [Client Configuration & Example request](https://github.com/Hakky54/mutual-tls-ssl/blob/master/client/src/main/java/nl/altindag/client/service/ClojureHttpClientService.clj)
422+
418423
**Other**
419424

420425
This tutorial does not provide examples for the clients listed below, however it is proven to be working with the server provided in this tutorial. To guide you in the right direction you can convert the created java keystore files into pem files which in return can be used with one of the clients listed below. The following Gist page contains the commands to convert a Java keystore to a pem file: [Gist - Curl with Java KeyStore](https://gist.github.com/Hakky54/049299f0874fd4b870257c6458e0dcbd)

client/pom.xml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,15 @@
220220
<artifactId>hyperpoet-groovy</artifactId>
221221
</dependency>
222222

223+
<dependency>
224+
<groupId>org.clojure</groupId>
225+
<artifactId>clojure</artifactId>
226+
</dependency>
227+
<dependency>
228+
<groupId>clj-http</groupId>
229+
<artifactId>clj-http</artifactId>
230+
</dependency>
231+
223232
<!-- Utilities -->
224233
<dependency>
225234
<groupId>org.awaitility</groupId>
@@ -362,6 +371,12 @@
362371
<version>${version.gmavenplus-plugin}</version>
363372
</plugin>
364373

374+
<plugin>
375+
<groupId>com.theoryinpractise</groupId>
376+
<artifactId>clojure-maven-plugin</artifactId>
377+
<version>${version.clojure-maven-plugin}</version>
378+
</plugin>
379+
365380
<plugin>
366381
<groupId>org.apache.maven.plugins</groupId>
367382
<artifactId>maven-compiler-plugin</artifactId>
@@ -553,4 +568,23 @@
553568

554569
</profiles>
555570

571+
<repositories>
572+
<repository>
573+
<id>maven-central</id>
574+
<name>Maven Central Repository</name>
575+
<url>https://repo1.maven.org/maven2</url>
576+
<snapshots>
577+
<enabled>false</enabled>
578+
</snapshots>
579+
</repository>
580+
<repository>
581+
<id>clojars-central</id>
582+
<name>Clojars Repository</name>
583+
<url>https://repo.clojars.org/</url>
584+
<snapshots>
585+
<enabled>false</enabled>
586+
</snapshots>
587+
</repository>
588+
</repositories>
589+
556590
</project>

client/src/main/java/nl/altindag/client/ClientConfig.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package nl.altindag.client;
1717

18+
import clojure.java.api.Clojure;
19+
import clojure.lang.IFn;
1820
import com.github.mizosoft.methanol.Methanol;
1921
import com.google.api.client.http.HttpTransport;
2022
import com.google.api.client.http.javanet.NetHttpTransport;
@@ -33,6 +35,7 @@
3335
import jakarta.ws.rs.client.Client;
3436
import jakarta.ws.rs.client.ClientBuilder;
3537
import kong.unirest.Unirest;
38+
import nl.altindag.client.service.RequestService;
3639
import nl.altindag.ssl.SSLFactory;
3740
import nl.altindag.ssl.apache4.util.Apache4SslUtils;
3841
import nl.altindag.ssl.apache5.util.Apache5SslUtils;
@@ -310,4 +313,26 @@ public io.vertx.ext.web.client.WebClient vertxWebClient(SSLFactory sslFactory) {
310313
return io.vertx.ext.web.client.WebClient.create(Vertx.vertx(), clientOptions);
311314
}
312315

316+
@Bean
317+
public RequestService clojureHttpClientService(SSLFactory sslFactory) {
318+
return instantiateClojureRequestService("nl.altindag.client.service.ClojureHttpClientService", sslFactory);
319+
}
320+
321+
@Bean
322+
public RequestService clojureJdkHttpClientService(SSLFactory sslFactory) {
323+
return instantiateClojureRequestService("nl.altindag.client.service.ClojureJdkHttpClientService", sslFactory);
324+
}
325+
326+
@Bean
327+
public RequestService clojureCijHttpClientService(SSLFactory sslFactory) {
328+
return instantiateClojureRequestService("nl.altindag.client.service.ClojureCijHttpClientService", sslFactory);
329+
}
330+
331+
private RequestService instantiateClojureRequestService(String namespace, SSLFactory sslFactory) {
332+
IFn require = Clojure.var("clojure.core", "require");
333+
require.invoke(Clojure.read(namespace));
334+
IFn clojureHttpClientService = Clojure.var(namespace, "reify-request-service");
335+
return (RequestService) clojureHttpClientService.invoke(sslFactory);
336+
}
337+
313338
}

client/src/main/java/nl/altindag/client/ClientType.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ public enum ClientType {
6868
VERTX("vertx webclient"),
6969
GROOVY_JAVA_NET_CLIENT("groovy java net client"),
7070
HYPER_POET_CLIENT("hyperpoet client"),
71+
CLOJURE_HTTP_CLIENT("clojure httpclient"),
72+
CLOJURE_JDK_HTTP_CLIENT("clojure jdk httpclient"),
73+
CLOJURE_CLJ_HTTP_CLIENT("clojure clj-http client"),
7174
NONE("none");
7275

7376
private final String value;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
;
2+
; Copyright 2018 Thunderberry.
3+
;
4+
; Licensed under the Apache License, Version 2.0 (the "License");
5+
; you may not use this file except in compliance with the License.
6+
; You may obtain a copy of the License at
7+
;
8+
; https://www.apache.org/licenses/LICENSE-2.0
9+
;
10+
; Unless required by applicable law or agreed to in writing, software
11+
; distributed under the License is distributed on an "AS IS" BASIS,
12+
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
; See the License for the specific language governing permissions and
14+
; limitations under the License.
15+
;
16+
17+
(ns nl.altindag.client.service.ClojureCijHttpClientService
18+
(:gen-class)
19+
(:require [clj-http.client :as http])
20+
(:import
21+
[nl.altindag.client.service RequestService]
22+
[nl.altindag.client.model ClientResponse]
23+
[nl.altindag.client ClientType Constants]
24+
[nl.altindag.ssl SSLFactory]
25+
[nl.altindag.ssl.apache4.util Apache4SslUtils]
26+
[org.apache.http.impl.client HttpClients]))
27+
28+
(defn reify-request-service
29+
[^SSLFactory ssl-factory]
30+
(reify
31+
RequestService
32+
(executeRequest [this url]
33+
(let [http-client (-> (HttpClients/custom)
34+
(.setSSLSocketFactory (Apache4SslUtils/toSocketFactory ssl-factory))
35+
(.build))
36+
response (http/get url {:headers {Constants/HEADER_KEY_CLIENT_TYPE (.getValue (.getClientType this))}
37+
:http-client http-client
38+
:as :string
39+
:throw-exceptions false})]
40+
(ClientResponse. (:body response) (:status response))))
41+
(getClientType [this]
42+
ClientType/CLOJURE_CLJ_HTTP_CLIENT)))
43+
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
;
2+
; Copyright 2018 Thunderberry.
3+
;
4+
; Licensed under the Apache License, Version 2.0 (the "License");
5+
; you may not use this file except in compliance with the License.
6+
; You may obtain a copy of the License at
7+
;
8+
; https://www.apache.org/licenses/LICENSE-2.0
9+
;
10+
; Unless required by applicable law or agreed to in writing, software
11+
; distributed under the License is distributed on an "AS IS" BASIS,
12+
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
; See the License for the specific language governing permissions and
14+
; limitations under the License.
15+
;
16+
17+
(ns nl.altindag.client.service.ClojureHttpClientService
18+
(:gen-class)
19+
(:import
20+
[nl.altindag.client.service RequestService]
21+
[nl.altindag.client.model ClientResponse]
22+
[nl.altindag.client ClientType Constants ClientException]
23+
[nl.altindag.ssl SSLFactory]
24+
[java.net URL HttpURLConnection]
25+
[java.nio.charset StandardCharsets]
26+
[javax.net.ssl HttpsURLConnection]
27+
[org.apache.commons.io IOUtils]
28+
[org.apache.http.client.methods HttpGet]))
29+
30+
(defn reify-request-service
31+
[^SSLFactory ssl-factory]
32+
(reify
33+
RequestService
34+
(executeRequest [this url]
35+
(let [connection (if (.contains url "https:")
36+
(doto ^HttpsURLConnection (cast HttpsURLConnection (.openConnection (URL. url)))
37+
(.setHostnameVerifier (.getHostnameVerifier ssl-factory))
38+
(.setSSLSocketFactory (.getSslSocketFactory ssl-factory)))
39+
(if (.contains url "http:")
40+
(cast HttpURLConnection (.openConnection (URL. url)))
41+
(throw (ClientException. "Could not create a http client for one of these reasons: invalid url, security is enable while using an url with http or security is disable while using an url with https"))))]
42+
(.setRequestMethod connection HttpGet/METHOD_NAME)
43+
(.setRequestProperty connection Constants/HEADER_KEY_CLIENT_TYPE (.getValue (.getClientType this)))
44+
(ClientResponse. (IOUtils/toString (.getInputStream connection) StandardCharsets/UTF_8)
45+
(.getResponseCode connection))))
46+
(getClientType [this]
47+
ClientType/CLOJURE_HTTP_CLIENT)))
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
;
2+
; Copyright 2018 Thunderberry.
3+
;
4+
; Licensed under the Apache License, Version 2.0 (the "License");
5+
; you may not use this file except in compliance with the License.
6+
; You may obtain a copy of the License at
7+
;
8+
; https://www.apache.org/licenses/LICENSE-2.0
9+
;
10+
; Unless required by applicable law or agreed to in writing, software
11+
; distributed under the License is distributed on an "AS IS" BASIS,
12+
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
; See the License for the specific language governing permissions and
14+
; limitations under the License.
15+
;
16+
17+
(ns nl.altindag.client.service.ClojureJdkHttpClientService
18+
(:gen-class)
19+
(:import
20+
[nl.altindag.client.service RequestService]
21+
[nl.altindag.client.model ClientResponse]
22+
[nl.altindag.client ClientType Constants]
23+
[nl.altindag.ssl SSLFactory]
24+
[java.net URI]
25+
[java.net.http HttpClient HttpRequest HttpResponse$BodyHandlers]))
26+
27+
(defn reify-request-service
28+
[^SSLFactory ssl-factory]
29+
(let [http-client (-> (HttpClient/newBuilder)
30+
(.sslContext (.getSslContext ssl-factory))
31+
(.sslParameters (.getSslParameters ssl-factory))
32+
(.build))]
33+
(reify
34+
RequestService
35+
(executeRequest [this url]
36+
(let [request (-> (HttpRequest/newBuilder)
37+
(.GET)
38+
(.header Constants/HEADER_KEY_CLIENT_TYPE (.getValue (.getClientType this)))
39+
(.uri (URI/create url))
40+
(.build))
41+
response (.send http-client request (HttpResponse$BodyHandlers/ofString))]
42+
(ClientResponse. (.body response) (.statusCode response))))
43+
(getClientType [this]
44+
ClientType/CLOJURE_JDK_HTTP_CLIENT))))

client/src/test/java/nl/altindag/client/ClientConfigShould.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import feign.Feign;
2121
import jakarta.ws.rs.client.Client;
2222
import kong.unirest.Unirest;
23+
import nl.altindag.client.service.RequestService;
2324
import nl.altindag.ssl.SSLFactory;
2425
import okhttp3.OkHttpClient;
2526
import org.apache.http.impl.client.CloseableHttpClient;
@@ -398,4 +399,28 @@ void createVertxWithSecurity() {
398399
System.clearProperty("url");
399400
}
400401

402+
@Test
403+
void createClojureCijClient() {
404+
SSLFactory sslFactory = createSSLFactory(true, true);
405+
RequestService requestService = victim.clojureCijHttpClientService(sslFactory);
406+
assertThat(requestService).isNotNull();
407+
assertThat(requestService.getClientType()).isEqualTo(ClientType.CLOJURE_CLJ_HTTP_CLIENT);
408+
}
409+
410+
@Test
411+
void createClojureJdkClient() {
412+
SSLFactory sslFactory = createSSLFactory(true, true);
413+
RequestService requestService = victim.clojureJdkHttpClientService(sslFactory);
414+
assertThat(requestService).isNotNull();
415+
assertThat(requestService.getClientType()).isEqualTo(ClientType.CLOJURE_JDK_HTTP_CLIENT);
416+
}
417+
418+
@Test
419+
void createClojureHttpClient() {
420+
SSLFactory sslFactory = createSSLFactory(true, true);
421+
RequestService requestService = victim.clojureHttpClientService(sslFactory);
422+
assertThat(requestService).isNotNull();
423+
assertThat(requestService.getClientType()).isEqualTo(ClientType.CLOJURE_HTTP_CLIENT);
424+
}
425+
401426
}

client/src/test/resources/features/Hello.feature

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,6 @@ Feature: Securing the connection between you and the world
6161
| Vertx WebClient |
6262
| Groovy Java Net Client |
6363
| HyperPoet Client |
64+
| Clojure HttpClient |
65+
| Clojure Jdk HttpClient |
66+
| Clojure clj-http Client |

0 commit comments

Comments
 (0)