{"id":13654115,"url":"https://github.com/com-lihaoyi/requests-scala","last_synced_at":"2025-05-15T21:05:39.351Z","repository":{"id":37089759,"uuid":"141567748","full_name":"com-lihaoyi/requests-scala","owner":"com-lihaoyi","description":"A Scala port of the popular Python Requests HTTP client: flexible, intuitive, and straightforward to use.","archived":false,"fork":false,"pushed_at":"2025-01-14T12:24:36.000Z","size":242,"stargazers_count":736,"open_issues_count":30,"forks_count":87,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-12T11:07:17.444Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/com-lihaoyi.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"lihaoyi"}},"created_at":"2018-07-19T11:06:17.000Z","updated_at":"2025-05-07T22:22:23.000Z","dependencies_parsed_at":"2024-05-30T03:35:33.938Z","dependency_job_id":"f40eb48f-c85b-4923-826b-5c2e7815646d","html_url":"https://github.com/com-lihaoyi/requests-scala","commit_stats":null,"previous_names":["lihaoyi/requests-scala"],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/com-lihaoyi%2Frequests-scala","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/com-lihaoyi%2Frequests-scala/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/com-lihaoyi%2Frequests-scala/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/com-lihaoyi%2Frequests-scala/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/com-lihaoyi","download_url":"https://codeload.github.com/com-lihaoyi/requests-scala/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254422755,"owners_count":22068678,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T02:01:23.540Z","updated_at":"2025-05-15T21:05:39.330Z","avatar_url":"https://github.com/com-lihaoyi.png","language":"Scala","funding_links":["https://github.com/sponsors/lihaoyi","https://www.patreon.com/lihaoyi"],"categories":["Scala","网络编程","Table of Contents"],"sub_categories":["Spring Cloud框架","HTTP"],"readme":"# Requests-Scala 0.9.0\n\n[![Join the chat at https://gitter.im/lihaoyi/requests-scala](https://badges.gitter.im/lihaoyi/requests-scala.svg)](https://gitter.im/lihaoyi/requests-scala?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\nRequests-Scala is a Scala port of the popular Python\n[Requests](http://docs.python-requests.org/) HTTP client. Requests-Scala aims to\nprovide the same API and user-experience as the original Requests: flexible,\nintuitive, and straightforward to use.\n\nIf you use Requests-Scala and like it, you will probably enjoy the following book by the Author:\n\n- [*Hands-on Scala Programming*](https://www.handsonscala.com/)\n\n*Hands-on Scala* has uses Requests-Scala extensively throughout the book, and has\nthe entirety of *Chapter 12: Working with HTTP APIs* dedicated to\nthe library. *Hands-on Scala* is a great way to level up your skills in Scala\nin general and Requests-Scala in particular.\n\nYou can also support it by donating to our Patreon:\n\n- [https://www.patreon.com/lihaoyi](https://www.patreon.com/lihaoyi)\n\nFor a hands-on introduction to this library, take a look at the following blog post:\n\n- [How to work with HTTP JSON APIs in Scala](http://www.lihaoyi.com/post/HowtoworkwithHTTPJSONAPIsinScala.html)\n\n## Contents\n\n- [Requests-Scala 0.9.0](#requests-scala-081)\n  - [Contents](#contents)\n  - [Getting Started](#getting-started)\n  - [Making a Request](#making-a-request)\n    - [Passing in Parameters](#passing-in-parameters)\n    - [Response Content](#response-content)\n  - [Streaming Requests](#streaming-requests)\n  - [Handling JSON](#handling-json)\n  - [Multipart Uploads](#multipart-uploads)\n  - [Misc Configuration](#misc-configuration)\n    - [Custom Headers](#custom-headers)\n    - [Timeouts](#timeouts)\n    - [Compression](#compression)\n    - [Cookies](#cookies)\n    - [Redirects](#redirects)\n    - [Client Side Certificates](#client-side-certificates)\n  - [Sessions](#sessions)\n  - [Why Requests-Scala?](#why-requests-scala)\n  - [Changelog](#changelog)\n    - [0.9.0](#090)\n    - [0.8.0](#080)\n    - [0.7.1](#071)\n    - [0.7.0](#070)\n    - [0.6.7](#067)\n    - [0.6.5](#065)\n    - [0.5.1](#051)\n    - [0.4.7](#047)\n    - [0.3.0](#030)\n    - [0.2.0](#020)\n    - [0.1.9](#019)\n    - [0.1.8](#018)\n    - [0.1.7](#017)\n    - [0.1.6](#016)\n    - [0.1.5](#015)\n\n## Getting Started\n\nUse the following import to get you started:\n\n```scala\nivy\"com.lihaoyi::requests:0.9.0\" // mill\n\"com.lihaoyi\" %% \"requests\" % \"0.9.0\" // sbt\ncompile \"com.lihaoyi:requests_2.12:0.9.0\" //gradle\n```\n\n## Making a Request\n```scala\nval r = requests.get(\"https://api.github.com/users/lihaoyi\")\n\nr.statusCode\n// 200\n\nr.headers(\"content-type\")\n// Buffer(\"application/json; charset=utf-8\")\n\nr.text()\n// {\"login\":\"lihaoyi\",\"id\":934140,\"node_id\":\"MDQ6VXNlcjkzNDE0MA==\",...\n```\n\nMaking your first HTTP request is simple: simply call `requests.get` with the\nURL you want, and requests will fetch it for you.\n\nYou can also call `requests.post`, `requests.put`, etc. to make other kinds of\nHTTP requests:\n\n```scala\nval r = requests.post(\"http://httpbin.org/post\", data = Map(\"key\" -\u003e \"value\"))\n\nval r = requests.put(\"http://httpbin.org/put\", data = Map(\"key\" -\u003e \"value\"))\n\nval r = requests.delete(\"http://httpbin.org/delete\")\n\nval r = requests.head(\"http://httpbin.org/head\")\n\nval r = requests.options(\"http://httpbin.org/get\")\n\n// dynamically choose what HTTP method to use\nval r = requests.send(\"put\")(\"http://httpbin.org/put\", data = Map(\"key\" -\u003e \"value\"))\n\n```\n\n### Passing in Parameters\n\n```scala\nval r = requests.get(\n    \"http://httpbin.org/get\",\n    params = Map(\"key1\" -\u003e \"value1\", \"key2\" -\u003e \"value2\")\n)\n```\nYou can pass in URL parameters to GET requests via the `params` argument; simply\npass in a `Map[String, String]`. As seen earlier, when passing in POST or PUT\nparameters, you instead need the `data` argument:\n\n```scala\nval r = requests.post(\"http://httpbin.org/post\", data = Map(\"key\" -\u003e \"value\"))\n\nval r = requests.put(\"http://httpbin.org/put\", data = Map(\"key\" -\u003e \"value\"))\n```\n\nApart from POSTing key-value pairs, you can also POST `String`s, `Array[Byte]`s,\n`java.io.File`s, `java.nio.file.Path`s, and `requests.MultiPart` uploads:\n\n```scala\nrequests.post(\"https://httpbin.org/post\", data = \"Hello World\")\nrequests.post(\"https://httpbin.org/post\", data = Array[Byte](1, 2, 3))\nrequests.post(\"https://httpbin.org/post\", data = new java.io.File(\"thing.json\"))\nrequests.post(\"https://httpbin.org/post\", data = java.nio.file.Paths.get(\"thing.json\"))\n```\n\nThe `data` parameter also supports anything that implements the\n[Writable](https://github.com/com-lihaoyi/geny#writable) interface, such as\n[ujson.Value](http://com-lihaoyi.github.io/upickle/#uJson)s,\n[uPickle](http://com-lihaoyi.github.io/upickle)'s `upickle.default.writable` values,\nor [Scalatags](http://com-lihaoyi.github.io/scalatags/)'s `Tag`s\n\n### Response Content\n\n```scala\nval r = requests.get(\"https://api.github.com/events\")\n\nr.statusCode\n// 200\n\nr.headers(\"content-type\")\n// Buffer(\"application/json; charset=utf-8\")\n```\n\nAs seen earlier, you can use `.statusCode` and `.headers` to see the relevant\nmetadata of your HTTP response. The response data is in the `.data` field of the\n`Response` object. Most often, it's text, which you can decode using the `.text()`\nproperty as shown below:\n\n```scala\nr.text()\n// [{\"id\":\"7990061484\",\"type\":\"PushEvent\",\"actor\":{\"id\":6242317,\"login\":...\n```\n\nIf you want the raw bytes of the response, use `r.contents`\n\n\n```scala\nr.contents\n// Array(91, 123, 34, 105, 100, 34, 58, 34, 55, 57,  57, 48, 48, 54, 49, ...\n```\n\n\n## Streaming Requests\n\n```scala\nos.write(\n  os.pwd / \"file.json\",\n  requests.get.stream(\"https://api.github.com/events\")\n)\n```\n\nRequests exposes the `requests.get.stream` (and equivalent\n`requests.post.stream`, `requests.put.stream`, etc.) functions for you to\nperform streaming uploads/downloads without needing to load the entire\nrequest/response into memory. This is useful if you are upload/downloading large\nfiles or data blobs. `.stream` returns a\n[Readable](https://github.com/com-lihaoyi/geny#readable) value, that can be then\npassed to methods like [os.write](https://github.com/com-lihaoyi/os-lib#oswrite),\n`fastparse.parse` or `upickle.default.read` to handle the received data in a\nstreaming fashion:\n\n```scala\nujson.read(requests.get.stream(\"https://api.github.com/events\"))\n```\n\nSince `requests.post` and `requests.put` both take a `data: geny.Writable`\nparameter, you can even chain requests together, taking the data returned from\none HTTP request and feeding it into another:\n\n```scala\nos.write(\n  os.pwd / \"chained.json\",\n  requests.post.stream(\n    \"https://httpbin.org/post\",\n    data = requests.get.stream(\"https://api.github.com/events\")\n  )\n)\n```\n\n`requests.*.stream` should make it easy for you to work with data\ntoo big to fit in memory, while still benefiting from most of Requests' friendly\n\u0026 intuitive API.\n\n## Handling JSON\n\nRequests does not provide any built-in JSON support, but you can easily use a\nthird-party JSON library to work with it. This example shows how to use\n[uJson](https://com-lihaoyi.github.io/upickle/) talk to a HTTP endpoint that requires a\nJSON-formatted body, either using `upickle.default.stream`:\n\n```scala\nrequests.post(\n  \"https://api.github.com/some/endpoint\",\n  data = upickle.default.stream(Map(\"user-agent\" -\u003e \"my-app/0.0.1\"))\n)\n```\n\nOr by constructing `ujson.Value`s directly\n\n```scala\nrequests.post(\n  \"https://api.github.com/some/endpoint\",\n  data = ujson.Obj(\"user-agent\" -\u003e \"my-app/0.0.1\")\n)\n```\n\nIn both cases, the upload occurs efficiently in a streaming fashion, without\nmaterializing the entire JSON blob in memory.\n\nIt is equally easy ot use uJson to deal with JSON returned in the response from\nthe server:\n\n```scala\nval r = requests.get(\"https://api.github.com/events\")\n\nval json = ujson.read(r.text())\n\njson.arr.length\n// 30\n\njson.arr(0).obj.keys\n// Set(\"id\", \"type\", \"actor\", \"repo\", \"payload\", \"public\", \"created_at\")\n```\n\nWhile Requests-Scala doesn't come bundled with JSON functionality, it is trivial\nto use it together with any other 3rd party JSON library (I like\n[uJson](https://github.com/com-lihaoyi/upickle)) So just pick whatever library you\nwant.\n\n## Multipart Uploads\n\n```scala\nval r = requests.post(\n  \"http://httpbin.org/post\",\n  data = requests.MultiPart(\n    requests.MultiItem(\"name\", new java.io.File(\"build.sc\"), \"file.txt\"),\n    // you can upload strings, and file name is optional\n    requests.MultiItem(\"name2\", \"Hello\"),\n    // bytes arrays are ok too\n    requests.MultiItem(\"name3\", Array[Byte](1, 2, 3, 4))\n  )\n)\n```\n\nMultipart uploads are done by passing `requests.MultiPart`/`requests.MultiItem`\nto the `data` parameter. Each `MultiItem` needs a name and a data-source, which\ncan be a `String`, `Array[Byte]`, `java.io.File`, or `java.nio.file.Path`. Each\n`MultiItem` can optionally take a file name that will get sent to the server\n\n## Misc Configuration\n\nEarlier you already saw how to use the `params` and `data` arguments. Apart from\nthose, the `requests.get` method takes in a lot of arguments you can use to\nconfigure it, e.g. passing in custom headers:\n\n### Custom Headers\n\n```scala\nrequests.get(\n  \"https://api.github.com/some/endpoint\",\n  headers = Map(\"user-agent\" -\u003e \"my-app/0.0.1\")\n)\n```\n\nTo pass in a single header multiple times, you can pass them as a comma separated list:\n\n```scala\nrequests.get(\n  \"https://api.github.com/some/endpoint\",\n  headers = Map(\"user-agent\" -\u003e \"my-app/0.0.1,other-app/0.0.2\")\n)\n```\n\n### Timeouts\n\n`readTimeout`s and `connectTimeout`s:\n\n```scala\nrequests.get(\"https://httpbin.org/delay/1\", readTimeout = 10)\n// TimeoutException\n\nrequests.get(\"https://httpbin.org/delay/1\", readTimeout = 1500)\n// ok\n\nrequests.get(\"https://httpbin.org/delay/3\", readTimeout = 1500)\n// TimeoutException\n```\n\n```scala\nrequests.get(\"https://httpbin.org/delay/1\", connectTimeout = 10)\n// TimeoutException\n\nrequests.get(\"https://httpbin.org/delay/1\", connectTimeout = 1500)\n// ok\n\nrequests.get(\"https://httpbin.org/delay/3\", connectTimeout = 1500)\n// ok\n```\n\n### Compression\n\nConfiguration for compressing the request `data` upload with Gzip or Deflate via\nthe `compress` parameter:\n\n```scala\nrequests.post(\n  \"https://httpbin.org/post\",\n  compress = requests.Compress.None,\n  data = \"Hello World\"\n)\n\nrequests.post(\n  \"https://httpbin.org/post\",\n  compress = requests.Compress.Gzip,\n  data = \"I am cow\"\n)\n\nrequests.post(\n  \"https://httpbin.org/post\",\n  compress = requests.Compress.Deflate,\n  data = \"Hear me moo\"\n)\n```\n\nOr to disabling the de-compression of the response `data` being downloaded via\nthe `autoCompress` parameter, in case you want the un-compressed data blob for\nwhatever reason:\n\n```scala\nrequests.get(\"https://httpbin.org/gzip\").contents.length\n// 250\n\nrequests.get(\"https://httpbin.org/gzip\", autoDecompress=false).contents.length\n// 201\n\n\nrequests.get(\"https://httpbin.org/deflate\").contents.length\n// 251\n\nrequests.get(\"https://httpbin.org/deflate\", autoDecompress=false).contents.length\n// 188\n```\n\nNote that by default, compression of fixed-size in-memory input (`String`s,\n`Array[Byte]`s, ...) buffers up the compressed data in memory before uploading\nit. Compression of unknown-length/not-in-memory data (files, `InputStream`s,\n...) doesn't perform this buffering and uses chunked transfer encoding, as\nnormal. If you want to avoid buffering in memory and are willing to use chunked\ntransfer encoding for in-memory data, wrap it in an inputstream (e.g.\n`Array[Byte]` can be wrapped in a `ByteArrayInputStream`)\n\n### Cookies\n\nYou can take the cookies that result from one HTTP request and pass them into a\nsubsequent HTTP request:\n\n```scala\nval r = requests.get(\"https://httpbin.org/cookies/set?freeform=test\")\n\nr.cookies\n// Map(\"freeform\" -\u003e freeform=test)\n```\n```scala\n\nval r2 = requests.get(\"https://httpbin.org/cookies\", cookies = r.cookies)\n\nr2.text()\n// {\"cookies\":{\"freeform\":\"test\"}}\n```\n\nThis is a common pattern, e.g. to maintain an authentication/login session\nacross multiple requests. However, it may be easier to instead use Sessions...\n\n\n### Redirects\n\nRequests handles redirects automatically for you, up to a point:\n\n```scala\nval r = requests.get(\"http://www.github.com\")\n\nr.url\n// https://github.com/\n\nr.history\n// Some(Response(\"https://www.github.com\", 301, \"Moved Permanently\", ...\n\nr.history.get.history\n// Some(Response(\"http://www.github.com\", 301, \"Moved Permanently\", ...\n\nr.history.get.history.get.history\n// None\n```\n\nAs you can see, the request to `http://www.github.com` was first redirected to\n`https://www.github.com`, and then to `https://github.com/`. Requests by default\nonly follows up to 5 redirects in a row, though this is configurable via the\n`maxRedirects` parameter:\n\n```scala\nval r0 = requests.get(\"http://www.github.com\", maxRedirects = 0)\n// Response(\"http://www.github.com\", 301, \"Moved Permanently\", ...\n\nr0.history\n// None\n\nval r1 = requests.get(\"http://www.github.com\", maxRedirects = 1)\n// Response(\"http://www.github.com\", 301, \"Moved Permanently\", ...\n\nr1.history\n// Some(Response(\"http://www.github.com\", 301, \"Moved Permanently\", ...\n\nr1.history.get.history\n// None\n```\n\nAs you can see, you can use `maxRedirects = 0` to disable redirect handling\ncompletely, or use another number to control how many redirects Requests follows\nbefore giving up.\n\nAll of the intermediate responses in a redirect chain are available in a\nResponse's `.history` field; each `.history` points 1 response earlier, forming\na linked list of `Response` objects until the earliest response has a value of\n`None`. You can crawl up this linked list if you want to inspect the headers or\nother metadata of the intermediate redirects that brought you to your final value.\n\n### Client Side Certificates\n\nTo use client certificate you need a PKCS 12 archive with private key and certificate.\n\n```scala\nrequests.get(\n  \"https://client.badssl.com\",\n  cert = \"./badssl.com-client.p12\"\n)\n```\n\nIf the p12 archive is password protected you can provide a second parameter:\n\n```scala\nrequests.get(\n  \"https://client.badssl.com\",\n  cert = (\"./badssl.com-client.p12\", \"password\")\n)\n```\n\nFor test environments you may want to combine `cert` with the `verifySslCerts = false` option (if you have self signed SSL certificates on test servers).\n\n```scala\nrequests.get(\n  \"https://client.badssl.com\",\n  cert = (\"./badssl.com-client.p12\", \"password\"),\n  verifySslCerts = false\n)\n```\n\nYou can also use a sslContext to provide a more customized ssl configuration\n\n```scala\nval sslContext: SSLContext = //initialized sslContext\n\nrequests.get(\n  \"https://client.badssl.com\",\n  sslContext = sslContext\n)\n```\n\n## Sessions\n\nA `requests.Session` automatically handles sending/receiving/persisting cookies\nfor you across multiple requests:\n\n```scala\nval s = requests.Session()\n\nval r = s.get(\"https://httpbin.org/cookies/set?freeform=test\")\n\nval r2 = s.get(\"https://httpbin.org/cookies\")\n\nr2.text()\n// {\"cookies\":{\"freeform\":\"test\"}}\n```\n\nIf you want to deal with a website that uses cookies, it's usually easier to use\na `requests.Session` rather than passing around `cookie` variables manually.\n\nApart from persisting cookies, sessions are also useful for consolidating common\nconfiguration that you want to use across multiple requests, e.g. custom\nheaders, cookies or other things:\n\n```scala\nval s = requests.Session(\n  headers = Map(\"x-special-header\" -\u003e \"omg\"),\n  cookieValues = Map(\"cookie\" -\u003e \"vanilla\")\n)\n\nval r1 = s.get(\"https://httpbin.org/cookies\")\n\nr1.text()\n// {\"cookies\":{\"cookie\":\"vanilla\"}}\n\nval r2 = s.get(\"https://httpbin.org/headers\")\n\nr2.text()\n// {\"headers\":{\"X-Special-Header\":\"omg\", ...}}\n```\n\n## Why Requests-Scala?\n\nThere is a whole zoo of HTTP clients in the Scala ecosystem. Akka-http, Play-WS,\nSTTP, HTTP4S, Scalaj-HTTP, RosHTTP, Dispatch. Nevertheless, none of them come\nclose to the ease and weightlessness of using Kenneth Reitz's\n[Requests](https://requests.readthedocs.io/en/latest/) library: too many implicits,\noperators, builders, monads, and other things.\n\nWhen I want to make a HTTP request, I do not want to know about\n`.unsafeRunSync`, infix methods like `svc OK as.String`, or define implicit\n`ActorSystem`s, `ActorMaterializer`s, and `ExecutionContext`s. So far\n[sttp](https://github.com/softwaremill/sttp) and\n[scalaj-http](https://github.com/scalaj/scalaj-http) come closest to what I\nwant, but still fall short: both still use a pattern of fluent builders that to\nme doesn't fit how I think when making a HTTP request. I just want to call one\nfunction to make a HTTP request, and get back my HTTP response.\n\nMost people will never reach the scale that asynchrony matters, and most of\nthose who do reach that scale will only need it in a small number of specialized\nplaces, not everywhere.\n\nCompare the getting-started code necessary for Requests-Scala against some other\ncommon Scala HTTP clients:\n```scala\n// Requests-Scala\nval r = requests.get(\n  \"https://api.github.com/search/repositories\",\n  params = Map(\"q\" -\u003e \"http language:scala\", \"sort\" -\u003e \"stars\")\n)\n\nr.text()\n// {\"login\":\"lihaoyi\",\"id\":934140,\"node_id\":\"MDQ6VXNlcjkzNDE0MA==\",...\n```\n```scala\n// Akka-Http\nimport akka.actor.ActorSystem\nimport akka.http.scaladsl.Http\nimport akka.http.scaladsl.model._\nimport akka.stream.ActorMaterializer\n\nimport scala.concurrent.Future\nimport scala.util.{ Failure, Success }\n\nimplicit val system = ActorSystem()\nimplicit val materializer = ActorMaterializer()\n// needed for the future flatMap/onComplete in the end\nimplicit val executionContext = system.dispatcher\n\nval responseFuture: Future[HttpResponse] = Http().singleRequest(HttpRequest(uri = \"http://akka.io\"))\n\nresponseFuture\n  .onComplete {\n    case Success(res) =\u003e println(res)\n    case Failure(_)   =\u003e sys.error(\"something wrong\")\n  }\n\n```\n\n```scala\n// Play-WS\n\nimport akka.actor.ActorSystem\nimport akka.stream.ActorMaterializer\nimport play.api.libs.ws._\nimport play.api.libs.ws.ahc._\n\nimport scala.concurrent.Future\n\nimport DefaultBodyReadables._\nimport scala.concurrent.ExecutionContext.Implicits._\n\n// Create Akka system for thread and streaming management\nimplicit val system = ActorSystem()\nimplicit val materializer = ActorMaterializer()\n\n// Create the standalone WS client\n// no argument defaults to a AhcWSClientConfig created from\n// \"AhcWSClientConfigFactory.forConfig(ConfigFactory.load, this.getClass.getClassLoader)\"\nval wsClient = StandaloneAhcWSClient()\n\nwsClient.url(\"http://www.google.com\").get()\n  .map { response ⇒\n    val statusText: String = response.statusText\n    val body = response.body[String]\n    println(s\"Got a response $statusText\")\n  }.\n  andThen { case _ =\u003e wsClient.close() }\n  andThen { case _ =\u003e system.terminate() }\n\n```\n```scala\n// Http4s\nimport org.http4s.client.dsl.io._\nimport org.http4s.headers._\nimport org.http4s.MediaType\n\nval request = GET(\n  Uri.uri(\"https://my-lovely-api.com/\"),\n  Authorization(Credentials.Token(AuthScheme.Bearer, \"open sesame\")),\n  Accept(MediaType.application.json)\n)\n\nhttpClient.expect[String](request)\n```\n```scala\n// sttp\nimport sttp.client3._\n\nval request = basicRequest.response(asStringAlways)\n  .get(uri\"https://api.github.com/search\"\n    .addParams(Map(\"q\" -\u003e \"http language:scala\", \"sort\" -\u003e \"stars\")))\n\nval backend = HttpURLConnectionBackend()\nval response = backend.send(request)\n\nprintln(response.body)\n```\n```scala\n// Dispatch\nimport dispatch._, Defaults._\nval svc = url(\"http://api.hostip.info/country.php\")\nval country = Http.default(svc OK as.String)\n```\n\nThe existing clients require a complex mix of imports, implicits, operators, and\nDSLs. The goal of Requests-Scala is to do away with all of that: your HTTP\nrequest is just a function call that takes parameters; that is all you need to\nknow.\n\nAs it turns out, Kenneth Reitz's Requests is\n[not a lot of code](https://github.com/requests/requests/tree/main/requests).\nMost of the heavy lifting is done in other libraries, and his library is a just\nthin-shim that makes the API 10x better. Similarly, it turns out on the JVM most of the\nheavy lifting is also done for you. There have always been options, but\nsince JDK 11 a decent HTTP client is provided in the standard library.\n\nGiven that's the case, how hard can it be to port over a dozen Python files to\nScala? This library attempts to do that: class by class, method by method,\nkeyword-argument by keyword-argument. Not everything has been implemented yet,\nsome things differ (some avoidably, some unavoidably), and it's nowhere near as\npolished, but you should definitely try it out as the HTTP client for your next\ncodebase or project!\n\n## Changelog\n\n### 0.9.0\n\n- Use JDK 11 HttpClient ([#158](https://github.com/com-lihaoyi/requests-scala/pull/158)). Note\n  that this means we are dropping compatibility with JDK 8, and will require JDK 11 and above\n  going forward. People who need to use JDK 8 can continue using version 0.8.3\n\n### 0.8.3\n\n- Fix handling of HTTP 304 ([#159](https://github.com/com-lihaoyi/requests-scala/pull/159))\n\n### 0.8.2\n\n- fix: content type header not present in multipart item ([#154](https://github.com/com-lihaoyi/requests-scala/pull/154))\n\n### 0.8.0\n\n- Update Geny to 1.0.0 [#120](https://github.com/com-lihaoyi/requests-scala/pull/120)\n\n### 0.7.1\n\n- Fix issue with data buffers not being flushed when compression is enabled [#108](https://github.com/com-lihaoyi/requests-scala/pull/108)\n\n### 0.7.0\n\n- Allow `requests.send(method)(...)` to dynamically choose a HTTP method [#94](https://github.com/com-lihaoyi/requests-scala/pull/94)\n- Avoid crashing on gzipped HEAD requests [#95](https://github.com/com-lihaoyi/requests-scala/pull/95)\n- All exceptions now inherit from a `RequestsException` base class\n\n### 0.6.7\n\n- Add support for Scala 3.0.0-RC2\n\n### 0.6.5\n\n- `requests.Response` now implements the `geny.Readable` interface, and can be\n  directly passed to compatible APIs like `ujson.read` or `os.write`\n\n- Add support for custom SSL certs\n\n- Allow body content for DELETE requests\n\n### 0.5.1\n\n- Made `requests.{get,post,put,delete,head,options,patch}.stream` return a\n  [Readable](https://github.com/lihaoyi/geny#readable), allowing upickle and\n  fastparse to operate directly on the streaming input\n\n### 0.4.7\n\n- `requests.{get,post,put,delete,head,options,patch}` now throw a\n  `requests.RequestFailedException(val response: Response)` if a non-2xx status\n  code is received. You can disable throwing the exception by passing in\n  `check = false`\n- `requests.{get,post,put,delete,head,options,patch}.stream` now returns a\n  [Writable](https://github.com/lihaoyi/geny#writable) instead of taking\n  callbacks.\n\n### 0.3.0\n\n- Support for uploading\n  [geny.Writable](https://github.com/lihaoyi/geny#writable) data types in\n  request bodies.\n\n### 0.2.0\n\n- Support for Scala 2.13.0 final\n\n### 0.1.9\n\n- Support `PATCH` and other verbs\n\n### 0.1.8\n\n- Support for `Bearer` token auth\n\n### 0.1.7\n\n- `RequestBlob` headers no longer over-write session headers\n\n### 0.1.6\n\n- Allow POSTs to take URL parameters\n- Return response body for all 2xx response codes\n- Always set `Content-Length` to 0 when request body is empty\n\n### 0.1.5\n\n- First Release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcom-lihaoyi%2Frequests-scala","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcom-lihaoyi%2Frequests-scala","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcom-lihaoyi%2Frequests-scala/lists"}