Square’s meticulous HTTP client for the JVM, Android, and GraalVM.

Related tags

android kotlin java graalvm
Overview

OkHttp

See the project website for documentation and APIs.

HTTP is the way modern applications network. It’s how we exchange data & media. Doing HTTP efficiently makes your stuff load faster and saves bandwidth.

OkHttp is an HTTP client that’s efficient by default:

  • HTTP/2 support allows all requests to the same host to share a socket.
  • Connection pooling reduces request latency (if HTTP/2 isn’t available).
  • Transparent GZIP shrinks download sizes.
  • Response caching avoids the network completely for repeat requests.

OkHttp perseveres when the network is troublesome: it will silently recover from common connection problems. If your service has multiple IP addresses, OkHttp will attempt alternate addresses if the first connect fails. This is necessary for IPv4+IPv6 and services hosted in redundant data centers. OkHttp supports modern TLS features (TLS 1.3, ALPN, certificate pinning). It can be configured to fall back for broad connectivity.

Using OkHttp is easy. Its request/response API is designed with fluent builders and immutability. It supports both synchronous blocking calls and async calls with callbacks.

Get a URL

This program downloads a URL and prints its contents as a string. Full source.

OkHttpClient client = new OkHttpClient();

String run(String url) throws IOException {
  Request request = new Request.Builder()
      .url(url)
      .build();

  try (Response response = client.newCall(request).execute()) {
    return response.body().string();
  }
}

Post to a Server

This program posts data to a service. Full source.

public static final MediaType JSON
    = MediaType.get("application/json; charset=utf-8");

OkHttpClient client = new OkHttpClient();

String post(String url, String json) throws IOException {
  RequestBody body = RequestBody.create(JSON, json);
  Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();
  try (Response response = client.newCall(request).execute()) {
    return response.body().string();
  }
}

Further examples are on the OkHttp Recipes page.

Requirements

OkHttp works on Android 5.0+ (API level 21+) and Java 8+.

OkHttp depends on Okio for high-performance I/O and the Kotlin standard library. Both are small libraries with strong backward-compatibility.

We highly recommend you keep OkHttp up-to-date. As with auto-updating web browsers, staying current with HTTPS clients is an important defense against potential security problems. We track the dynamic TLS ecosystem and adjust OkHttp to improve connectivity and security.

OkHttp uses your platform's built-in TLS implementation. On Java platforms OkHttp also supports Conscrypt, which integrates BoringSSL with Java. OkHttp will use Conscrypt if it is the first security provider:

Security.insertProviderAt(Conscrypt.newProvider(), 1);

The OkHttp 3.12.x branch supports Android 2.3+ (API level 9+) and Java 7+. These platforms lack support for TLS 1.2 and should not be used. But because upgrading is difficult, we will backport critical fixes to the 3.12.x branch through December 31, 2021.

Releases

Our change log has release history.

The latest release is available on Maven Central.

implementation("com.squareup.okhttp3:okhttp:4.9.0")

Snapshot builds are available. R8 and ProGuard rules are available.

Also, we have a bill of materials (BOM) available to help you keep OkHttp artifacts up to date and be sure about version compatibility.

    dependencies {
       // define a BOM and its version
       implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.0"))
       
       // define any required OkHttp artifacts without version
       implementation("com.squareup.okhttp3:okhttp")
       implementation("com.squareup.okhttp3:logging-interceptor")
    }

MockWebServer

OkHttp includes a library for testing HTTP, HTTPS, and HTTP/2 clients.

The latest release is available on Maven Central.

testImplementation("com.squareup.okhttp3:mockwebserver:4.9.0")

GraalVM Native Image

Building your native images with Graal https://www.graalvm.org/ should work automatically. Please report any bugs or workarounds you find.

See the okcurl module for an example build.

$ ./gradlew okcurl:nativeImage
$ ./okcurl/build/graal/okcurl https://httpbin.org/get

License

Copyright 2019 Square, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Issues
  • java.net.SocketTimeoutException from HTTP/2 connection leaves dead okhttp clients in pool

    java.net.SocketTimeoutException from HTTP/2 connection leaves dead okhttp clients in pool

    Tried writing a unit test w/ TestButler on Android w/ no luck, so I'll write up the steps to reproduce this and include some sample code. This happens if you connect to an HTTP/2 server and your network goes down while the okhttp client is connected to it:

    1. create an okhttp client
    2. tell it to read from the HTTP/2 server
    3. bring the network down
    4. tell it to read from the HTTP/2 server (it'll get a SocketTimeoutException)
    5. bring the network back up
    6. tell it to read from the HTTP/2 server again (it'll be stuck w/ SocketTimeoutExceptions)
    7. if you create new http clients at this point, it'll work, but the dead http client will eventually come back in the pool and fail.

    okhttp client should attempt to reopen the HTTP/2 connection instead of being stuck in this state

    Code sample for Android (create a trivial view w/ a button and a textview):

    public class MainActivity extends AppCompatActivity {
        OkHttpClient okhttpClient = new OkHttpClient();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Button loadButton = (Button) findViewById(R.id.loadButton);
            TextView outputView = (TextView) findViewById(R.id.outputView);
    
            loadButton.setOnClickListener(view -> Observable.fromCallable(() -> {
                        Request request = new Request.Builder()
                                .url(<INSERT URL TO YOUR HTTP/2 SERVER HERE>)
                                .build();
    
                        Response response = okhttpClient.newCall(request).execute();
    
                        return response.body().string();
                    })
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(outputView::setText, t -> outputView.setText(t.toString()))
            );
        }
    }
    
    
    bug 
    opened by kenyee 113
  • Analytics API

    Analytics API

    We should add verbose logging for the response cache. Folks occasionally are puzzled when the cache doesn't work. Let's make it easy for them to figure out why.

    It would also be handy for debug panels and optimizers to monitor bytes in and out, connections created, etc.

    enhancement 
    opened by swankjesse 106
  • EOFException in RealBufferedSource.readUtf8LineStrict

    EOFException in RealBufferedSource.readUtf8LineStrict

    A few people have reported this. Needs investigation & fix.

    java.io.EOFException: null
        at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:154) ~[na:0.0]
        at com.squareup.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:189) ~[na:0.0]
        at com.squareup.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:101) ~[na:0.0]
        at com.squareup.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:676) ~[na:0.0]
        at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:426) ~[na:0.0]
        at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:371) ~[na:0.0]
        at com.squareup.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:466) ~[na:0.0]
        at com.squareup.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105) ~[na:0.0]
    
    bug 
    opened by swankjesse 100
  • EOFException in RealBufferedSource.readUtf8LineStrict(): 0-bytes in stream

    EOFException in RealBufferedSource.readUtf8LineStrict(): 0-bytes in stream

    We're getting an EOF exception with size=0 in the stream.

    java.io.EOFException: \n not found: size=0 content=...
                at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:200)
                at com.squareup.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:187)
                at com.squareup.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:80)
                at com.squareup.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:791)
                at com.squareup.okhttp.internal.http.HttpEngine.access$200(HttpEngine.java:90)
    

    (Forked from issue 1114.)

    bug 
    opened by swankjesse 78
  • Unable to extract the trust manager

    Unable to extract the trust manager

    Hi, after upgrading from OkHttp 3.0.1 to 3.1.0 I get the following stack trace and crash after calling build() to create a OkHttpClient.

    java.lang.IllegalStateException: Unable to extract the trust manager on [email protected], sslSocketFactory is class com.google.android.gms.org.conscrypt.KitKatPlatformOpenSSLSocketAdapterFactory
                                                                            at okhttp3.OkHttpClient.<init>(OkHttpClient.java:187)
                                                                            at okhttp3.OkHttpClient.<init>(OkHttpClient.java:60)
                                                                            at okhttp3.OkHttpClient$Builder.build(OkHttpClient.java:719)
    

    This issue was not present in 3.0.1.

    Here's where the crash happens:

    OkHttpClient.Builder builder = new OkHttpClient.Builder()
                        .connectTimeout(10, TimeUnit.SECONDS)
                        .writeTimeout(10, TimeUnit.SECONDS)
                        .readTimeout(30, TimeUnit.SECONDS);
    
                OkHttpClient client = builder.build();
    
    bug 
    opened by AlexLardschneider 72
  • NoSuchElementException in RouteSelector

    NoSuchElementException in RouteSelector

    okhttp 3.7.0 retrofit 2.2.0

    All device brands and Android versions are reporting this issue.

    It happened for example after I tapped a notification, the app then makes a GET which ended in this exception. It didn't happen when I recreated the scenario. Device was Pixel, Android 7.1.2, on WLAN.

    java.util.NoSuchElementException
      at okhttp3.internal.connection.RouteSelector.next(RouteSelector.java:77)
      at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:171)
      at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121)
      at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100)
      at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
      at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
      at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
      at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
      at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:211)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
      at com.readystatesoftware.chuck.ChuckInterceptor.intercept(ChuckInterceptor.java:167)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
      at com.myownpackage.manager.OkHttpManager$AuthenticationInterceptor.intercept(OkHttpManager.java:135)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
      at com.myownpackage.manager.OkHttpManager$NetworkLoggingInterceptor.intercept(OkHttpManager.java:190)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
      at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
      at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:185)
      at okhttp3.RealCall.execute(RealCall.java:69)
      at retrofit2.OkHttpCall.execute(OkHttpCall.java:174)
      at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.execute(ExecutorCallAdapterFactory.java:89)
      at com.myownpackage.ui.ProfileFragment$11.doInBackground(ProfileFragment.java:516)
      at com.myownpackage.ui.ProfileFragment$11.doInBackground(ProfileFragment.java:511)
      at com.nanotasks.AbstractTask.doInBackground(AbstractTask.java:18)
      at com.nanotasks.AbstractTask.doInBackground(AbstractTask.java:7)
      at android.os.AsyncTask$2.call(AsyncTask.java:305)
      at java.util.concurrent.FutureTask.run(FutureTask.java:237)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
      at java.lang.Thread.run(Thread.java:761)
    
    opened by Jeff11 64
  • WARNING: A connection to https://... was leaked. Did you forget to close a response body?

    WARNING: A connection to https://... was leaked. Did you forget to close a response body?

    Version: com.squareup.okhttp3:okhttp:3.0.1

    Log message:

    <timestamp> okhttp3.ConnectionPool pruneAndGetAllocationCount
    WARNING: A connection to https://... was leaked. Did you forget to close a response body?
    

    Code:

    private String get(final String url) {
        String res = null;
        try {
            final Request req = new Request.Builder().url(url).get().build();
            final Response resp = ok.newCall(req).execute();
            final int code = resp.code();
            if (code == 200) {
                final ResponseBody body = resp.body();
                res = body.string();
                body.close(); // even this doesn't work!
            }
        }
        catch (final Throwable th) {
            System.out.println(th.getMessage());
        }
        return res;
    }
    
    opened by bxqgit 61
  • support enabling TLSv1.2 on Android 4.1-4.4.

    support enabling TLSv1.2 on Android 4.1-4.4.

    Our lawyers and security consultants claim that for PCI compliance*, we must disable TLS 1.0 and 1.1 on our servers. For some confusing reason, Android has supported TLS 1.2 since API 16 (android 4.1) but enabled it by default only since API 20 (android "4.4W").

    With okhttp 2.6, we were able to force use of TLS 1.2 with:

    OkHttpClient cli = new OkHttpClient();
    SSLContext sc = SSLContext.getInstance("TLSv1.2");
    sc.init(null, null, null);
    cli.setSslSocketFactory(new Tls12SocketFactory(sc.getSocketFactory()));
    ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
            .tlsVersions(TlsVersion.TLS_1_2)
            .build();
    cli.setConnectionSpecs(ImmutableList.of(cs));
    

    where Tls12SocketFactory is this.

    However, okhttp 3.1 uses some kind of reflection on internal implementation details of the SSLSocketFactory, so the above implementation no longer works. And, indeed, it's a bit silly to make callers write so much code anyway. Specifying TLS_1_2 in the ConnectionSpec should be enough to get TLSv1.2 whenever it is supported.

    As far as I can tell, the only reason why the custom socket factory is needed in the first place is that ConnectionSpec.supportedSpec() calls SSLSocket.getEnabledProtocols() to learn the list of protocols supported by the system, so on Android 4.x where TLS 1.2 is supported but not enabled by default, OkHttp thinks 1.2 is not supported at all.

    Sorry for this long bug report: I think the fix is as simple as changing getEnabledProtocols() above to getSupportedProtocols() but wanted to submit this bug for discussion before making a PR with such a change, in case there is some affirmative reason why it's the other way now.

    * Originally I understood the PCI compliance deadline to be June 2016; however, it seems like it has since been changed to be June 2018. Regardless, OkHttp should support this change for users that want it.

    android 
    opened by mlc 60
  • ETag and If-None-Match

    ETag and If-None-Match

    I have troubles with the ETag-based caching. I am using OkHttp 1.5.4 and Retrofit 1.5.1 with HttpResponseCache set. There are logs below for better explanation.

    The request with the Session header set to a token A. OkHttp hits the network, which is great.

    ---> HTTP GET https://localhost/shares
    Session: TOKEN_A
    Accept: application/json
    User-Agent: Application/1.0.0 (Android 4.4.2; Nexus 4) Size/4.7 Resolution/1280x768
    ---> END HTTP (0-byte body)
    <--- HTTP 200 https://localhost/shares (402ms)
    : HTTP/1.1 200 OK
    Content-Length: 136
    Content-Type: application/json
    Date: Sat, 17 May 2014 11:07:20 GMT
    Etag: "677210f4c22a13203551e2b92a20684528a23c87"
    Last-Modified: Sat, 17 May 2014 04:07:20 GMT
    OkHttp-Received-Millis: 1400324839589
    OkHttp-Response-Source: NETWORK 200
    OkHttp-Sent-Millis: 1400324839194
    <--- END HTTP (136-byte body)
    

    The second request with the Session header set to a token A. OkHttp hits the cache, which is great as well.

    ---> HTTP GET https://localhost/shares
    Session: TOKEN_A
    Accept: application/json
    User-Agent: Application/1.0.0 (Android 4.4.2; Nexus 4) Size/4.7 Resolution/1280x768
    ---> END HTTP (0-byte body)
    GC_FOR_ALLOC freed 415K, 5% free 9588K/10036K, paused 19ms, total 19ms
    <--- HTTP 200 https://localhost/shares (46ms)
    : HTTP/1.1 200 OK
    Content-Length: 136
    Content-Type: application/json
    Date: Sat, 17 May 2014 11:07:20 GMT
    Etag: "677210f4c22a13203551e2b92a20684528a23c87"
    Last-Modified: Sat, 17 May 2014 04:07:20 GMT
    OkHttp-Received-Millis: 1400324839589
    OkHttp-Response-Source: CACHE 200
    OkHttp-Sent-Millis: 1400324839194
    <--- END HTTP (136-byte body)
    

    The third request with the Session header set to token B. OkHttp hits the cache again, which is not so great, because in this case the server returns a different response with a different ETag actually.

    ---> HTTP GET https://localhost/shares
    Session: TOKEN_B
    Accept: application/json
    User-Agent: Application/1.0.0 (Android 4.4.2; Nexus 4) Size/4.7 Resolution/1280x768
    ---> END HTTP (0-byte body)
    <--- HTTP 200 https://localhost/shares (11ms)
    : HTTP/1.1 200 OK
    Content-Length: 136
    Content-Type: application/json
    Date: Sat, 17 May 2014 11:07:20 GMT
    Etag: "677210f4c22a13203551e2b92a20684528a23c87"
    Last-Modified: Sat, 17 May 2014 04:07:20 GMT
    OkHttp-Received-Millis: 1400324839589
    OkHttp-Response-Source: CACHE 200
    OkHttp-Sent-Millis: 1400324839194
    <--- END HTTP (136-byte body)
    

    Personally I expect to see the If-None-Match at the second and the third requests. Is the issue related to the lack of Cache-Control header at servers’s responses? Maybe I just don’t understand the caching strategy properly.

    opened by arturdryomov 50
  • IOException in DiskLruCache in 1.5.0.

    IOException in DiskLruCache in 1.5.0.

    Upgraded to v1.5.0 and I'm seeing a lot of these exceptions thrown.

    java.lang.RuntimeException: java.io.IOException: failed to delete /data/data/app.philm.in/cache/picasso-cache/452f1b31c49eebbd77673818036d6560.0
           at com.squareup.okhttp.internal.DiskLruCache$1.run(DiskLruCache.java:175)
           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
           at java.lang.Thread.run(Thread.java:841)
    Caused by: java.io.IOException: failed to delete /data/data/app.philm.in/cache/picasso-cache/452f1b31c49eebbd77673818036d6560.0
           at com.squareup.okhttp.internal.DiskLruCache.remove(DiskLruCache.java:584)
           at com.squareup.okhttp.internal.DiskLruCache.trimToSize(DiskLruCache.java:639)
           at com.squareup.okhttp.internal.DiskLruCache.access$100(DiskLruCache.java:86)
           at com.squareup.okhttp.internal.DiskLruCache$1.run(DiskLruCache.java:169)
           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
           at java.lang.Thread.run(Thread.java:841)
    
    opened by chrisbanes 48
Feign makes writing java http clients easier

Feign makes writing java http clients easier Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. Feign's first goal

null 6.8k Mar 12, 2021
Feign makes writing java http clients easier

Feign makes writing java http clients easier Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. Feign's first goal

null 6.8k Mar 13, 2021
http-kit is a minimalist, event-driven, high-performance Clojure HTTP server/client library with WebSocket and asynchronous support

HTTP Kit A simple, high-performance event-driven HTTP client+server for Clojure CHANGELOG | API | current Break Version: [http-kit "2.5.3"] ; Publish

HTTP Client/Server for Clojure 2.2k Mar 12, 2021
Google HTTP Client Library for Java

Google HTTP Client Library for Java Description Written by Google, the Google HTTP Client Library for Java is a flexible, efficient, and powerful Java

Google APIs 1.1k Mar 12, 2021
Client-side response routing for Spring

Riptide: A next generation HTTP client Riptide noun, /ˈrɪp.taɪd/: strong flow of water away from the shore Riptide is a library that implements client

Zalando SE 167 Mar 11, 2021
Asynchronous Http and WebSocket Client library for Java

Async Http Client Follow @AsyncHttpClient on Twitter. The AsyncHttpClient (AHC) library allows Java applications to easily execute HTTP requests and a

AsyncHttpClient 5.7k Mar 12, 2021
⚗️ Lightweight HTTP extensions for Java 11

Methanol A lightweight library that complements java.net.http for a better HTTP experience. Overview Methanol provides useful lightweight HTTP extensi

Moataz Abdelnasser 89 Mar 3, 2021
Java HTTP Request Library

Http Request A simple convenience library for using a HttpURLConnection to make requests and access the response. This library is available under the

Kevin Sawicki 3.2k Apr 4, 2021
ssh, scp and sftp for java

sshj - SSHv2 library for Java To get started, have a look at one of the examples. Hopefully you will find the API pleasant to work with :) Getting SSH

Jeroen van Erp 1.8k Mar 14, 2021
Ribbon is a Inter Process Communication (remote procedure calls) library with built in software load balancers. The primary usage model involves REST calls with various serialization scheme support.

Ribbon Ribbon is a client side IPC library that is battle-tested in cloud. It provides the following features Load balancing Fault tolerance Multiple

Netflix, Inc. 3.9k Mar 11, 2021
A high-level and lightweight HTTP client framework for Java. it makes sending HTTP requests in Java easier.

A high-level and lightweight HTTP client framework for Java. it makes sending HTTP requests in Java easier.

dromara 322 Apr 30, 2021
分布式代理ip共享系统

echo Echo是一个分布式的代理共享和管理系统,以长链接的方式连接多个运行在任意位置的终端,并将终端的网络资源整理为一套代理ip集群系统。echo提供整体的鉴权、流量监控、quota控制的功能。 Echo天然支持复杂网络环境,所以可以将代理终端部署在手机(甚至树莓派等终端设备) Echo支持代理

邓维佳 82 Mar 27, 2021
Microservice query language

restQL-core-java restQL-core allows you to run restQL queries directly from JVM applications, making easy to fetch information from multiple services

B2W Digital 42 Feb 21, 2021
Tiny, easily embeddable HTTP server in Java.

NanoHTTPD – a tiny web server in Java NanoHTTPD is a light-weight HTTP server designed for embedding in other applications, released under a Modified

NanoHttpd 5.8k Mar 14, 2021