{"id":38870457,"url":"https://github.com/johntalton/http-util","last_synced_at":"2026-03-01T05:25:50.647Z","repository":{"id":331715598,"uuid":"1131885099","full_name":"johntalton/http-util","owner":"johntalton","description":"Set of HTTP helper Utilities","archived":false,"fork":false,"pushed_at":"2026-02-26T10:06:21.000Z","size":128,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-26T16:40:41.384Z","etag":null,"topics":["http","http2","stream"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/johntalton.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-10T22:08:19.000Z","updated_at":"2026-02-26T10:04:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/johntalton/http-util","commit_stats":null,"previous_names":["johntalton/http-util"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/johntalton/http-util","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johntalton%2Fhttp-util","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johntalton%2Fhttp-util/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johntalton%2Fhttp-util/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johntalton%2Fhttp-util/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/johntalton","download_url":"https://codeload.github.com/johntalton/http-util/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johntalton%2Fhttp-util/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29951650,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T18:42:55.706Z","status":"ssl_error","status_checked_at":"2026-02-28T18:42:48.811Z","response_time":90,"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":["http","http2","stream"],"created_at":"2026-01-17T14:29:20.179Z","updated_at":"2026-03-01T05:25:50.619Z","avatar_url":"https://github.com/johntalton.png","language":"JavaScript","readme":"# http-util\n\nSet of utilities to aid in building from-scratch [node:http2](https://nodejs.org/docs/latest/api/http2.html) stream compatible services.\n\n- [Header parsers](#header-parsers)\n- [Stream Response methods](#response)\n- [Body parser](#body)\n\n## Header Parsers\n### From Client:\n- Accept Encoding - `parse` and `select` based on server/client values\n- Accept Language - `parse` and `select`\n- Accept - `parse` and `select`\n\n- Content Type - returns structured data object for use with Body/etc\n- Forwarded - `parse` with select-right-most helper\n- Multipart - parse into `FormData`\n- Content Disposition - for use inside of Multipart\n- Conditionals - Etag / FixDate for IfMatch, IfModifiedSince etc\n\n### Server Sent:\n- Rate Limit\n- Server Timing\n\n\n```javascript\nimport {\n  Accept,\n  MIME_TYPE_JSON,\n  MIME_TYPE_TEXT\n} from '@johntalton/http-util/headers'\n\n// assuming our path/method/server supports content in json or text\nconst supportedType = [ MIME_TYPE_JSON, MIME_TYPE_TEXT ]\n\n// from request.header.accept (client prefers json)\nconst acceptHeader = 'application/json;q=.5, */*;q.4'\n\nconst bestMatchingType = Accept.select(acceptHeader, supportedType)\n// bestMatchingType === 'application/json'\n```\n\n## Response\n\nAll responders take in a `stream` as well as a metadata object to hint on servername and origin strings etc.\n\n- [`sendAccepted`](#responseaccepted)\n- [`sendConflict`](#responseconflict)\n- [`sendContentTooLarge`](#)\n- [`sendCreated`](#responsecreated)\n- [`sendError`](#responseerror) - 500\n- [`sendGone`](#)\n- [`sendImATeapot`](#)\n- [`sendInsufficientStorage`](#)\n- [`sendJSON_Encoded`](#responsejson) - Standard Ok response with encoding\n- [`sendMovedPermanently`](#)\n- [`sendMultipleChoices`](#)\n- [`sendNoContent`](#responsenocontent)\n- [`sendNotAcceptable`](#responsenotacceptable)\n- [`sendNotAllowed`](#responsenotallowed) - Method not supported / allowed\n- [`sendNotFound`](#responsenotfound) - 404\n- [`sendNotImplemented`](#responsenotimplemented)\n- [`sendNotModified`](#responsenotmodified)\n- [`sendPartialContent`](#)\n- [`sendPreconditionFailed`](#responsepreconditionfailed)\n- [`sendPreflight`](#responsepreflight) - Response to OPTIONS with CORS headers\n- [`sendRangeNotSatisfiable`](#)\n- [`sendSeeOther`](#)\n- [`sendTemporaryRedirect`](#)\n- [`sendTimeout`](#responsetimeout)\n- [`sendTooManyRequests`](#responsetoomanyrequests) - Rate limit response (429)\n- [`sendTrace`](#responsetrace)\n- [`sendUnauthorized`](#responseunauthorized) - Unauthorized\n- [`sendUnavailable`](#responseunavailable)\n- [`sendUnprocessable`](#responseunprocessable)\n- [`sendUnsupportedMediaType`](#responseunsupportedmediatype)\n- [`sendSSE`](#responsesse) - SSE header (leave the `stream` open)\n\nResponses allow for optional CORS headers as well as Server Timing meta data.\n\n## Response Object\n\nThe response methods `sendXYZ` are also wrapped in a `Response` object which can make imports simpler and help organize code.\n\n```js\nimport { Response } from '@johntalton/http-util/response/object'\n\n// ... sendNotFound becomes .notFound\nResponse.notFound(stream, meta)\n```\n\n## Body\n\nThe `requestBody` method returns a `fetch`-like response.  Including methods `blob`, `arrayBuffer`, `bytes`, `text`, `formData`, `json` as well as a `body` as a `ReadableStream`.\n\nThe return is a deferred response that does NOT consume the `steam` until calling one of the above methods.\n\nOptional `byteLimit`, `contentLength` and `contentType` can be provided to hint the parser, as well as a `AbortSignal` to abandoned the reader.\n\n```js\nimport { requestBody } from '@johntalton/http-util/body'\n\nconst signal = // from someplace like a timeout for the overall request\n\n// limit time and size for the body\n// note: this does not consume the stream\nconst futureBody = requestBody(stream, {\n  byteLimit: 1000 * 1000,\n  signal\n})\n\n// ... a few moments later ...\n\n// consume the stream\nconst body = futureBody.json()\n\n```\n\n## Response method API\n\nAll response methods take in the `stream` and a `meta` property.\n\nAdditional parameters are specific to each return type.\n\nEach return type semantic may also expose header (in addition to the standard headers) to the calling code as needed.\n\nSome common objects can be passed such as `EtagItem`, `CacheControlOptions` and `Metadata` have their own structure.\n\nMany parameters accept `undefined` to skip/ignore the usage\n\n### Response.accepted\n\nParameters:\n- stream\n- meta\n\n### Response.conflict\n\nParameters:\n- stream\n- meta\n\n\n### Response.created\n\nParameters:\n- stream\n- location\n- etag\n- meta\n\nAdditional Exposed Headers:\n- location\n\n### Response.error\n\nParameters:\n- stream\n- meta\n\n\n### Response.json\n\nParameters:\n- stream\n- object\n- encoding - undefined | 'identity' | 'br' | 'gzip' | 'deflate' | 'zstd'\n- etag\n- age\n- cacheControl\n- supportedQueryTypes - undefined | Array of supported query types\n- meta\n\nAdditional Exposed Headers\n- age\n- accept-query\n\n### Response.noContent\n\nParameters:\n- stream\n- etag\n- meta\n\n### Response.notAcceptable\n\nParameters:\n- stream\n- supportedTypes\n- meta\n\n### Response.notAllowed\n\nParameters:\n- stream\n- methods - Array of allowed methods\n- meta\n\nAdditional Exposed Headers:\n- allow\n\n### Response.notFound\n\nParameters:\n- stream\n- message\n- meta\n\n### Response.notImplemented\n\nParameters:\n- stream\n- message\n- meta\n\n### Response.notModified\n\nParameters:\n- stream\n- etag\n- age\n- cacheControl\n- meta\n\nAdditional Exposed Headers:\n- age\n\n### Response.preconditionFailed\n\nParameters:\n- stream\n- meta\n\n### Response.preflight\n\nParameters:\n- stream\n- methods\n- supportedQueryTypes - undefined | Array of supported types\n- meta\n\nAdditional Exposed Headers:\n- accept-query\n\n### Response.sse\n\nParameters:\n- stream\n- meta\n\n\n### Response.timeout\n\nParameters:\n- stream\n- meta\n\n\n### Response.tooManyRequests\n\nParameters:\n- stream\n- limitInfo - `RateLimitInfo`\n- policies - Array of `RateLimitPolicyInfo`\n- meta\n\nAdditional Exposed Headers:\n- retry-after\n- rate-limit\n- rate-limit-policy\n\n### Response.trace\n\nParameters:\n- stream\n- method\n- url\n- headers\n- meta\n\n### Response.unauthorized\n\nParameters:\n- stream\n- meta\n\n\n### Response.unavailable\n\nParameters:\n- stream\n- message\n- retryAfter\n- meta\n\nAdditional Exposed Headers:\n- retry-after\n\n### Response.unprocessable\n\nParameters:\n- stream\n- meta\n\n### Response.unsupportedMediaType\n\nParameters:\n- stream\n- acceptableMediaTypes\n- supportedQueryTypes\n- meta\n\nAdditional Exposed Headers:\n- accept-query\n- accept-post","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohntalton%2Fhttp-util","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjohntalton%2Fhttp-util","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohntalton%2Fhttp-util/lists"}