{"id":36783954,"url":"https://github.com/federicoleon/go-httpclient","last_synced_at":"2026-01-12T13:19:23.175Z","repository":{"id":45089984,"uuid":"292163665","full_name":"federicoleon/go-httpclient","owner":"federicoleon","description":"A productive and performant HTTP client in Go","archived":false,"fork":false,"pushed_at":"2024-05-20T04:01:01.000Z","size":24,"stargazers_count":43,"open_issues_count":2,"forks_count":19,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-06-18T20:17:30.196Z","etag":null,"topics":["golang","http","mock","mocking","restfu","testing"],"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/federicoleon.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,"publiccode":null,"codemeta":null}},"created_at":"2020-09-02T02:56:46.000Z","updated_at":"2024-06-17T22:24:18.000Z","dependencies_parsed_at":"2024-06-18T20:13:53.844Z","dependency_job_id":null,"html_url":"https://github.com/federicoleon/go-httpclient","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/federicoleon/go-httpclient","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/federicoleon%2Fgo-httpclient","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/federicoleon%2Fgo-httpclient/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/federicoleon%2Fgo-httpclient/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/federicoleon%2Fgo-httpclient/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/federicoleon","download_url":"https://codeload.github.com/federicoleon/go-httpclient/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/federicoleon%2Fgo-httpclient/sbom","scorecard":{"id":395363,"data":{"date":"2025-08-11","repo":{"name":"github.com/federicoleon/go-httpclient","commit":"c8a477542c912efe8bc5c0170ce01b34793dc667"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/7 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 5 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T18:51:44.857Z","repository_id":45089984,"created_at":"2025-08-18T18:51:44.857Z","updated_at":"2025-08-18T18:51:44.857Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28338996,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T12:22:26.515Z","status":"ssl_error","status_checked_at":"2026-01-12T12:22:10.856Z","response_time":98,"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":["golang","http","mock","mocking","restfu","testing"],"created_at":"2026-01-12T13:19:23.016Z","updated_at":"2026-01-12T13:19:23.145Z","avatar_url":"https://github.com/federicoleon.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Go HTTP Client\n\nA production-ready HTTP client in Go with lots of useful features and using nothing more than the standard library of the language.\n\n## Installation\n\n```bash\n# Go Modules\nrequire github.com/federicoleon/go-httpclient\n```\n\n## Usage\nIn order to use the library for making HTTP calls you need to import the corresponding HTTP package:\n\n```go\nimport \"github.com/federicoleon/go-httpclient/gohttp\"\n```\n\n## Configuring the client\nOnce you have imported the package, you can now start using the client. First you need to configure and build the client as you need:\n\n```go\nheaders := make(http.Header)\nheaders.Set(\"Some-Common-Header\", \"value-for-all-requests\")\n\n// Create a new builder:\nclient := gohttp.NewBuilder().\n\n\t// You can set global headers to be used in every request made by this client:\n\tSetHeaders(headers).\n\n\t// Configure the timeout for getting a new connection:\n\tSetConnectionTimeout(2 * time.Second).\n\n\t// Configure the timeout for performing the actual HTTP call:\n\tSetResponseTimeout(3 * time.Second).\n\n\t// Configure the User-Agent header that will be used for all of the requests:\n\tSetUserAgent(\"Your-User-Agent\").\n\n\t// Finally, build the client and start using it!\n\tBuild()\n```\n\n## Performing HTTP calls\nThe ``Client`` interface provides convenient methods that you can use to perform different HTTP calls. If you get an error then you can safely ignore the response object since it won't be there.\n\n**Important:** There is no need to read \u0026 close anything from the response since the client is doing all of this for you. You just need to get the response and start using it!\n\nTake a look at all of the [EXAMPLES](examples) for more information.\n\n### GET\n\n```go\ntype Endpoints struct {\n\tCurrentUserUrl    string `json:\"current_user_url\"`\n\tAuthorizationsUrl string `json:\"authorizations_url\"`\n\tRepositoryUrl     string `json:\"repository_url\"`\n}\n\nfunc GetEndpoints() (*Endpoints, error) {\n\t// Make the request and wait for the response:\n\tresponse, err := httpClient.Get(\"https://api.github.com\")\n\tif err != nil {\n\t\t// Deal with the error as you need:\n\t\treturn nil, err\n\t}\n\n\t// Interacting with the response:\n\tfmt.Println(fmt.Sprintf(\"Status Code: %d\", response.StatusCode))\n\tfmt.Println(fmt.Sprintf(\"Status: %s\", response.Status))\n\tfmt.Println(fmt.Sprintf(\"Body: %s\\n\", response.String()))\n\n\t// Processing JSON responses:\n\tvar endpoints Endpoints\n\tif err := response.UnmarshalJson(\u0026endpoints); err != nil {\n\t\t// Deal with the unmarshal error as you need:\n\t\treturn nil, err\n\t}\n\n\tfmt.Println(fmt.Sprintf(\"Repository URL: %s\", endpoints.RepositoryUrl))\n\treturn \u0026endpoints, nil\n}\n```\n\n### POST\n\n```go\n\n// The struct representing the actual JSON response from the API we're calling:\ntype GithubError struct {\n\tStatusCode       int    `json:\"-\"`\n\tMessage          string `json:\"message\"`\n\tDocumentationUrl string `json:\"documentation_url\"`\n}\n\n// The struct representing the JSON body we're going to send:\ntype Repository struct {\n\tName        string `json:\"name\"`\n\tDescription string `json:\"description,omitempty\"`\n\tPrivate     bool   `json:\"private\"`\n}\n\nfunc CreateRepo(request Repository) (*Repository, error) {\n\t// Make the request and wait for the response:\n\tresponse, err := httpClient.Post(\"https://api.github.com/user/repos\", request)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Deal with failed status codes:\n\tif response.StatusCode != http.StatusCreated {\n\t\tvar githubError GithubError\n\t\tif err := response.UnmarshalJson(\u0026githubError); err != nil {\n\t\t\treturn nil, errors.New(\"error processing github error response when creating a new repo\")\n\t\t}\n\t\treturn nil, errors.New(githubError.Message)\n\t}\n\n\t// Deal with successful response:\n\tvar result Repository\n\tif err := response.UnmarshalJson(\u0026result); err != nil {\n\t\treturn nil, err\n\t}\n\treturn \u0026result, nil\n}\n\n```\n\n## Testing\n\nThe library provides a convenient package for mocking requests and getting a particular response. The mock key is generated using the ``HTTP method``, the ``request URL`` and the ``request body``. Every request with these same elements will return the same mock.\n\nIn order to use the mocking features you need to import the corresponding package:\n\n```go\nimport \"github.com/federicoleon/go-httpclient/gohttp_mock\"\n```\n\n### Starting the mock server:\n```go\nfunc TestMain(m *testing.M) {\n\t// Tell the HTTP library to mock any further requests from here.\n\tgohttp_mock.MockupServer.Start()\n\n\t// Start the test cases for this pacakge:\n\tos.Exit(m.Run())\n}\n```\n\nOnce you start the mock server, every request will be handled by this server and will not be sent against the real API. If there is no mock matching the current request you'll get an error saying ``no mock matching {METHOD} from '{URL}' with given body``.\n\n### Configuring a given HTTP mock:\n\n```go\n// Delete all mocks in every new test case to ensure a clean environment:\ngohttp_mock.MockupServer.DeleteMocks()\n\n// Configure a new mock:\ngohttp_mock.MockupServer.AddMock(gohttp_mock.Mock{\n\tMethod:      http.MethodPost,\n\tUrl:         \"https://api.github.com/user/repos\",\n\tRequestBody: `{\"name\":\"test-repo\",\"private\":true}`,\n\n\tError: errors.New(\"timeout from github\"),\n})\n```\n\nIn this case, we're telling the client that when we send a POST request against that URL and with that body, we want that particular error. In this case, no response was returned. Let's see how you can configure a particular response:\n\n\n```go\n// Delete all mocks in every new test case to ensure a clean environment:\ngohttp_mock.MockupServer.DeleteMocks()\n\n// Configure a new mock:\ngohttp_mock.MockupServer.AddMock(gohttp_mock.Mock{\n\tMethod:      http.MethodPost,\n\tUrl:         \"https://api.github.com/user/repos\",\n\tRequestBody: `{\"name\":\"test-repo\",\"private\":true}`,\n\n\tResponseStatusCode: http.StatusCreated,\n\tResponseBody:       `{\"id\":123,\"name\":\"test-repo\"}`,\n})\n```\n\nIn this case, we get a response with status code ``201 Created`` and that particular response body.\n\n## Collaboration\n\nPull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.\n\nPlease make sure to update tests as needed. Changes with no test cases will NOT be reviewed!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffedericoleon%2Fgo-httpclient","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffedericoleon%2Fgo-httpclient","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffedericoleon%2Fgo-httpclient/lists"}