{"id":24929919,"url":"https://github.com/thisislawatts/pinproxy","last_synced_at":"2026-02-11T11:31:53.760Z","repository":{"id":274823964,"uuid":"924183917","full_name":"thisislawatts/pinproxy","owner":"thisislawatts","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-29T16:07:26.000Z","size":124,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-17T03:43:10.981Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thisislawatts.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}},"created_at":"2025-01-29T15:08:58.000Z","updated_at":"2025-01-31T17:52:06.000Z","dependencies_parsed_at":"2025-01-29T16:29:03.161Z","dependency_job_id":"d3e8eaed-b1a5-4c8d-8a22-2cdfb8b81d02","html_url":"https://github.com/thisislawatts/pinproxy","commit_stats":null,"previous_names":["thisislawatts/pinproxy"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/thisislawatts/pinproxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisislawatts%2Fpinproxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisislawatts%2Fpinproxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisislawatts%2Fpinproxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisislawatts%2Fpinproxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thisislawatts","download_url":"https://codeload.github.com/thisislawatts/pinproxy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thisislawatts%2Fpinproxy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29332538,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-11T06:13:03.264Z","status":"ssl_error","status_checked_at":"2026-02-11T06:12:55.843Z","response_time":97,"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":[],"created_at":"2025-02-02T13:52:22.074Z","updated_at":"2026-02-11T11:31:53.746Z","avatar_url":"https://github.com/thisislawatts.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction\n\n[![GoDoc](https://godoc.org/github.com/thisislawatts/pinproxy?status.svg)](https://godoc.org/github.com/thisislawatts/pinproxy)\n[![Join the chat at https://gitter.im/thisislawatts/pinproxy](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/thisislawatts/pinproxy?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n![Status](https://github.com/thisislawatts/pinproxy/workflows/Go/badge.svg)\n\npackage pinproxy provides a customizable HTTP proxy library for Go (golang),\n\nIt supports regular HTTP proxy, HTTPS through CONNECT, and \"hijacking\" HTTPS\nconnection using \"Man in the Middle\" style attack.\n\nThe intent of the proxy is to be usable with reasonable amount of traffic,\nyet customizable and programmable.\n\nThe proxy itself is simply a `net/http` handler.\n\nIn order to use goproxy, one should set their browser to use goproxy as an HTTP\nproxy. Here is how you do that [in Chrome](https://support.google.com/chrome/answer/96815?hl=en)\nand [in Firefox](http://www.wikihow.com/Enter-Proxy-Settings-in-Firefox).\n\nFor example, the URL you should use as proxy when running `./bin/basic` is\n`localhost:8080`, as this is the default binding for the basic proxy.\n\n## Mailing List\n\nNew features will be discussed on the [mailing list](https://groups.google.com/forum/#!forum/goproxy-dev)\nbefore their development.\n\n## Latest Stable Release\n\nGet the latest goproxy from `gopkg.in/thisislawatts/pinproxy.v1`.\n\n# Why not Fiddler2?\n\nFiddler is an excellent software with similar intent. However, Fiddler is not\nas customizable as goproxy intends to be. The main difference is, Fiddler is not\nintended to be used as a real proxy.\n\nA possible use case that suits goproxy but\nnot Fiddler, is gathering statistics on page load times for a certain website over a week.\nWith goproxy you could ask all your users to set their proxy to a dedicated machine running a\ngoproxy server. Fiddler is a GUI app not designed to be run like a server for multiple users.\n\n# A taste of goproxy\n\nTo get a taste of `goproxy`, a basic HTTP/HTTPS transparent proxy\n\n```go\npackage main\n\nimport (\n    \"github.com/thisislawatts/pinproxy\"\n    \"log\"\n    \"net/http\"\n)\n\nfunc main() {\n    proxy := goproxy.NewProxyHttpServer()\n    proxy.Verbose = true\n    log.Fatal(http.ListenAndServe(\":8080\", proxy))\n}\n```\n\nThis line will add `X-GoProxy: yxorPoG-X` header to all requests sent through the proxy\n\n```go\nproxy.OnRequest().DoFunc(\n    func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {\n        r.Header.Set(\"X-GoProxy\",\"yxorPoG-X\")\n        return r,nil\n    })\n```\n\n`DoFunc` will process all incoming requests to the proxy. It will add a header to the request\nand return it. The proxy will send the modified request.\n\nNote that we returned nil value as the response. Had we returned a response, goproxy would\nhave discarded the request and sent the new response to the client.\n\nIn order to refuse connections to reddit at work time\n\n```go\nproxy.OnRequest(goproxy.DstHostIs(\"www.reddit.com\")).DoFunc(\n    func(r *http.Request,ctx *goproxy.ProxyCtx)(*http.Request,*http.Response) {\n        if h,_,_ := time.Now().Clock(); h \u003e= 8 \u0026\u0026 h \u003c= 17 {\n            return r,goproxy.NewResponse(r,\n                    goproxy.ContentTypeText,http.StatusForbidden,\n                    \"Don't waste your time!\")\n        }\n        return r,nil\n})\n```\n\n`DstHostIs` returns a `ReqCondition`, that is a function receiving a `Request` and returning a boolean.\nWe will only process requests that match the condition. `DstHostIs(\"www.reddit.com\")` will return\na `ReqCondition` accepting only requests directed to \"www.reddit.com\".\n\n`DoFunc` will receive a function that will preprocess the request. We can change the request, or\nreturn a response. If the time is between 8:00am and 17:00pm, we will reject the request, and\nreturn a pre-canned text response saying \"do not waste your time\".\n\nSee additional examples in the examples directory.\n\n\n# Type of handlers for manipulating connect/req/resp behavior\n\nThere are 3 kinds of useful handlers to manipulate the behavior, as follows:\n\n```go\n// handler called after receiving HTTP CONNECT from the client, and before proxy establish connection \n// with destination host\nhttpsHandlers   []HttpsHandler\n    \n// handler called before proxy send HTTP request to destination host\nreqHandlers     []ReqHandler \n    \n// handler called after proxy receives HTTP Response from destination host, and before proxy forward \n// the Response to the client.\nrespHandlers    []RespHandler \n```\n\nDepending on what you want to manipulate, the ways to add handlers to each handler list are:\n\n```go\n// Add handlers to httpsHandlers \nproxy.OnRequest(Some ReqConditions).HandleConnect(YourHandlerFunc())\n\n// Add handlers to reqHandlers\nproxy.OnRequest(Some ReqConditions).Do(YourReqHandlerFunc())\n\n// Add handlers to respHandlers\nproxy.OnResponse(Some RespConditions).Do(YourRespHandlerFunc())\n```\n\nFor example:\n\n```go\n// This rejects the HTTPS request to *.reddit.com during HTTP CONNECT phase\nproxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile(\"reddit.*:443$\"))).HandleConnect(goproxy.AlwaysReject)\n\n// This will NOT reject the HTTPS request with URL ending with gif, due to the fact that proxy \n// only got the URL.Hostname and URL.Port during the HTTP CONNECT phase if the scheme is HTTPS, which is\n// quiet common these days.\nproxy.OnRequest(goproxy.UrlMatches(regexp.MustCompile(`.*gif$`))).HandleConnect(goproxy.AlwaysReject)\n\n// The correct way to manipulate the HTTP request using URL.Path as condition is:\nproxy.OnRequest(goproxy.UrlMatches(regexp.MustCompile(`.*gif$`))).Do(YourReqHandlerFunc())\n```\n\n# What's New\n\n1. Ability to `Hijack` CONNECT requests. See\n[the eavesdropper example](https://github.com/thisislawatts/pinproxy/blob/master/examples/goproxy-eavesdropper/main.go#L27)\n2. Transparent proxy support for http/https including MITM certificate generation for TLS.  See the [transparent example.](https://github.com/thisislawatts/pinproxy/tree/master/examples/goproxy-transparent)\n\n# License\n\nI put the software temporarily under the Go-compatible BSD license.\nIf this prevents someone from using the software, do let me know and I'll consider changing it.\n\nAt any rate, user feedback is very important for me, so I'll be delighted to know if you're using this package.\n\n# Beta Software\n\nI've received positive feedback from a few people who use goproxy in production settings.\nI believe it is good enough for usage.\n\nI'll try to keep reasonable backwards compatibility. In case of a major API change,\nI'll change the import path.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthisislawatts%2Fpinproxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthisislawatts%2Fpinproxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthisislawatts%2Fpinproxy/lists"}