{"id":37212739,"url":"https://github.com/leafney/req","last_synced_at":"2026-01-15T00:30:25.482Z","repository":{"id":37041155,"uuid":"152715352","full_name":"leafney/req","owner":"leafney","description":"a golang http request library for humans  Go语言人性化HTTP请求库","archived":false,"fork":true,"pushed_at":"2022-06-18T09:48:24.000Z","size":212,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-06-22T03:22:21.723Z","etag":null,"topics":["golang","http","request"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"imroc/req","license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leafney.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}},"created_at":"2018-10-12T08:03:25.000Z","updated_at":"2022-06-18T09:47:04.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/leafney/req","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/leafney/req","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leafney%2Freq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leafney%2Freq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leafney%2Freq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leafney%2Freq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leafney","download_url":"https://codeload.github.com/leafney/req/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leafney%2Freq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28439704,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T22:37:52.437Z","status":"ssl_error","status_checked_at":"2026-01-14T22:37:31.496Z","response_time":107,"last_error":"SSL_read: 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","request"],"created_at":"2026-01-15T00:30:24.751Z","updated_at":"2026-01-15T00:30:25.475Z","avatar_url":"https://github.com/leafney.png","language":"Go","readme":"# req\n\nA golang http request library for humans\n\nfork from [imroc/req](https://github.com/imroc/req)\n\nAdd New\n========\n\n### Cookie\n\nsupport `[]*http.Cookie`\n```go\nvar cookList []*http.Cookie\n//....\nreq.Get(url, cookList)\n```\n\n### XReq\n```go\nxs := XSets{\n\t\"Content-Type\": \"application/javascript\",\n    \"Debug\":  true,\n    \"Method\": \"GET\",\n}\nreq.XReq(url, xs)\n```\n\n------\n\n\nFeatures\n========\n\n- Light weight\n- Simple\n- Easy play with JSON and XML\n- Easy for debug and logging\n- Easy file uploads and downloads\n- Easy manage cookie\n- Easy set up proxy\n- Easy set timeout\n- Easy customize http client\n\n\nDocument\n========\n[中文](doc/README_cn.md)\n\n\nInstall\n=======\n``` sh\ngo get github.com/leafney/req\n```\n\nOverview\n=======\n`req` implements a friendly API over Go's existing `net/http` library.  \n  \n`Req` and `Resp` are two most important struct, you can think of `Req` as a client that initiate HTTP requests, `Resp` as a information container for the request and response. They all provide simple and convenient APIs that allows you to do a lot of things.\n``` go\nfunc (r *Req) Post(url string, v ...interface{}) (*Resp, error)\n```  \n\nIn most cases, only url is required, others are optional, like headers, params, files or body etc.\n\nThere is a default `Req` object, all of its' public methods  are wrapped by the `req` package, so you can also think of `req` package as a `Req` object\n``` go\n// use Req object to initiate requests.\nr := req.New()\nr.Get(url)\n\n// use req package to initiate request.\nreq.Get(url)\n```\nYou can use `req.New()` to create lots of `*Req` as client with independent configuration\n\nExamples\n=======\n[Basic](#Basic)  \n[Set Header](#Set-Header)  \n[Set Param](#Set-Param)  \n[Set Body](#Set-Body)  \n[Debug](#Debug)  \n[Output Format](#Format)  \n[ToJSON \u0026 ToXML](#ToJSON-ToXML)  \n[Get *http.Response](#Response)  \n[Upload](#Upload)  \n[Download](#Download)  \n[Cookie](#Cookie)  \n[Set Timeout](#Set-Timeout)  \n[Set Proxy](#Set-Proxy)  \n[Customize Client](#Customize-Client)\n[Set context.Context](#Context)\n\n## \u003ca name=\"Basic\"\u003eBasic\u003c/a\u003e\n``` go\nheader := req.Header{\n\t\"Accept\":        \"application/json\",\n\t\"Authorization\": \"Basic YWRtaW46YWRtaW4=\",\n}\nparam := req.Param{\n\t\"name\": \"imroc\",\n\t\"cmd\":  \"add\",\n}\n// only url is required, others are optional.\nr, err := req.Post(\"http://foo.bar/api\", header, param)\nif err != nil {\n\tlog.Fatal(err)\n}\nr.ToJSON(\u0026foo)       // response =\u003e struct/map\nlog.Printf(\"%+v\", r) // print info (try it, you may surprise) \n```\n\n## \u003ca name=\"Set-Header\"\u003eSet Header\u003c/a\u003e\nUse `req.Header` (it is actually a `map[string]string`)\n``` go\nauthHeader := req.Header{\n\t\"Accept\":        \"application/json\",\n\t\"Authorization\": \"Basic YWRtaW46YWRtaW4=\",\n}\nreq.Get(\"https://www.baidu.com\", authHeader, req.Header{\"User-Agent\": \"V1.1\"})\n```\nuse `http.Header`\n``` go\nheader := make(http.Header)\nheader.Set(\"Accept\", \"application/json\")\nreq.Get(\"https://www.baidu.com\", header)\n```\n\nYou can also set header from struct, use `HeaderFromStruct` func to parse your struct\n``` go\ntype HeaderStruct struct {\n\tUserAgent     string `json:\"User-Agent\"`\n\tAuthorization string `json:\"Authorization\"`\n}\n\nfunc main(){\n\th := HeaderStruct{\n\t\t\"V1.0.0\",\n\t\t\"roc\",\n\t}\n\n\tauthHeader := req.HeaderFromStruct(h) \n\treq.Get(\"https://www.baidu.com\", authHeader, req.Header{\"User-Agent\": \"V1.1\"})\n}\n```\n\u003e Note: Please add tag 'json' to your argument in struct to let you customize the key name of your header\n\n## \u003ca name=\"Set-Param\"\u003eSet Param\u003c/a\u003e\nUse `req.Param` (it is actually a `map[string]interface{}`)\n``` go\nparam := req.Param{\n\t\"id\":  \"imroc\",\n\t\"pwd\": \"roc\",\n}\nreq.Get(\"http://foo.bar/api\", param) // http://foo.bar/api?id=imroc\u0026pwd=roc\nreq.Post(url, param)                  // body =\u003e id=imroc\u0026pwd=roc\n```\nuse `req.QueryParam` force to append params to the url (it is also actually a `map[string]interface{}`)\n``` go\nreq.Post(\"http://foo.bar/api\", req.Param{\"name\": \"roc\", \"age\": \"22\"}, req.QueryParam{\"access_token\": \"fedledGF9Hg9ehTU\"})\n/*\nPOST /api?access_token=fedledGF9Hg9ehTU HTTP/1.1\nHost: foo.bar\nUser-Agent: Go-http-client/1.1\nContent-Length: 15\nContent-Type: application/x-www-form-urlencoded;charset=UTF-8\nAccept-Encoding: gzip\n\nage=22\u0026name=roc\n*/\n```\n\n## \u003ca name=\"Set-Body\"\u003eSet Body\u003c/a\u003e\nPut `string`, `[]byte` and `io.Reader` as body directly.\n``` go\nreq.Post(url, \"id=roc\u0026cmd=query\")\n```\nPut object as xml or json body (add `Content-Type` header automatically)\n``` go\nreq.Post(url, req.BodyJSON(\u0026foo))\nreq.Post(url, req.BodyXML(\u0026bar))\n```\n\n## \u003ca name=\"Debug\"\u003eDebug\u003c/a\u003e\nSet global variable `req.Debug` to true, it will print detail information for every request.\n``` go\nreq.Debug = true\nreq.Post(\"http://localhost/test\" \"hi\")\n```\n![post](doc/post.png)\n\n## \u003ca name=\"Format\"\u003eOutput Format\u003c/a\u003e\nYou can use different kind of output format to log the request and response information in your log file in defferent scenarios. For example, use `%+v` output format in the development phase, it allows you to observe the details. Use `%v` or `%-v` output format in production phase, just log the information necessarily.  \n\n### `%+v` or `%+s`\nOutput in detail\n``` go\nr, _ := req.Post(url, header, param)\nlog.Printf(\"%+v\", r) // output the same format as Debug is enabled\n```\n\n### `%v` or `%s`\nOutput in simple way (default format)\n``` go\nr, _ := req.Get(url, param)\nlog.Printf(\"%v\\n\", r) // GET http://foo.bar/api?name=roc\u0026cmd=add {\"code\":\"0\",\"msg\":\"success\"}\nlog.Prinln(r)         // same as above\n```\n\n### `%-v` or `%-s`\nOutput in simple way and keep all in one line (request body or response body may have multiple lines, this format will replace `\"\\r\"` or `\"\\n\"` with `\" \"`, it's useful when doing some search in your log file)\n\n### Flag\nYou can call `SetFlags` to control the output content, decide which pieces can be output.\n``` go\nconst (\n\tLreqHead  = 1 \u003c\u003c iota // output request head (request line and request header)\n\tLreqBody              // output request body\n\tLrespHead             // output response head (response line and response header)\n\tLrespBody             // output response body\n\tLcost                 // output time costed by the request\n\tLstdFlags = LreqHead | LreqBody | LrespHead | LrespBody\n)\n```\n``` go\nreq.SetFlags(req.LreqHead | req.LreqBody | req.LrespHead)\n```\n\n### Monitoring time consuming\n``` go\nreq.SetFlags(req.LstdFlags | req.Lcost) // output format add time costed by request\nr,_ := req.Get(url)\nlog.Println(r) // http://foo.bar/api 3.260802ms {\"code\":0 \"msg\":\"success\"}\nif r.Cost() \u003e 3 * time.Second { // check cost\n\tlog.Println(\"WARN: slow request:\", r)\n}\n```\n\n## \u003ca name=\"ToJSON-ToXML\"\u003eToJSON \u0026 ToXML\u003c/a\u003e\n``` go\nr, _ := req.Get(url)\nr.ToJSON(\u0026foo)\nr, _ = req.Post(url, req.BodyXML(\u0026bar))\nr.ToXML(\u0026baz)\n```\n\n## \u003ca name=\"Response\"\u003eGet *http.Response\u003c/a\u003e\n```go\n// func (r *Req) Response() *http.Response\nr, _ := req.Get(url)\nresp := r.Response()\nfmt.Println(resp.StatusCode)\n```\n\n## \u003ca name=\"Upload\"\u003eUpload\u003c/a\u003e\nUse `req.File` to match files\n``` go\nreq.Post(url, req.File(\"imroc.png\"), req.File(\"/Users/roc/Pictures/*.png\"))\n```\nUse `req.FileUpload` to fully control\n``` go\nfile, _ := os.Open(\"imroc.png\")\nreq.Post(url, req.FileUpload{\n\tFile:      file,\n\tFieldName: \"file\",       // FieldName is form field name\n\tFileName:  \"avatar.png\", //Filename is the name of the file that you wish to upload. We use this to guess the mimetype as well as pass it onto the server\n})\n```\nUse `req.UploadProgress` to listen upload progress\n```go\nprogress := func(current, total int64) {\n\tfmt.Println(float32(current)/float32(total)*100, \"%\")\n}\nreq.Post(url, req.File(\"/Users/roc/Pictures/*.png\"), req.UploadProgress(progress))\nfmt.Println(\"upload complete\")\n```\n\n## \u003ca name=\"Download\"\u003eDownload\u003c/a\u003e\n``` go\nr, _ := req.Get(url)\nr.ToFile(\"imroc.png\")\n```\nUse `req.DownloadProgress` to listen download progress\n```go\nprogress := func(current, total int64) {\n\tfmt.Println(float32(current)/float32(total)*100, \"%\")\n}\nr, _ := req.Get(url, req.DownloadProgress(progress))\nr.ToFile(\"hello.mp4\")\nfmt.Println(\"download complete\")\n```\n\n## \u003ca name=\"Cookie\"\u003eCookie\u003c/a\u003e\nBy default, the underlying `*http.Client` will manage your cookie(send cookie header to server automatically if server has set a cookie for you), you can disable it by calling this function :\n``` go\nreq.EnableCookie(false)\n```\nand you can set cookie in request just using `*http.Cookie`\n``` go\ncookie := new(http.Cookie)\n// ......\nreq.Get(url, cookie)\n```\n\n## \u003ca name=\"Set-Timeout\"\u003eSet Timeout\u003c/a\u003e\n``` go\nreq.SetTimeout(50 * time.Second)\n```\n\n## \u003ca name=\"Set-Proxy\"\u003eSet Proxy\u003c/a\u003e\nBy default, req use proxy from system environment if `http_proxy` or `https_proxy` is specified, you can set a custom proxy or disable it by set `nil`\n``` go\nreq.SetProxy(func(r *http.Request) (*url.URL, error) {\n\tif strings.Contains(r.URL.Hostname(), \"google\") {\n\t\treturn url.Parse(\"http://my.vpn.com:23456\")\n\t}\n\treturn nil, nil\n})\n```\nSet a simple proxy (use fixed proxy url for every request)\n``` go\nreq.SetProxyUrl(\"http://my.proxy.com:23456\")\n```\n\n## \u003ca name=\"Context\"\u003eSet context.Context\u003c/a\u003e\nYou can pass context.Context in simple way:\n```go\nr, _ := req.Get(url, context.Background())\n```\n\n## \u003ca name=\"Customize-Client\"\u003eCustomize Client\u003c/a\u003e\nUse `SetClient` to change the default underlying `*http.Client`\n``` go\nreq.SetClient(client)\n```\nSpecify independent http client for some requests\n``` go\nclient := \u0026http.Client{Timeout: 30 * time.Second}\nreq.Get(url, client)\n```\nChange some properties of default client you want\n``` go\nreq.Client().Jar, _ = cookiejar.New(nil)\ntrans, _ := req.Client().Transport.(*http.Transport)\ntrans.MaxIdleConns = 20\ntrans.TLSHandshakeTimeout = 20 * time.Second\ntrans.DisableKeepAlives = true\ntrans.TLSClientConfig = \u0026tls.Config{InsecureSkipVerify: true}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleafney%2Freq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleafney%2Freq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleafney%2Freq/lists"}