Geonode logo
Geonode Team

Geonode Team

Dikemas kini: 7 Oktober 2026

Diterbitkan: 2 September 2026

OkHttp di Java: Panduan Memulai

OkHttp adalah klien HTTP yang pada akhirnya digunakan oleh sebagian besar proyek JVM dan Android, dan ada dua keputusan desain yang sering membingungkan pemula: klien ini dirancang untuk digunakan bersama, dan isi respons harus ditutup. Jika kedua hal tersebut dilakukan dengan benar, sisanya akan berjalan lancar. Namun, jika salah melakukannya, koneksi akan bocor hingga sistem mengalami kegagalan. Panduan ini mencakup dasar-dasar, interceptor, batas waktu, dan proxy — ditambah catatan mengenai lokasi proyek saat ini, yang telah berubah.

Latar belakang kami: kami adalah Geonode dan kami menjual layanan proxy, dan konfigurasi proxy OkHttp memang sangat tidak biasa — otentikasi proxy dilakukan melalui proxyAuthenticator, bukan melalui header, dan jika salah mengonfigurasinya, akan muncul kode kesalahan 407 yang terlihat seperti masalah kredensial, padahal sebenarnya itu adalah masalah konfigurasi. Bagian tersebut ada di bagian akhir. Semua bagian sebelumnya berfungsi tanpa proxy sama sekali, dan jika Anda sedang mempelajari pustaka ini, pelajari terlebih dahulu dengan menggunakan koneksi Anda sendiri.

Di Mana OkHttp Sekarang

Perlu disebutkan sejak awal, karena tautan lama sudah tidak aktif.

Repositori OkHttp telah dipindahkan. github.com/square/okhttp

kini dialihkan ke github.com/lysine-dev/okhttp

, dan situs dokumentasi yang sebelumnya berada di square.github.io/okhttp

menampilkan kode status 404 — situs saat ini berada di lysine.dev/okhttp

. Proyek ini dikelola secara aktif dan berlisensi Apache-2.0, sebagaimana diverifikasi pada September 2026.

Koordinat Maven tidak berubah. Proyek ini masih dipublikasikan sebagai com.squareup.okhttp3:okhttp

:

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

Terdapat pula daftar bahan (bill of materials) untuk memastikan artefak terkait tetap selaras:

implementation(platform("com.squareup.okhttp3:okhttp-bom:5.5.0"))

Persyaratan: Android 5.0+ (tingkat API 21+) dan Java 8+. OkHttp bergantung pada Okio untuk I/O dan pada pustaka standar Kotlin — keduanya digambarkan oleh proyek ini sebagai "pustaka kecil dengan kompatibilitas mundur yang kuat". Di Android, OkHttp menggunakan AndroidX Startup, dan jika Anda menonaktifkan inisialisasi di manifes, aplikasi Anda harus memanggil ``OkHttp.initialize(applicationContext)`

di ``Application.onCreate

`.

Cabang lama ``3.12.x`

` mendukung Android 2.3+ dan Java 7, dan proyek ini secara tegas menyatakan bahwa platform-platform tersebut "tidak mendukung TLS 1.2 dan sebaiknya tidak digunakan".

Permintaan Pertama Anda

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();
  }
}

Ada tiga hal penting dalam contoh tujuh baris tersebut.

**try

-with-resources bukanlah opsi opsional.** Response

mengimplementasikan Closeable

, dan respons yang belum ditutup akan mempertahankan koneksinya. Jika terjadi kebocoran yang cukup parah, kolam koneksi akan habis; pada titik ini, permintaan akan macet alih-alih gagal — sebuah gejala yang tampak seperti masalah jaringan, padahal sebenarnya bukan.

**body().string()

dapat dipanggil satu kali.** Fungsi ini menghabiskan aliran data. Memanggilnya dua kali akan memicu pengecualian, dan memanggilnya setelah respons ditutup juga akan memicu pengecualian. Jika Anda memerlukan isi respons lebih dari sekali, simpanlah string tersebut.

** ``execute()`

bersifat sinkron.** Untuk pemrosesan asinkron, ``enqueue()

menerima ``Callback

` dan dijalankan pada kolam utas dispatcher OkHttp.

Permintaan POST memiliki bentuk yang sama dengan isi:

public static final MediaType JSON = MediaType.get("application/json");

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();
  }
}

Gunakan Klien Bersama

Keputusan desain yang paling sering salah dilakukan orang.

OkHttpClient

menyimpan kumpulan koneksi dan kumpulan utas. Membuat satu klien per permintaan akan membuang setiap koneksi yang mungkin bisa Anda gunakan kembali, serta menciptakan utas yang kemudian Anda tinggalkan begitu saja. Cara ini memang berfungsi, tetapi lambat, dan saat beban tinggi, hal ini akan menghabiskan sumber daya.

Buat satu klien untuk aplikasi Anda dan gunakan bersama. Desainnya sudah aman untuk thread.

Saat Anda memerlukan pengaturan berbeda untuk bagian tertentu dari kode Anda, jangan buat klien kedua dari awal — kloning klien yang sudah ada agar pool-nya dapat digunakan bersama:

OkHttpClient shortTimeout = client.newBuilder()
    .readTimeout(5, TimeUnit.SECONDS)
    .build();

newBuilder()

menghasilkan klien yang berbagi pool koneksi dan dispatcher dengan induknya, yang persis seperti yang Anda inginkan.

Untuk proses shutdown, terutama pada proses berumur pendek, lepaskan sumber daya secara eksplisit:

client.dispatcher().executorService().shutdown();
client.connectionPool().evictAll();

Tanpa ini, JVM mungkin akan macet selama durasi keep-alive kolam sebelum keluar, yang merupakan hal yang membingungkan untuk didebug dalam alat CLI.

Apa yang Ditambahkan OkHttp ke Permintaan Anda

Pustaka ini mengubah permintaan, dan dengan mengetahui apa yang ditambahkannya, Anda dapat menghindari kebingungan tertentu.

Dokumentasinya sangat jelas: "OkHttp mungkin menambahkan header yang tidak ada pada permintaan asli, termasuk Content-Length, Transfer-Encoding, User-Agent, Host, Connection, dan Content-Type. OkHttp akan menambahkan header Accept-Encoding untuk kompresi respons transparan kecuali jika header tersebut sudah ada. Jika Anda memiliki cookie, OkHttp akan menambahkan header Cookie beserta cookie tersebut."

Ada dua konsekuensi.

Kompresi transparan dilakukan secara otomatis dan dibalikkan untuk Anda. OkHttp meminta kompresi, mendekompresi respons, dan kemudian "akan menghapus header respons yang sesuai, yaitu Content-Encoding dan Content-Length, karena header tersebut tidak berlaku untuk isi respons yang telah didekompresi". Jadi, tidak adanya Content-Length pada respons adalah hal yang normal, bukan bug — kecuali jika Anda sendiri yang mengatur Accept-Encoding, dalam hal ini Anda bertanggung jawab atas proses dekompresi.

Permintaan bersyarat terjadi secara otomatis saat penyimpanan dalam cache diaktifkan. OkHttp menambahkan If-Modified-Since dan If-None-Match untuk memvalidasi ulang entri cache yang sudah kadaluwarsa.

OkHttp juga mengikuti pengalihan secara default dan, saat menghadapi tantangan otorisasi, "akan meminta Authenticator (jika telah dikonfigurasi) untuk memenuhi tantangan tersebut", lalu mencoba kembali dengan kredensial yang disediakan.

Pustaka ini mendeskripsikan dirinya sebagai "berprinsip dan menghindari konfigurasi yang berlebihan, terutama jika konfigurasi tersebut dimaksudkan untuk mengatasi server yang bermasalah, menguji skenario yang tidak valid, atau yang bertentangan dengan RFC yang relevan". Pustaka ini secara jujur menyebutkan keterbatasannya sendiri — pustaka ini “tidak mengizinkan GET dengan body”, dan cache “bukanlah antarmuka dengan implementasi alternatif”. Jika Anda perlu mengirimkan permintaan yang sengaja dibuat tidak valid, pustaka ini bukanlah pilihan yang tepat, dan hal tersebut merupakan pilihan desain, bukan kelalaian.

Interceptor

Titik ekstensi utama, sekaligus fitur yang akan menentukan cara Anda menggunakan pustaka ini.

class LoggingInterceptor implements Interceptor {
  @Override public Response intercept(Interceptor.Chain chain) throws IOException {
    Request request = chain.request();
    long t1 = System.nanoTime();
    logger.info(String.format("Sending request %s on %s%n%s",
        request.url(), chain.connection(), request.headers()));

    Response response = chain.proceed(request);

    long t2 = System.nanoTime();
    logger.info(String.format("Received response for %s in %.1fms%n%s",
        response.request().url(), (t2 - t1) / 1e6d, response.headers()));
    return response;
  }
}

Dokumentasi tersebut dengan tegas menyatakan bahwa "panggilan ke chain.proceed(request) merupakan bagian krusial dari implementasi setiap interceptor. Metode yang tampak sederhana ini adalah tempat di mana semua proses HTTP berlangsung." Dan peringatan yang patut diperhatikan: "jika chain.proceed(request) dipanggil lebih dari sekali, badan respons sebelumnya harus ditutup."

Ada dua jenis, dan memilih dengan benar sangat penting. Daftarkan dengan addInterceptor() atau addNetworkInterceptor(). Dokumentasi menjelaskan perbedaannya secara tepat.

Interceptor aplikasi:

  • "Tidak perlu khawatir tentang respons perantara seperti pengalihan dan percobaan ulang."
  • "Selalu dipanggil sekali, bahkan jika respons HTTP disajikan dari cache."
  • "Mengikuti maksud asli aplikasi. Tidak terpengaruh oleh header yang disisipkan oleh OkHttp seperti If-None-Match."
  • "Diizinkan untuk melakukan short-circuit dan tidak memanggil Chain.proceed()."
  • "Diizinkan untuk mencoba ulang dan melakukan beberapa panggilan ke Chain.proceed()."
  • "Dapat menyesuaikan batas waktu panggilan menggunakan withConnectTimeout, withReadTimeout, withWriteTimeout."

Penyadap jaringan:

  • "Mampu beroperasi pada respons perantara seperti pengalihan dan upaya ulang."
  • "Tidak dipanggil untuk respons yang disimpan dalam cache yang memotong jalur jaringan."
  • "Mengamati data persis seperti yang akan dikirimkan melalui jaringan."
  • "Akses ke Connection yang membawa permintaan."

Aturan praktis: gunakan interceptor aplikasi untuk segala hal yang berkaitan dengan maksud permintaan Anda — menambahkan header otorisasi, user agent, atau pencatatan (logging) tingkat aplikasi. Gunakan interceptor jaringan untuk segala hal yang berkaitan dengan data yang benar-benar dikirim melalui jaringan — memeriksa isi pesan yang terkompresi, melacak setiap lompatan pengalihan, serta menganalisis koneksi.

Kesalahan paling umum adalah mendaftarkan interceptor otorisasi sebagai interceptor jaringan, yang kemudian akan terpicu sekali per lompatan pengalihan dan berpotensi membocorkan kredensial Anda ke host yang tidak Anda tuju.

Batas Waktu

OkHttp memiliki pengaturan default yang masuk akal dan empat pengaturan terpisah; dengan mengetahui pengaturan mana yang terpicu, Anda dapat mengetahui di mana letak masalahnya.

OkHttpClient client = new OkHttpClient.Builder()
    .connectTimeout(10, TimeUnit.SECONDS)
    .readTimeout(30, TimeUnit.SECONDS)
    .writeTimeout(30, TimeUnit.SECONDS)
    .callTimeout(60, TimeUnit.SECONDS)
    .build();

**connectTimeout

** mencakup proses pembentukan koneksi TCP dan TLS. **readTimeout

** berlaku di antara setiap proses pembacaan data, bukan untuk respons secara keseluruhan — sehingga unduhan yang lambat namun terus berlanjut tidak akan memicu batas waktu ini. **writeTimeout

** melakukan hal yang sama untuk unggahan. **callTimeout

** membatasi seluruh panggilan termasuk pengalihan, upaya ulang, dan transfer isi. Nilai defaultnya adalah nol, yang berarti tidak ada batasan keseluruhan.

Yang terakhir itulah yang harus diatur. Tanpa pengaturan ini, panggilan yang terus mengirimkan data sedikit demi sedikit dapat berjalan tanpa batas waktu, karena batas waktu pembacaan (read timeout) akan disetel ulang setiap kali satu byte diterima. Batas waktu pengiriman (callTimeout

) adalah batas atas yang memastikan suatu tugas selesai, dan ini setara dengan opsi ``--max-time`

` di curl — perbedaan yang telah kita bahas dalam mengatur batas waktu dengan curl.

Pengaturan ulang per-panggilan tersedia melalui ``withReadTimeout`

` dan metode sejenisnya pada interceptor aplikasi, yang memungkinkan Anda memberikan ruang lebih bagi satu endpoint yang lambat tanpa melonggarkan pengaturan default untuk semua hal.

Proksi

Di sinilah OkHttp berbeda dari kebanyakan klien, dan di sinilah orang-orang sering menghabiskan waktu.

Proxy proxy = new Proxy(Proxy.Type.HTTP,
    new InetSocketAddress("proxy.example.com", 9000));

OkHttpClient client = new OkHttpClient.Builder()
    .proxy(proxy)
    .build();

Untuk SOCKS, gunakan Proxy.Type.SOCKS dengan format yang sama.

Otentikasi adalah bagian yang sering mengejutkan orang. Anda tidak perlu mengatur header Proxy-Authorization. Anda menyediakan proxyAuthenticator, yang dipanggil oleh OkHttp saat proxy mengeluarkan tantangan 407:

Authenticator proxyAuth = (route, response) -> {
  if (response.request().header("Proxy-Authorization") != null) {
    return null;   // already tried these credentials; give up
  }
  String credential = Credentials.basic("user", "pass");
  return response.request().newBuilder()
      .header("Proxy-Authorization", credential)
      .build();
};

OkHttpClient client = new OkHttpClient.Builder()
    .proxy(proxy)
    .proxyAuthenticator(proxyAuth)
    .build();

Pengembalian null sangat penting. Tanpa itu, kata sandi yang salah akan menyebabkan loop percobaan ulang tak berujung alih-alih kegagalan — OkHttp meminta autentikator, mendapatkan kredensial yang salah, menerima 407 lagi, dan meminta lagi. Cara memutus siklus ini adalah dengan memeriksa apakah Anda sudah mengirimkan header Proxy-Authorization.

Tiga catatan tambahan.

Kode status 407 bukanlah 401. Proxy telah menolak permintaan Anda dan tidak pernah mencapai server tujuan. Kode status 401 berarti proxy berhasil dan server tujuan meminta kredensial, yang merupakan skenario "authenticator()" yang sama sekali berbeda.

proxySelector() memungkinkan Anda memilih proxy per permintaan, bukan per klien, sehingga Anda dapat merutekan host yang berbeda secara berbeda tanpa perlu membuat beberapa klien.

Pastikan pengaturan tersebut berlaku. Kirim permintaan ke layanan yang menampilkan alamat Anda, baik dengan maupun tanpa konfigurasi proxy. Kesalahan konfigurasi di sini tidak menunjukkan gejala apa pun — permintaan berhasil dan langsung terkirim — dan memastikan alamat keluar adalah satu-satunya cara untuk memastikannya. Pola keberhasilan tanpa gejala inilah yang kami bahas dalam mengapa pengujian proxy penting.

Menangani Respons dengan Benar

Beberapa pola yang membedakan antara kode yang berfungsi dan kode yang tetap berfungsi di bawah beban tinggi.

**Periksa ``isSuccessful()`

, bukan sekadar ketiadaan pengecualian.** OkHttp melemparkan ``IOException

untuk kegagalan jaringan, bukan untuk status kesalahan HTTP. Kode status 404 atau 500 muncul sebagai ``Response

` biasa:

try (Response response = client.newCall(request).execute()) {
  if (!response.isSuccessful()) {
    String body = response.body() != null ? response.body().string() : "";
    throw new IOException("HTTP " + response.code() + " from " + request.url()
                          + ": " + body.substring(0, Math.min(200, body.length())));
  }
  return response.body().string();
}

Dengan menyertakan bagian pertama dari isi pesan kesalahan, kode status yang tidak jelas menjadi pesan yang menjelaskan masalahnya — kebanyakan API menjelaskan masalahnya sendiri di dalam isi pesan 400.

Jangan menyimpan respons besar ke dalam String. body().string()

akan membaca semuanya ke dalam memori. Untuk unduhan besar, gunakan streaming:

try (Response response = client.newCall(request).execute();
     BufferedSource source = response.body().source();
     BufferedSink sink = Okio.buffer(Okio.sink(new File("out.bin")))) {
  sink.writeAll(source);
}

Panggilan asinkron tetap memerlukan penutupan isi respons, dan callback dijalankan pada thread latar belakang:

client.newCall(request).enqueue(new Callback() {
  @Override public void onFailure(Call call, IOException e) {
    logger.warn("request failed", e);
  }
  @Override public void onResponse(Call call, Response response) throws IOException {
    try (ResponseBody body = response.body()) {
      handle(body.string());
    }
  }
});

Perhatikan bahwa onFailure

hanya dipicu untuk masalah jaringan. Kode status HTTP 500 muncul di onResponse

, yang mengejutkan orang-orang yang mengira penamaannya berarti apa yang terdengar.

Upaya ulang perlu diperhatikan. OkHttp secara otomatis melakukan upaya ulang untuk beberapa kegagalan di tingkat koneksi, yang dikendalikan oleh retryOnConnectionFailure()

, yang aktif secara default. OkHttp tidak melakukan upaya ulang untuk status kesalahan HTTP, dan memang seharusnya demikian — melakukan upaya ulang terhadap POST yang mungkin telah berhasil dapat menyebabkan duplikasi penulisan. Jika Anda menambahkan logika percobaan ulang sendiri, lakukanlah di dalam interceptor aplikasi, batasi jumlah percobaan, berikan jeda di antara percobaan, dan batasi hanya pada metode idempoten kecuali API tersebut menyediakan kunci idempoten.

Manfaat Lainnya

Singkatnya, inilah alasan-alasan untuk memilihnya.

HTTP/2, di mana "dukungan ini memungkinkan semua permintaan ke host yang sama untuk berbagi satu soket". Connection pooling, yang "mengurangi latensi permintaan (jika HTTP/2 tidak tersedia)". GZIP transparan. Penyimpanan respons dalam cache, yang "menghindari penggunaan jaringan sama sekali untuk permintaan berulang".

Ketahanan. Fitur ini "akan pulih secara otomatis dari masalah koneksi umum", dan jika sebuah layanan memiliki beberapa alamat, fitur ini "akan mencoba alamat alternatif jika koneksi pertama gagal" — yang menurut catatan proyek "diperlukan untuk IPv4+IPv6 dan layanan yang dihosting di pusat data redundan".

TLS modern, termasuk TLS 1.3, ALPN, dan certificate pinning, menggunakan implementasi platform tersebut. Pada JVM, proyek ini juga mendukung Conscrypt, yang mengintegrasikan BoringSSL dengan Java, dan digunakan secara otomatis jika Conscrypt adalah penyedia keamanan pertama.

Kepatuhan terhadap standar. Proyek ini mencantumkan spesifikasi yang dipatuhinya: RFC 9110 untuk semantik HTTP, RFC 9111 untuk caching, RFC 9112 untuk HTTP/1.1, RFC 9113 untuk HTTP/2, RFC 6455 untuk WebSockets, dan spesifikasi WHATWG untuk server-sent events. Jika suatu spesifikasi bersifat ambigu, proyek ini "mengikuti agen pengguna modern seperti peramban populer atau pustaka HTTP umum".

Pertanyaan Lainnya

Apakah OkHttp masih dikembangkan?

Ya. Repositori telah dipindahkan dari square/okhttp ke lysine-dev/okhttp dan situs dokumentasinya kini berada di lysine.dev/okhttp, namun proyek ini masih dikembangkan secara aktif dan dilisensikan di bawah lisensi Apache-2.0. Koordinat Maven-nya tetap com.squareup.okhttp3:okhttp.

Apakah saya harus membuat OkHttpClient baru untuk setiap permintaan?

Tidak. Klien ini memiliki kumpulan koneksi dan kumpulan utas, serta dirancang agar aman untuk digunakan dalam lingkungan multithread. Buatlah satu untuk aplikasi Anda dan gunakan secara bersama-sama. Jika Anda memerlukan pengaturan yang berbeda, gunakan newBuilder() pada klien yang sudah ada agar kumpulan tersebut dapat digunakan bersama.

Mengapa saya harus menutup respons?

Karena Response mempertahankan koneksi hingga ditutup, dan respons yang bocor akan menghabiskan kumpulan koneksi. Gejalanya adalah permintaan yang macet alih-alih gagal, yang sulit didiagnosis. Selalu gunakan try-with-resources.

Apa perbedaan antara interceptor aplikasi dan interceptor jaringan?

Interceptor aplikasi melihat permintaan asli Anda dan dipanggil tepat sekali, bahkan untuk respons yang disimpan dalam cache, serta dapat menghentikan proses atau mencoba ulang. Interceptor jaringan melihat setiap pertukaran jaringan secara individual, termasuk pengalihan dan upaya ulang, memiliki akses ke koneksi, dan dilewati sepenuhnya untuk respons yang disimpan dalam cache.

Bagaimana cara mengatur proxy di OkHttp?

Berikan java.net.Proxy ke OkHttpClient.Builder.proxy(). Untuk otentikasi, atur proxyAuthenticator alih-alih header — dan kembalikan null jika header Proxy-Authorization sudah ada, atau kredensial yang salah akan menyebabkan loop percobaan ulang tak terbatas.

Timeout apa saja yang harus saya atur?

connectTimeout sekitar 10 detik, readTimeout dan writeTimeout sekitar 30 detik, dan — yang paling penting — callTimeout, yang secara default bernilai nol dan merupakan satu-satunya pengaturan yang membatasi seluruh panggilan. Tanpa pengaturan ini, respons yang masuk sangat lambat tidak akan pernah mengalami timeout karena timeout pembacaan akan disetel ulang pada setiap byte.

Apakah OkHttp menangani GZIP secara otomatis?

Ya, jika Anda tidak mengatur Accept-Encoding sendiri. OkHttp akan meminta kompresi, mendekompresi respons, dan menghapus Content-Encoding serta Content-Length karena header-header tersebut tidak lagi menggambarkan isi yang telah didekompresi. Jika Anda mengatur header tersebut secara manual, Anda juga harus menangani proses dekompresi sendiri.

Versi Java apa yang dibutuhkan oleh OkHttp?

Java 8 atau yang lebih baru, serta Android 5.0 (tingkat API 21) atau yang lebih baru. Hal ini bergantung pada Okio dan pustaka standar Kotlin. Cabang 3.12.x yang lama mendukung Java 7 dan Android 2.3, tetapi tidak mendukung TLS 1.2 dan sebaiknya tidak digunakan.

Kesimpulan

OkHttp adalah API kecil yang dibangun di atas implementasi yang dirancang dengan matang, dan ada dua kebiasaan yang mencakup sebagian besar cara penggunaannya yang benar: gunakan satu klien untuk seluruh aplikasi Anda, dan tutup setiap respons dengan ``try-with-resources. Kedua kegagalan tersebut tidak menampilkan pesan kesalahan, dan pada akhirnya akan muncul sebagai permintaan yang macet, bukan sebagai kesalahan yang dapat Anda baca.

Interceptor adalah tempat Anda akan menghabiskan waktu, dan perbedaan antara interceptor aplikasi dan jaringan layak dipelajari dengan benar, bukan hanya melalui percobaan. Interceptor aplikasi mendeteksi niat Anda dan dijalankan sekali; interceptor jaringan mendeteksi setiap lompatan dan dilewati untuk respons yang disimpan dalam cache. Mendaftarkan interceptor otorisasi di lapisan jaringan adalah kesalahan klasik, dan interceptor tersebut akan terpicu pada setiap pengalihan.

Tetapkan batas waktu maksimum (callTimeout). Nilai defaultnya adalah nol; ini adalah satu-satunya pengaturan yang membatasi durasi panggilan secara keseluruhan, dan ketiadaannya adalah alasan mengapa suatu tugas yang seharusnya selesai dalam hitungan detik kadang-kadang berjalan hingga dihentikan oleh proses lain.

Dan jika Anda mengikuti dokumentasi lama, periksa tautannya. Proyek ini telah dipindahkan ke lysine.dev/okhttp dan situs yang dihosting oleh Square sudah tidak ada lagi — meskipun koordinat artefak tetap sama, sehingga berkas build Anda tidak memerlukan perubahan apa pun.