{"id":19265977,"url":"https://github.com/keq-request/keq","last_synced_at":"2026-01-29T10:04:31.502Z","repository":{"id":37702036,"uuid":"244151916","full_name":"keq-request/keq","owner":"keq-request","description":"Request API write by Typescript for flexibility, readability, and a low learning curve","archived":false,"fork":false,"pushed_at":"2026-01-15T11:00:49.000Z","size":2889,"stargazers_count":19,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-17T04:48:17.877Z","etag":null,"topics":["axios","got","http","http-client","https","javascript","js","koa","request","superagent","ts","typescript"],"latest_commit_sha":null,"homepage":"https://keq-request.github.io/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/keq-request.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":null,"patreon":"val_istar_guo","open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2020-03-01T13:13:22.000Z","updated_at":"2025-09-17T08:06:22.000Z","dependencies_parsed_at":"2022-09-20T05:15:38.175Z","dependency_job_id":"ee3de50d-9f86-4643-8064-437edd4e8f75","html_url":"https://github.com/keq-request/keq","commit_stats":null,"previous_names":["val-istar-guo/keq"],"tags_count":224,"template":false,"template_full_name":null,"purl":"pkg:github/keq-request/keq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keq-request%2Fkeq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keq-request%2Fkeq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keq-request%2Fkeq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keq-request%2Fkeq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/keq-request","download_url":"https://codeload.github.com/keq-request/keq/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keq-request%2Fkeq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28809344,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T07:41:26.337Z","status":"ssl_error","status_checked_at":"2026-01-27T07:41:08.776Z","response_time":168,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["axios","got","http","http-client","https","javascript","js","koa","request","superagent","ts","typescript"],"created_at":"2024-11-09T20:00:29.441Z","updated_at":"2026-01-29T10:04:31.485Z","avatar_url":"https://github.com/keq-request.png","language":"TypeScript","readme":"\u003cp align=\"center\" style=\"padding-top: 40px\"\u003e\n  \u003cimg src=\"./images/logo.svg?sanitize=true\" width=\"120\" alt=\"logo\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\" style=\"text-align: center\"\u003eKEQ\u003c/h1\u003e\n\n[npm]: https://www.npmjs.com/package/keq\n\n[![version](https://img.shields.io/npm/v/keq.svg?logo=npm\u0026style=for-the-badge)][npm]\n[![downloads](https://img.shields.io/npm/dm/keq.svg?logo=npm\u0026style=for-the-badge)][npm]\n[![dependencies](https://img.shields.io/librariesio/release/npm/keq?logo=npm\u0026style=for-the-badge)][npm]\n[![license](https://img.shields.io/npm/l/keq.svg?logo=github\u0026style=for-the-badge)][npm]\n[![Codecov](https://img.shields.io/codecov/c/gh/keq-request/keq?logo=codecov\u0026token=PLF0DT6869\u0026style=for-the-badge)](https://codecov.io/gh/keq-request/keq)\n\n\n[Fetch MDN]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch\n[Headers MDN]: https://developer.mozilla.org/en-US/docs/Web/API/Headers\n[Response MDN]: https://developer.mozilla.org/en-US/docs/Web/API/Response\n[FormData MDN]: https://developer.mozilla.org/en-US/docs/Web/API/FormData\n[URL MDN]: https://developer.mozilla.org/en-US/docs/Web/API/URL\n\n[Document EN]: https://keq-request.github.io/guide/introduction\n[Document CN]: https://keq-request.github.io/zh/guide/introduction\n\nKeq is a request API write by Typescript for flexibility, readability, and a low learning curve. It also works with Node.js!\nKeq wraps the Fetch APIs, adding chain calls and middleware functions.\n\n\n[**Document**][Document EN] | [**中文文档**][Document CN]\n\n## Simple Usage\n\n\n\u003c!-- usage --\u003e\n\n### Send Request\n\nA request can be initiated by invoking the appropriate method on the request object,\nthen calling `.then()` (or `.end()` or `await`) to send the request.\nFor example a simple GET request:\n\n```javascript\nimport { request } from \"keq\";\n\nconst body = await request\n  .get(\"/search\")\n  .set(\"X-Origin-Host\", \"https://example.com\")\n  .query(\"key1\", \"value1\");\n```\n\nRequest can be initiated by:\n\n```javascript\nimport { request } from \"keq\";\n\nconst body = await request({\n  url: \"/search\",\n  method: \"get\",\n});\n```\n\nAbsolute URLs can be used.\nIn web browsers absolute URLs work only if the server implements CORS.\n\n```javascript\nimport { request } from \"keq\";\n\nconst body = await request.get(\"https://example.com/search\");\n```\n\n**DELETE**, **HEAD**, **PATCH**, **POST**, and **PUT** requests can also be used, simply change the method name:\n\n```javascript\nimport { request } from \"keq\";\n\nawait request.head(\"https://example.com/search\");\nawait request.patch(\"https://example.com/search\");\nawait request.post(\"https://example.com/search\");\nawait request.put(\"https://example.com/search\");\nawait request.delete(\"https://example.com/search\");\nawait request.del(\"https://example.com/search\");\n```\n\n\u003e `.del()` is the alias of `.delete()`.\n\n`Keq` will parse `body` according to the `Content-Type` of [`Response`][Response MDN]\nand return `undefined` if `Content-Type` not found.\nAdd invoke `.resolveWith('response')` to get the origin [`Response`][Response MDN] Object.\n\n```javascript\nimport { request } from \"keq\";\n\nconst response = await request\n  .get(\"http://test.com\")\n  .resolve('response')\n\nconst body = await response.json();\n```\n\nWe will introduce `resolveWith` in more detail later.\n\n###### `Keq` won't auto parse body, if response.status is 204. The HTTP 204 No Content success status response code indicates that server has fulfilled the request but does not need to return an entity-body, and might want to return updated meta information\n\n### Setting header fields\n\nSetting header fields is simple, invoke `.set()` with a field name and value:\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  .get(\"/search\")\n  .set(\"X-Origin-Host\", \"https://example.com\")\n  .set(\"Accept\", \"application/json\");\n```\n\nYou may also pass an object or `Headers` to set several fields in a single call:\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  .get(\"/search\")\n  .set({\n    \"X-Origin-Host\": \"https://example.com\",\n    Accept: \"application/json\",\n  });\n```\n\n### Request query\n\nThe `.query()` method accepts objects,\nwhich when used with the GET method will form a query-string.\nThe following will produce the path `/search?query=Manny\u0026range=1..5\u0026order=desc.`\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  .get(\"/search\")\n  .query({ query: \"Manny\" })\n  .query({ range: \"1..5\" })\n  .query(\"order\", \"desc\");\n```\n\nOr as a single object:\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  .get(\"/search\")\n  .query({ query: \"Manny\", range: \"1..5\", order: \"desc\" });\n```\n\n### Request routing parameters\n\nThe `.params()` method accepts key and value, which when used for the request with routing parameters.\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  // request to /users/jack/books/kafka\n  .get(\"/users/:userName/books/{bookName}\")\n  .params(\"userName\", 'jack');\n  .params(\"bookName\", \"kafka\");\n  // or invoke with an object\n  .params({\n    \"userName\": \"jack\",\n    \"bookName\": \"kafka\"\n  })\n```\n\n### JSON Request\n\nA typical JSON POST request might look a little like the following,\nwhere we set the `Content-Type` header field appropriately:\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  .post(\"/user\")\n  .set(\"Content-Type\", \"application/json\")\n  .send({ name: \"tj\", pet: \"tobi\" });\n```\n\nWhen passed an `object` to `.send()`, it will auto set `Content-Type` to `application/json`\n\n### x-www-form-urlencoded Request\n\nA typical Form POST request might look a little like the following:\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  .post(\"/user\")\n  .type(\"form\")\n  .send({ name: \"tj\", pet: \"tobi\" })\n  .send(\"pet=tobi\");\n```\n\nTo send the data as `application/x-www-form-urlencoded` simply invoke `.type()` with \"form\".\nWhen passed an `string` to `.send()`, it will auto set `Content-Type` to `application/x-www-form-urlencoded`.\n\n\u003e When calling `.send ()` multiple times, the value of `Content-Type` will only be set when the first calling `.send ()`.\n\n### Form-Data Request\n\nA typical Form POST request might look a little like the following:\n\n```javascript\nimport { request } from \"keq\";\n\nconst form = new FormData();\nform.append(\"name\", \"tj\");\nform.append(\"pet\", \"tobi\");\n\n// prettier-ignore\nawait request\n  .post(\"/user\")\n  .type(\"form-data\")\n  .send(form)\n```\n\nWhen passed an `FormData` object to `.send()`, it will auto set `Content-Type` to `multipart/form-data`.\n\nYou can append field by invoke `.field()` and `.attach()`\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  .post(\"/user\")\n  .field(\"name\", \"tj\")\n  .field(\"pet\", \"tobi\")\n  .attach(\"file\", new Blob([\"I am tj\"]));\n```\n\n### Setting the Content-Type\n\nThe obvious solution is to use the .set() method:\n\n```javascript\nimport { request } from \"keq\";\n\n// prettier-ignore\nawait request\n  .post(\"/user\")\n  .set(\"Content-Type\", \"application/json\")\n```\n\nAs a short-hand the .type() method is also available,\naccepting the canonicalized MIME type name complete with type/subtype,\nor simply the extension name such as \"xml\", \"json\", \"png\", etc:\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  .post(\"/user\")\n  .type(\"json\");\n```\n\n| **Shorthand**                                 | **Mime Type**                                                                                 |\n| :-------------------------------------------- | :-------------------------------------------------------------------------------------------- |\n| json, xml                                     | application/json, application/xml                                                             |\n| form                                          | application/x-www-form-urlencoded                                                             |\n| html, css                                     | text/html, text/css                                                                           |\n| form-data                                     | multipart/form-data                                                                           |\n| jpeg, bmp, apng, gif, x-icon, png, webp, tiff | image/jpeg, image/bmp, image/apng, image/gif, image/x-icon, image/png, image/webp, image/tiff |\n| svg                                           | image/svg+xml                                                                                 |\n\n### Set Request Redirect mode\n\nFollow redirect by default, invoke `.redirect(mode)` to set the redirect mode. Allow values are `\"error\"`, `\"manual\"` and `\"follow\"`.\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  .get(\"http://test.com\")\n  .redirect(\"manual\");\n```\n\n### Set Request Credentials And Mode\n\nThese two parameters are used to control cross-domain requests.\n\n```javascript\nimport { request } from \"keq\";\n\nawait request\n  .get(\"http://test.com\")\n  .mode(\"cors\")\n  .credentials(\"include\");\n```\n\n### resolve responseBody\n\nIt was mentioned before that `Keq` will automatically parses the response body.\nAnd we can control the parsing behavior by calling `.resolveWith(method)`.\nThere are multiple parsing methods for us to choose from\n\n| method                       | description                                                                                                                                                                                          |\n| :--------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `.resolveWith('intelligent')`  | It is the default method of `Keq`. This will returned `context.output` first if it exists. Otherwise return undefined when the response status is 204. Or return parsed response body according to the `Content-Type` of [`Response`][Response MDN]. |\n| `.resolveWith('response')`     | Return [`Response`][Response MDN].                                                                                                                                                                   |\n| `.resolveWith('text')`         | Return `response.text()`.                                                                                                                                                                            |\n| `.resolveWith('json')`         | Return `response.json()`.                                                                                                                                                                            |\n| `.resolveWith('form-data')`    | Return `response.formData()`.                                                                                                                                                                        |\n| `.resolveWith('blob')`         | Return `response.blob()`.                                                                                                                                                                            |\n| `.resolveWith('array-buffer')` | Return `response.arrayBuffer()`                                                                                                                                                                      |\n\n\nSee more usage in the [Document][Document EN]\n\n## Contributing \u0026 Development\n\nIf there is any doubt, it is very welcome to discuss the issue together.\n\n![github-keq-request-keq](https://count.getloli.com/@github-keq-request-keq?theme=asoul)\n","funding_links":["https://patreon.com/val_istar_guo"],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeq-request%2Fkeq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkeq-request%2Fkeq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeq-request%2Fkeq/lists"}