Commit Graph

25 Commits

Author SHA1 Message Date
Abhinav Singh b2a16046c2
Invoke github actions for all pull requests (#259) 2020-01-07 10:35:25 -08:00
Abhinav Singh e84c212465
Integration testing (#243)
* Add tests for public/private/csr generation

* Add integration testing skeleton for mac and ubuntu

* Merge integration within lib test to avoid too many workflows

* Disable integration testing on windows for now

* Use sudo to start integration test script as lsof fails on MacOS.

lsof: WARNING: can't stat() vmhgfs file system

* Add basic integration testing for now to assert proxy works as expected when started out of develop branch

* Add a call to inbuilt http server to verify it works

* wait for server to accept requests
2019-12-25 16:39:18 -08:00
Abhinav Singh 8971f82f82
Enable mccabe (#217) 2019-12-02 10:04:27 -08:00
Abhinav Singh 7f9ffad6d4
Move homebrew under helper (#215) 2019-12-01 23:28:46 -08:00
Abhinav Singh 54d2a1cc32
Packaging (#210)
* Move docker installation steps above

* Try brewing with virtualenv

* depends on python

* Update homebrew formula for stable release

* Just test brewing on latest python
2019-12-01 20:08:50 -08:00
Abhinav Singh 4713ad6ea7
Homebrew formula (#209)
* Add homebrew formula

* Build PyPi package and Homebrew installation verification

* Check develop

* bdist_wheel reported as error: invalid command "bdist_wheel"

* Move under stable/develop folders to keep Proxy class name same

* uff

* develop installs proxy not proxy.py binary

* Prepend site-packages

* Install typing-extensions explicitly with brew

* Use find_packages

* Most likely failing due to lack of find_packages in current develop branch

* Fix windows setup.py build

* test_static_web_server_serves seems flaky on Ubuntu python 3.8

* Add instructions to install using homebrew

* Disable test_static_web_server_serves on GitHub actions, seems flaky
2019-12-01 19:01:28 -08:00
Abhinav Singh c9ce446440
Add py3.8 support and bump node to 12.x (#195)
* Add py3.8 support and bump node to 12.x

* Add 10.x, 11.x, 12.x matrix for dashboard testing

* Add Python 3.8 support label

* Single tested with label
2019-11-26 21:44:20 -08:00
Abhinav Singh 35a88c0235
Cleanup (#194)
* Add basic README description for dashboard

* Use spaces for all except makefile

* enable tests for py 3.5

* Python 3.5 support label

* Avoid clash of names
2019-11-26 21:16:08 -08:00
Abhinav Singh bb7006b67a
Move benchmark module within proxy (#181)
* Move benchmark within proxy module

* chmod 0644 for benchmark.py which was executable till now

* Turn utilities into its own section
2019-11-15 23:49:51 -08:00
Abhinav Singh 131e9366ac
Move plugin_examples/ as proxy.plugin and update readme (#179)
* Update dev guide

* Move plugin_examples/ as proxy.plugin

* Update proxy.plugin ref path in readme

* Remove unnecessary port flag

* Remove plugin_examples from github workflows

* dashboard folder is a npm package not python package anymore

* Plugins can now be tried using Docker image
2019-11-15 14:47:50 -08:00
Abhinav Singh 148c260472
Move dashboard backend within proxy module, now ships via same pip package (#177)
* Allow resources to load from http and ws when running w/o https

* Move dashboard backend (dashboard.py) within proxy module. Now shipped with pip install proxy.py

* Update ref to dashboard backend in github workflows

* Add git-pre-commit hook file.

Enable it by symlinking as .git/hooks/pre-commit

* Also enable static server for dashboard serving
2019-11-15 13:29:48 -08:00
Abhinav Singh 3aa1dc2824
Test refactor + Docker image CI (#154)
* Move tests into individual modules too

* Ensure one test class per file

* Fix docker image after refactoring

* Add github actions workflow for building docker image

* Fix image name

* Setup python required for extracting proxy version

* Version will also require deps
2019-10-29 20:41:39 -07:00
Abhinav Singh e14548252c
Proxy.py Dashboard (#141)
* Remove redundant variables

* Initialize frontend dashboard app (written in typescript)

* Add a WebsocketFrame.text method to quickly build a text frame raw packet, also close connection for static file serving, atleast Google Chrome seems to hang up instead of closing the connection

* Add read_and_build_static_file_response method for reusability in plugins

* teardown websocket connection when opcode CONNECTION_CLOSE is received

* First draft of proxy.py dashboard

* Remove uglify, obfuscator is superb enough

* Correct generic V

* First draft of dashboard

* ProtocolConfig is now Flags

* First big refactor toward no-single-file-module

* Working tests

* Update dashboard for refactored imports

* Remove proxy.py as now we can just call python -m proxy -h

* Fix setup.py for refactored code

* Banner update

* Lint check

* Fix dashboard static serving and no UNDER_TEST constant necessary

* Add support for plugin imports when specified in path/to/module.MyPlugin

* Update README with instructions to run proxy.py after refactor

* Move dashboard under /dashboard path

* Rename to devtools.ts

* remove unused

* Update github workflow for new directory structure

* Update test command too

* Fix coverage generation

* *.py is an invalid syntax on windows

* No * on windows

* Enable execution via github zip downloads

* Github Zip downloads cannot be executed as Github puts project under a folder named after Github project, this breaks python interpreter expectation of finding a __main__.py in the root directory

* Forget zip runs for now

* Initialize ProxyDashboard on page load rather than within typescript i.e. on script load

* Enforce eslint with standard style

* Add .editorconfig to make editor compatible with various style requirements (Makefile, Typescript, Python)

* Remove extra empty line

* Add ability to pass headers with HttpRequestRejected exception, also remove proxy agent header for HttpRequestRejected

* Add ability to pass headers with HttpRequestRejected exception, also remove proxy agent header for HttpRequestRejected

* Fix tests

* Move common code under common sub-module

* Move flags under common module

* Move acceptor under core

* Move connection under core submodule

* Move chunk_parser under http

* Move http_parser as http/parser

* Move http_methods as http/methods

* Move http_proxy as http/proxy

* Move web_server as http/server

* Move status_codes as http/codes

* move websocket as http/websocket

* Move exception under http/exception, also move http/proxy exceptions under http/exceptions

* move protocol_handler as http/handler

* move devtools as http/devtools

* Move version under common/version

* Lifecycle if now core Event

* autopep8

* Add core event queue

* Register / unregister handler

* Enable inspection support for frontend dashboard

* Dont give an illusion of exception for HttpProtocolExceptions

* Update readme for refactored codebase

* DictQueueType everywhere

* Move all websocket API related code under WebsocketApi class

* Inspection enabled on tab switch.

1. Additionally now acceptors are assigned an int id.
2. Fix tests to match change in constructor.

* Corresponding ends of the work queues can be closed immediately.

Since work queues between AcceptorPool and Acceptor process is used only
once, close corresponding ends asap instead of at shutdown.

* No need of a manager for shared multiprocess Lock.

This unnecessarily creates additional manager process.

* Move threadless into its own module

* Merge acceptor and acceptor_pool tests

* Defer os.close

* Change content display with tab clicks.

Also ensure relay manager shutdown.

* Remove --cov flags

* Use right type for SyncManager

* Ensure coverage again

* Print help to discover flags, --cov certainly not available on Travis for some reason

* Add pytest-cov to requirements-testing

* Re-add windows on .travis also add changelog to readme

* Use 3.7 and no pip upgrade since it fails on travis windows

* Attempt to fix pip install on windows

* Disable windows on travis, it fails and uses 3.8.  Try reporting coverage from github actions

* Move away from coveralls, use codecov

* Codecov app installation either didnt work or token still needs to be passed

* Remove travis CI

* Use https://github.com/codecov/codecov-action for coverage uploads

* Remove run codecov

* Ha, codecov action only works on linux, what a mess

* Add cookie.js though unable to use it with es5/es6 modules yet

* Enable testing for python 3.8 also Build dashboard during testing

* No python 3.8 on github actions yet

* Autopep8

* Add separate workflows for library (python) and dashboard (node) app

* Type jobs not job

* Add checkout

* Fix parsing node version

* Fix dashboard build on windows

* Show codecov instead of coveralls
2019-10-28 14:57:33 -07:00
Abhinav Singh a1bb659488
Threadless execution using coroutines (#134)
* Workers need not register/unregister sock for every loop

* No need of explicit socket.settimeout(0) which is same as socket.setblocking(False)

* Remove settimeout assertion

* Only store sender side of Pipe().  Also ensure both end of the Pipe() are closed on shutdown

* Make now global. Also we seem to be using datetime.utcnow and time.time for similar purposes

* Use time.time throughout.  Remove incomplete test_cache_responses_plugin to avoid resource leak in tests

* Remove unused

* Wrap selector register/unregister within a context manager

* Refactor in preparation of threadless request handling

* MyPy generator fix

* Add --threadless flag

* Internally call them acceptors

* Internally use acceptors

* Add Threadless class.

Also no need to pass family over pipe to acceptors.

* Make threadless work for a single client :)

* Threadless is soon be our default

* Close client queue

* Use context manager for register/unregister

* Fix Acceptor tests broken after refactoring

* Use asyncio tasks to invoke ProtocolHandle.handle_events

This gives all client threads a chance to respond without
waiting for other handlers to return.

* Explicitly initialize event loop per Threadless process

* Mypy fixes

* Add ThreadlessWork abstract class implemented by ProtocolHandler

* Add benchmark.py

Avoid TIME_WAIT by properly shutting down the connection.

* Add benchmark.py as part of testing workflow

* When e2e encryption is enabled, unwrap socket before shutdown to ensure CLOSED state

* MyPy fixes, Union should have worked, but likely unwrap is not part of socket.socket hence

* Unwrap if wrapped before shutdown

* Unwrap if wrapped before shutdown

* socket.SHUT_RDWR will cause leaks

* MyPy

* Add instructions for monitor.sh

* Avoid recursive exception in new_socket_connection and only invoke plugins/shutdown if server connection was initialized

* Add Fast & Scalable section

* Update internal classes section

* Dont print out local dir path in help text :)

* Refactor

* Fix a bug where response parser for HTTP only requests was reused for pipelined requests resulting in a hang

* Add chrome_with_proxy.sh helper script

* Handle OSError during client.flush which can happen due to invalid protocol type for socket error

* Remove redundant e

* Add classmethods to quickly construct a parser object

* Don't raise from TcpConnection abstract class.

This allows both client/socket side of communication to handle
exceptions as necessary. We might refactor this again later to remove
redundant code :)

* Disable response parsing when TLS interception is enabled. See issue #127

* remove unused imports

* Within webserver parse pipelined requests only if we have a route

* Add ShortLinkPlugin plugin

* Add more shortlinks

* Add ShortLinkPlugin to README.md

* Add path forwarding too instead of leaving as excercise ;)

* Add shortlink to TOC

* Ensure no socket leaks

* Ensure no leaks

* Naming

* Default number of clients 1

* Avoid shortlinking localhost

* Stress more
2019-10-15 23:56:39 -07:00
Abhinav Singh 6455a34973
Invoke proxy plugin handle_request for each request in HTTP/1.1 pipeline or when TLS interception is enabled (#128)
* Add tests for is_http_1_1_keep_alive

* Add ModifyPostDataPlugin in README

* Fixes #126

* Refactor HttpProxyBasePlugin API

* before_upstream_connection too can drop request by returning None

* Remove HTTP Server startup during tests, no longer used

* Removed unused imports

* Simplify load_plugins
2019-10-12 17:43:19 -07:00
Abhinav Singh a19da5dcb9
Update issue templates (#123) 2019-10-10 16:18:12 -07:00
Abhinav Singh 3b9587b6f1
Ensure explicit flush before upgrade while TLS intercepting (#121)
* Ensure explicit flush before upgrade + nonblocking server sock.

* tls interception tests

* prepare for v1.1.1

* Add requirements.txt for typing extensions

* Add setup.py under lint workflow
2019-10-10 15:15:27 -07:00
Abhinav Singh a9c8659ffa
Use selectors.DefaultSelector instead of select.select (#106)
* Use selectors.DefaultSelector instead of select.select

* Unregister to avoid endless loop

* Cleanup event register/unregiter

* Cleanup event registration

* Add google-fluentd.conf.  Use if running proxy.py on Google Cloud.

* Send server error from proxy if for whatever reason we fail to process the request (or should it be BadRequest based upon situation?)

* Fix tests for selectors

* Only include proxy.py and tests.py in coverage report

* Only include proxy.py for coverage

* remove redundant integration test, will rewrite using mocks

* Proper unregister of events

* Change multi core accept model to avoid client TIME_WAIT. Fixes #97

* Catch BlockingIOError

* Remove redundant comments

* Simplify with AcceptorPool

* Pass family to acceptor processes

* Remove plugin.access_log for core plugins

* Return 501 not implemented for web socket upgrade requests to inbuilt HTTP server

* Add support for websocket upgrade

* Websocket frame parser

* Enable websocket based routing

* Add WebsocketClient

* Websocket

* mypy fixes

* Sync GitHub workflow lint and makefile lint commands.

For now comment out tests which are broken :(  New tests coming next.

* Start fixing tests for new code

* Fix formatting

* Fix main tests

* Add worker tests

* GitHub only ran windows tests, may be require unique names

* Use 3.6/3.7 dev versions for GitHub actions

* Add AcceptorPool test

* Add x64 and x86 matrix for actions tests

* Dont use dev versions since they dont exists for x86

* Ha no x86 support itself

* Add backer link

* Remove support badge for 3.5 as it doesnt support typing

* Update read me with changed architecture notes

* Update read me with changed architecture notes

* Add `import proxy` usage instructions.

* Add pydoc reference for developers

* Put pydoc as internal documentation
2019-10-02 00:09:35 -07:00
Abhinav Singh 3a9c8bc8a2
Create FUNDING.yml 2019-09-27 09:56:31 -07:00
Abhinav Singh ccb1dbeb5f
Pluggable WebServer (#98)
* Enable windows and pre/dev python releases

* Move twine to requirements-release.txt

* 3.5 do not support type annotations

* Use inbuild build_request, build_response methods now.

* First cut of web server route plugin architecture

* Add route decorator

* mypy

* disable TestMultiCoreRequestDispatcherIntegration for github

* Anyways it doesnt format as advertised
2019-09-26 02:07:16 -07:00
Abhinav Singh 292ae497fc
Test coverage and mypy compliance (#94)
* Add tests and mypy compliance for tests

* Add pragma: no cover for abstract class methods

* mypy --strict compliance for tests.py

* Refactor and test coverage

* lint fixes
2019-09-25 15:51:12 -07:00
Abhinav Singh 92142a70d9
Add support for TLS/SSL interception and HTTPS server (#86)
* Handle OSError thrown when curl --proxy-cacert flag is invalid

* Add server-cert

* Dockerfile dont need --ipv4 since now its auto-detected and deprecated

* Add make server-cert info

* Add support for HTTPS interception.

1) Start as

    proxy.py --ca-key-file ca-key.pem --ca-cert-file ca-cert.pem --ca-signing-key-file ca-signing-key.pem

2) Test using curl

    curl -v -L -x proxy.py:8899 --cacert ca-cert.pem https://google.com

Now proxy.py is able to decrypt HTTPS traffic between curl and
google.com.  Generated certificates are stored under ~/.proxy.py
directory.

* Add comments for why interception do not work if client is communicating with proxy.py over https

* Fix tests

* Exit with message when trying to https intercept and also serve over https

* lint

* Disable OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_TLSv1, OP_NO_TLSv1_1 when wrapping upstream server socket

* Ensure client.conn.shutdown is called if necessary.

* Add mypy check for plugin_examples.py

* Exception handling when client sends invalid requests

* Verify plugin_examples

* mypy compat

* HttpRequestRejected
2019-09-24 19:02:57 -07:00
Abhinav Singh 397f92e561
Can serve proxy traffic over HTTPS (#85)
* Can serve proxy traffic over HTTPS.

Pass --certfile and --keyfile arguments to enable SSL/TLS layer.
Example:

1) Start proxy.py as

./proxy.py --certfile cert.pem --keyfile key.pem

2) Then verify via curl

curl -v -x https://localhost:8899 --proxy-cacert cert.pem http://httpbin.org/get

* Add --ignore-missing-imports for missing multiprocessing.reduction module

* mock socket.fromfd to avoid sys calls

* Add HTTPS info

* Add TLS encryption

* Add TLS encryption
2019-09-23 17:38:10 -07:00
Abhinav Singh ae1f1d654c
mypy coverage (#78)
* mypy coverage

* First stab at mypy --strict complaince

* mypy --strict compliance.

* Run mypy during Quality Check phase
2019-09-22 21:11:55 -07:00
Abhinav Singh 5eb4d8a97c
Use Pipe instead of Queue when passing sockets (#69)
* Use pipes instead of queues.

Possible solution for #68

* Handle ConnectionRefusedError

* Close corresponding pipes on shutdown

* Abstract classes for plugins.

* Add github workflows

* Use pytest for github workflow

* Add Windows/Mac workflows

* Use os.matrix

* 3.8 and 3.9 probably dont exists yet

* Do not fail-fast, also python 3.5 seems to be throwing syntax error for typing

* autopep8

* Disable windows-latest workflow which seems to hang
2019-09-16 20:18:14 -07:00