{"id":22687427,"url":"https://github.com/cablehead/go-http.sh","last_synced_at":"2025-03-29T15:43:14.496Z","repository":{"id":139658773,"uuid":"412603154","full_name":"cablehead/go-http.sh","owner":"cablehead","description":"Integrate a HTTP server into your shell pipelines","archived":false,"fork":false,"pushed_at":"2021-10-02T05:01:32.000Z","size":14,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-25T05:05:47.261Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cablehead.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2021-10-01T20:03:58.000Z","updated_at":"2022-08-03T21:01:53.000Z","dependencies_parsed_at":null,"dependency_job_id":"cafcd478-8d27-43b3-9a74-49fb640da6c0","html_url":"https://github.com/cablehead/go-http.sh","commit_stats":null,"previous_names":["cablehead/http.sh"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cablehead%2Fgo-http.sh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cablehead%2Fgo-http.sh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cablehead%2Fgo-http.sh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cablehead%2Fgo-http.sh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cablehead","download_url":"https://codeload.github.com/cablehead/go-http.sh/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246207491,"owners_count":20740723,"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-12-09T23:18:24.628Z","updated_at":"2025-03-29T15:43:14.470Z","avatar_url":"https://github.com/cablehead.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# http.sh\n\n*Integrate a HTTP server into your shell pipelines*\n\nNot quite sure where this is going to go, but... let's see!\n\nThis is a small CLI which writes HTTP requests to its STDOUT. It reads\npotential responses for these requests from its STDIN. That part is counter\nintuitive, but it works out well.\n\nThe expected usage is to pipe a subscription from a message queue into STDIN\nand to pipe STDOUT to a message queue writer.\n\n### Example usage\n\nYou can simulate a subscription from a message queue with `tail -F responses` and\nwriting to a message queue with `tee requests`.\n\nRun the HTTP server in window 1:\n\n```\n$ cp /dev/null responses \u0026\u0026 tail -F responses | go run . | tee requests | jq\n```\n\nCreate a request in window 2:\n\n```\n$ curl localhost:8080\n```\n\nNote the curl is hanging, waiting for a response. You should see the request\nin window 1's STDOUT.\n\n```json\n{\n  \"app\": \"http.request\",\n  \"content\": {\n    \"method\": \"GET\",\n    \"header\": {\n      \"Accept\": [\n        \"*/*\"\n      ],\n      \"User-Agent\": [\n        \"curl/7.64.1\"\n      ]\n    },\n    \"remote_addr\": \"[::1]:50503\",\n    \"uri\": \"/\",\n    \"body\": \"\",\n    \"request_id\": \"8684598f-2181-41fd-ba56-7c4b863e4fc8\"\n  }\n}\n```\n\nWe can use window 3 to create a response. So far, a response's schema is:\n\n- **request_id**: the request_id this is a response for\n- **body**: base64 encoded response body\n\nGrab [jo](https://github.com/jpmens/jo) if you don't have it, it's great. We\ncan use it to build a response and then write that to `responses` which is\nbeing piped to window 1's STDIN.\n\n```\n$ jo request_id=8684598f-2181-41fd-ba56-7c4b863e4fc8 body=\"$(echo oh hai | base64)\" | \\\n    tee -a responses\n```\n\n```json\n{\n  \"request_id\": \"8684598f-2181-41fd-ba56-7c4b863e4fc8\",\n  \"body\": \"b2ggaGFpCg==\"\n}\n```\n\nYou should see the curl in window 2 return with `oh hai`. The response is logged by the HTTP server in window 1:\n\n```json\n{\n  \"app\": \"http.response.log\",\n  \"content\": {\n    \"took\": 32263.4,\n    \"response\": {\n      \"body\": \"b2ggaGFpCg==\",\n      \"request_id\": \"8684598f-2181-41fd-ba56-7c4b863e4fc8\",\n    }\n  }\n}\n```\n\nNote how long the request `took`. That time is in milliseconds, so in this\ncase, 32s. I need to get faster with `jo`!  We can automate reading requests\nand writing responses.\n\nRun this snippet in window 3. It tails `requests`, using `jq` to select only\n`http.request` messages, as the server also emits `http.repsonse.log` messages.\nThe actual request is under the `content` key.  `jq` is used to generate the\nresponse schema, relaying the `request_id` and generating a base64 encoded\n`body` based on the `uri` of the request.\n\n```\n# unbuffer jq by default. Life works out better that way.\n$ alias jq='jq --unbuffered'\n$ tail -F -n1 requests | jq -c '\n    select(.app == \"http.request\") |\n    .content |\n    {request_id, \"body\": (\"oh hai. your path is: \\(.uri)\\n\" | @base64)}\n' | tee -a responses\n```\n\nIn window 2, `curl` the server again. It should return immediately now.\n\n```\n$ curl localhost:8080\noh hai. your path is: /\n```\n\nIn window 3 you should see something like this. `took` is 0.4ms.\n\n```json\n{\n  \"app\": \"http.response.log\",\n  \"content\": {\n    \"took\": 0.4,\n    \"response\": {\n      \"body\": \"b2ggaGFpLiB5b3VyIHBhdGggaXM6IC8K\",\n      \"request_id\": \"53c59d7b-6533-4059-acbb-32c7e3761368\"\n    }\n  }\n}\n```\n\n### TODO\n\n- Should be able to set `status` and `headers` in the response\n- Add a timeout for waiting on a response\n- Supporting chunk transfer could be interesting\n- Should be able to stream the body even if content-length can be known up front\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcablehead%2Fgo-http.sh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcablehead%2Fgo-http.sh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcablehead%2Fgo-http.sh/lists"}