Security News
The Risks of Misguided Research in Supply Chain Security
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.
github.com/jarcoal/httpmock
Easy mocking of http responses from external resources.
Currently supports Go 1.13 to 1.21 and is regularly tested against tip.
v1
branch has to be used instead of master
.
In your go files, simply use:
import "github.com/jarcoal/httpmock"
Then next go mod tidy
or go test
invocation will automatically
populate your go.mod
with the latest httpmock release, now
.
func TestFetchArticles(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
// Exact URL match
httpmock.RegisterResponder("GET", "https://api.mybiz.com/articles",
httpmock.NewStringResponder(200, `[{"id": 1, "name": "My Great Article"}]`))
// Regexp match (could use httpmock.RegisterRegexpResponder instead)
httpmock.RegisterResponder("GET", `=~^https://api\.mybiz\.com/articles/id/\d+\z`,
httpmock.NewStringResponder(200, `{"id": 1, "name": "My Great Article"}`))
// do stuff that makes a request to articles
...
// get count info
httpmock.GetTotalCallCount()
// get the amount of calls for the registered responder
info := httpmock.GetCallCountInfo()
info["GET https://api.mybiz.com/articles"] // number of GET calls made to https://api.mybiz.com/articles
info["GET https://api.mybiz.com/articles/id/12"] // number of GET calls made to https://api.mybiz.com/articles/id/12
info[`GET =~^https://api\.mybiz\.com/articles/id/\d+\z`] // number of GET calls made to https://api.mybiz.com/articles/id/<any-number>
}
func TestFetchArticles(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()
// our database of articles
articles := make([]map[string]interface{}, 0)
// mock to list out the articles
httpmock.RegisterResponder("GET", "https://api.mybiz.com/articles",
func(req *http.Request) (*http.Response, error) {
resp, err := httpmock.NewJsonResponse(200, articles)
if err != nil {
return httpmock.NewStringResponse(500, ""), nil
}
return resp, nil
})
// return an article related to the request with the help of regexp submatch (\d+)
httpmock.RegisterResponder("GET", `=~^https://api\.mybiz\.com/articles/id/(\d+)\z`,
func(req *http.Request) (*http.Response, error) {
// Get ID from request
id := httpmock.MustGetSubmatchAsUint(req, 1) // 1=first regexp submatch
return httpmock.NewJsonResponse(200, map[string]interface{}{
"id": id,
"name": "My Great Article",
})
})
// mock to add a new article
httpmock.RegisterResponder("POST", "https://api.mybiz.com/articles",
func(req *http.Request) (*http.Response, error) {
article := make(map[string]interface{})
if err := json.NewDecoder(req.Body).Decode(&article); err != nil {
return httpmock.NewStringResponse(400, ""), nil
}
articles = append(articles, article)
resp, err := httpmock.NewJsonResponse(200, article)
if err != nil {
return httpmock.NewStringResponse(500, ""), nil
}
return resp, nil
})
// mock to add a specific article, send a Bad Request response
// when the request body contains `"type":"toy"`
httpmock.RegisterMatcherResponder("POST", "https://api.mybiz.com/articles",
httpmock.BodyContainsString(`"type":"toy"`),
httpmock.NewStringResponder(400, `{"reason":"Invalid article type"}`))
// do stuff that adds and checks articles
}
When GET http://example.tld/some/path?b=12&a=foo&a=bar
request is
caught, all standard responders are checked against the following URL
or paths, the first match stops the search:
http://example.tld/some/path?b=12&a=foo&a=bar
(original URL)http://example.tld/some/path?a=bar&a=foo&b=12
(sorted query params)http://example.tld/some/path
(without query params)/some/path?b=12&a=foo&a=bar
(original URL without scheme and host)/some/path?a=bar&a=foo&b=12
(same, but sorted query params)/some/path
(path only)If no standard responder matched, the regexp responders are checked, in the same order, the first match stops the search.
// article_test.go
import (
"testing"
"github.com/jarcoal/httpmock"
"github.com/maxatome/go-testdeep/helpers/tdsuite"
"github.com/maxatome/go-testdeep/td"
)
type MySuite struct{}
func (s *MySuite) Setup(t *td.T) error {
// block all HTTP requests
httpmock.Activate()
return nil
}
func (s *MySuite) PostTest(t *td.T, testName string) error {
// remove any mocks after each test
httpmock.Reset()
return nil
}
func (s *MySuite) Destroy(t *td.T) error {
httpmock.DeactivateAndReset()
return nil
}
func TestMySuite(t *testing.T) {
tdsuite.Run(t, &MySuite{})
}
func (s *MySuite) TestArticles(assert, require *td.T) {
httpmock.RegisterResponder("GET", "https://api.mybiz.com/articles.json",
httpmock.NewStringResponder(200, `[{"id": 1, "name": "My Great Article"}]`))
// do stuff that makes a request to articles.json
}
// article_suite_test.go
import (
// ...
"github.com/jarcoal/httpmock"
)
// ...
var _ = BeforeSuite(func() {
// block all HTTP requests
httpmock.Activate()
})
var _ = BeforeEach(func() {
// remove any mocks
httpmock.Reset()
})
var _ = AfterSuite(func() {
httpmock.DeactivateAndReset()
})
// article_test.go
import (
// ...
"github.com/jarcoal/httpmock"
)
var _ = Describe("Articles", func() {
It("returns a list of articles", func() {
httpmock.RegisterResponder("GET", "https://api.mybiz.com/articles.json",
httpmock.NewStringResponder(200, `[{"id": 1, "name": "My Great Article"}]`))
// do stuff that makes a request to articles.json
})
})
// article_suite_test.go
import (
// ...
"github.com/jarcoal/httpmock"
"github.com/go-resty/resty"
)
// ...
var _ = BeforeSuite(func() {
// block all HTTP requests
httpmock.ActivateNonDefault(resty.DefaultClient.GetClient())
})
var _ = BeforeEach(func() {
// remove any mocks
httpmock.Reset()
})
var _ = AfterSuite(func() {
httpmock.DeactivateAndReset()
})
// article_test.go
import (
// ...
"github.com/jarcoal/httpmock"
"github.com/go-resty/resty"
)
var _ = Describe("Articles", func() {
It("returns a list of articles", func() {
fixture := `{"status":{"message": "Your message", "code": 200}}`
responder := httpmock.NewStringResponder(200, fixture)
fakeUrl := "https://api.mybiz.com/articles.json"
httpmock.RegisterResponder("GET", fakeUrl, responder)
// fetch the article into struct
articleObject := &models.Article{}
_, err := resty.R().SetResult(articleObject).Get(fakeUrl)
// do stuff with the article object ...
})
})
FAQs
Unknown package
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.
Research
Security News
Socket researchers found several malicious npm packages typosquatting Chalk and Chokidar, targeting Node.js developers with kill switches and data theft.
Security News
pnpm 10 blocks lifecycle scripts by default to improve security, addressing supply chain attack risks but sparking debate over compatibility and workflow changes.