66import io .github .hiwepy .opencode .OpenCodeClientConfig ;
77import io .github .hiwepy .opencode .exception .OpenCodeHttpException ;
88import io .github .hiwepy .opencode .model .*;
9- import org .apache .http .client .config .RequestConfig ;
10- import org .apache .http .client .methods .*;
11- import org .apache .http .conn .ssl .NoopHostnameVerifier ;
12- import org .apache .http .conn .ssl .SSLConnectionSocketFactory ;
13- import org .apache .http .entity .ContentType ;
14- import org .apache .http .entity .StringEntity ;
15- import org .apache .http .impl .client .CloseableHttpClient ;
16- import org .apache .http .impl .client .HttpClients ;
17- import org .apache .http .ssl .SSLContextBuilder ;
18- import org .apache .http .util .EntityUtils ;
9+ import kong .unirest .core .*;
10+ import kong .unirest .modules .jackson .JacksonObjectMapper ;
1911import org .slf4j .Logger ;
2012import org .slf4j .LoggerFactory ;
2113
22- import javax .net .ssl .SSLContext ;
23- import java .nio .charset .StandardCharsets ;
24- import java .util .Base64 ;
2514import java .util .List ;
2615import java .util .Map ;
2716import java .util .Objects ;
3423public class OpenCodeHttpClient implements AutoCloseable {
3524
3625 private static final Logger log = LoggerFactory .getLogger (OpenCodeHttpClient .class );
37- private static final ObjectMapper MAPPER = new ObjectMapper ()
38- .configure (DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false );
3926
4027 private final OpenCodeClientConfig config ;
41- private final CloseableHttpClient http ;
28+ private final UnirestInstance unirest ;
4229
4330 public OpenCodeHttpClient (OpenCodeClientConfig config ) {
4431 this .config = Objects .requireNonNull (config , "config" );
45- this .http = buildHttpClient (config );
32+ ObjectMapper mapper = new ObjectMapper ()
33+ .configure (DeserializationFeature .FAIL_ON_UNKNOWN_PROPERTIES , false );
34+ this .unirest = new UnirestInstance (new Config ()
35+ .connectTimeout (config .getConnectTimeoutMillis ())
36+ .requestTimeout (config .getReadTimeoutMillis ())
37+ .verifySsl (config .isVerifySsl ())
38+ .setObjectMapper (new JacksonObjectMapper (mapper )));
39+
40+ String password = config .resolvePassword ();
41+ if (!password .isEmpty ()) {
42+ this .unirest .config ().setDefaultBasicAuth (config .getUsername (), password );
43+ }
4644 }
4745
4846 // ============================================================
@@ -67,12 +65,12 @@ public Session getSession(String sessionId) {
6765 }
6866
6967 public List <Session > listSessions () {
70- String json = getRaw ("/session" );
71- return parseList (json , new TypeReference <List <Session >>() {});
68+ return getList ("/session" , new GenericType <List <Session >>() {});
7269 }
7370
7471 public boolean deleteSession (String sessionId ) {
75- return delete ("/session/" + sessionId );
72+ HttpResponse <String > resp = unirest .delete (url ("/session/" + sessionId )).asString ();
73+ return resp .isSuccess ();
7674 }
7775
7876 // ============================================================
@@ -90,176 +88,73 @@ public PromptResult prompt(String sessionId, PromptRequest request) {
9088 * 异步发送消息,不等待响应(POST /session/:id/prompt_async)。
9189 */
9290 public boolean promptAsync (String sessionId , PromptRequest request ) {
93- return postNoContent ("/session/" + sessionId + "/prompt_async" , request );
91+ HttpResponse <String > resp = unirest .post (url ("/session/" + sessionId + "/prompt_async" ))
92+ .header ("Content-Type" , "application/json" )
93+ .body (request )
94+ .asString ();
95+ return resp .isSuccess ();
9496 }
9597
9698 public List <PromptResult > getMessages (String sessionId ) {
97- String json = getRaw ("/session/" + sessionId + "/message" );
98- return parseList (json , new TypeReference <List <PromptResult >>() {});
99+ return getList ("/session/" + sessionId + "/message" , new GenericType <List <PromptResult >>() {});
99100 }
100101
102+ /**
103+ * 中止正在运行的会话。
104+ */
101105 public boolean abortSession (String sessionId ) {
102- return postNoContent ("/session/" + sessionId + "/abort" , null );
106+ HttpResponse <String > resp = unirest .post (url ("/session/" + sessionId + "/abort" )).asString ();
107+ return resp .isSuccess ();
103108 }
104109
105110 // ============================================================
106111 // Agent
107112 // ============================================================
108113
109114 public List <Agent > listAgents () {
110- String json = getRaw ("/agent" );
111- return parseList (json , new TypeReference <List <Agent >>() {});
115+ return getList ("/agent" , new GenericType <List <Agent >>() {});
112116 }
113117
114118 // ============================================================
115- // Internal HTTP helpers
119+ // Internal helpers
116120 // ============================================================
117121
118- private <T > T get (String path , Class <T > type ) {
119- String json = getRaw (path );
120- try {
121- return MAPPER .readValue (json , type );
122- } catch (Exception e ) {
123- throw new OpenCodeHttpException (200 , "JSON parse error: " + e .getMessage ());
124- }
125- }
126-
127- private String getRaw (String path ) {
128- String url = config .getServerUrl () + path ;
129- HttpGet request = new HttpGet (url );
130- addAuthHeader (request );
131- try (CloseableHttpResponse response = http .execute (request )) {
132- int status = response .getStatusLine ().getStatusCode ();
133- String body = response .getEntity () != null
134- ? EntityUtils .toString (response .getEntity (), StandardCharsets .UTF_8 ) : "" ;
135- if (status < 200 || status >= 300 ) {
136- throw new OpenCodeHttpException (status , body );
137- }
138- return body ;
139- } catch (OpenCodeHttpException e ) {
140- throw e ;
141- } catch (Exception e ) {
142- throw new OpenCodeHttpException (0 , "Request failed: " + e .getMessage ());
143- }
144- }
145-
146- private <T > T post (String path , Object body , Class <T > type ) {
147- String json = postRaw (path , body );
148- try {
149- return MAPPER .readValue (json , type );
150- } catch (Exception e ) {
151- throw new OpenCodeHttpException (200 , "JSON parse error: " + e .getMessage ());
152- }
153- }
154-
155- private boolean postNoContent (String path , Object body ) {
156- String url = config .getServerUrl () + path ;
157- HttpPost request = new HttpPost (url );
158- addAuthHeader (request );
159- if (body != null ) {
160- try {
161- String json = MAPPER .writeValueAsString (body );
162- request .setEntity (new StringEntity (json , ContentType .APPLICATION_JSON ));
163- } catch (Exception e ) {
164- throw new OpenCodeHttpException (0 , "JSON serialize error: " + e .getMessage ());
165- }
166- }
167- try (CloseableHttpResponse response = http .execute (request )) {
168- int status = response .getStatusLine ().getStatusCode ();
169- return status >= 200 && status < 300 ;
170- } catch (Exception e ) {
171- return false ;
172- }
173- }
174-
175- private String postRaw (String path , Object body ) {
176- String url = config .getServerUrl () + path ;
177- HttpPost request = new HttpPost (url );
178- addAuthHeader (request );
179- if (body != null ) {
180- try {
181- String json = MAPPER .writeValueAsString (body );
182- request .setEntity (new StringEntity (json , ContentType .APPLICATION_JSON ));
183- } catch (Exception e ) {
184- throw new OpenCodeHttpException (0 , "JSON serialize error: " + e .getMessage ());
185- }
186- }
187- try (CloseableHttpResponse response = http .execute (request )) {
188- int status = response .getStatusLine ().getStatusCode ();
189- String responseBody = response .getEntity () != null
190- ? EntityUtils .toString (response .getEntity (), StandardCharsets .UTF_8 ) : "" ;
191- if (status < 200 || status >= 300 ) {
192- throw new OpenCodeHttpException (status , responseBody );
193- }
194- return responseBody ;
195- } catch (OpenCodeHttpException e ) {
196- throw e ;
197- } catch (Exception e ) {
198- throw new OpenCodeHttpException (0 , "Request failed: " + e .getMessage ());
199- }
200- }
201-
202- private boolean delete (String path ) {
203- String url = config .getServerUrl () + path ;
204- HttpDelete request = new HttpDelete (url );
205- addAuthHeader (request );
206- try (CloseableHttpResponse response = http .execute (request )) {
207- int status = response .getStatusLine ().getStatusCode ();
208- return status >= 200 && status < 300 ;
209- } catch (Exception e ) {
210- return false ;
211- }
122+ private String url (String path ) {
123+ return config .getServerUrl () + path ;
212124 }
213125
214- private void addAuthHeader (HttpRequestBase request ) {
215- String password = config .resolvePassword ();
216- if (!password .isEmpty ()) {
217- String credentials = Base64 .getEncoder ()
218- .encodeToString ((config .getUsername () + ":" + password ).getBytes ());
219- request .setHeader ("Authorization" , "Basic " + credentials );
126+ private <T > T get (String path , Class <T > type ) {
127+ HttpResponse <T > resp = unirest .get (url (path )).asObject (type );
128+ if (!resp .isSuccess ()) {
129+ throw new OpenCodeHttpException (resp .getStatus (),
130+ resp .getBody () != null ? resp .getBody ().toString () : "" );
220131 }
132+ return resp .getBody ();
221133 }
222134
223- private <T > List < T > parseList (String json , TypeReference < List < T >> typeRef ) {
224- try {
225- return MAPPER . readValue ( json , typeRef );
226- } catch ( Exception e ) {
227- throw new OpenCodeHttpException ( 200 , "JSON parse error: " + e . getMessage () );
135+ private <T > T getList (String path , GenericType < T > genericType ) {
136+ HttpResponse < T > resp = unirest . get ( url ( path )). asObject ( genericType );
137+ if (! resp . isSuccess ()) {
138+ throw new OpenCodeHttpException ( resp . getStatus (),
139+ resp . getBody () != null ? resp . getBody (). toString () : "" );
228140 }
141+ return resp .getBody ();
229142 }
230143
231- private CloseableHttpClient buildHttpClient (OpenCodeClientConfig config ) {
232- try {
233- RequestConfig requestConfig = RequestConfig .custom ()
234- .setConnectTimeout (config .getConnectTimeoutMillis ())
235- .setSocketTimeout (config .getReadTimeoutMillis ())
236- .setConnectionRequestTimeout (config .getConnectTimeoutMillis ())
237- .build ();
238-
239- if (!config .isVerifySsl ()) {
240- SSLContext sslContext = new SSLContextBuilder ()
241- .loadTrustMaterial (null , (chain , authType ) -> true )
242- .build ();
243- SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory (
244- sslContext , NoopHostnameVerifier .INSTANCE );
245- return HttpClients .custom ()
246- .setDefaultRequestConfig (requestConfig )
247- .setSSLSocketFactory (sslFactory )
248- .build ();
249- }
250- return HttpClients .custom ()
251- .setDefaultRequestConfig (requestConfig )
252- .build ();
253- } catch (Exception e ) {
254- throw new RuntimeException ("Failed to build HTTP client" , e );
144+ private <T > T post (String path , Object body , Class <T > type ) {
145+ HttpResponse <T > resp = unirest .post (url (path ))
146+ .header ("Content-Type" , "application/json" )
147+ .body (body )
148+ .asObject (type );
149+ if (!resp .isSuccess ()) {
150+ throw new OpenCodeHttpException (resp .getStatus (),
151+ resp .getBody () != null ? resp .getBody ().toString () : "" );
255152 }
153+ return resp .getBody ();
256154 }
257155
258156 @ Override
259157 public void close () {
260- try {
261- http .close ();
262- } catch (Exception ignored ) {
263- }
158+ unirest .close ();
264159 }
265160}
0 commit comments