GithubHelp home page GithubHelp logo

cristianoliveira / ergo Goto Github PK

View Code? Open in Web Editor NEW
621.0 7.0 59.0 3.72 MB

The management of multiple apps running over different ports made easy

License: MIT License

Go 63.22% Makefile 2.10% JavaScript 0.05% Shell 29.15% PowerShell 3.52% Nix 1.96%
proxy tools golang proxy-server development development-environment developer-tools ergo reverse-proxy osx

ergo's Introduction

Ergo GoDoc Go Report Card unix win build codecov

Ergo Proxy - The reverse proxy agent for local domain management.

The management of multiple apps running over different ports made easy through custom local domains.

Demo

See more on examples

TL;DR;

python3 -m http.server 8800 & # launch a web server listening on 8800
echo "http://localhost:8800 mylocalsite" > .ergo # adds a service "mylocalsite" to ergo
ergo local & # it may need sudo since it binds to port 80
curl http://mylocalsite.localhost # make a HTTP request to the ergo service :)

Summary

Philosophy

Ergo's goal is to be a simple reverse proxy that follows the Unix philosophy of doing only one thing and doing it well. Simplicity means no magic involved. Just a flexible reverse proxy which extends the well-known /etc/hosts declaration.

Feedback

This project is constantly undergoing development, however, it's ready to use. Feel free to provide feedback as well as open issues. All suggestions and contributions are welcome. :)

For help and feedback you can find us at #ergo-proxy channel on https://gopher.slack.com

Why?

Dealing with multiple apps locally, and having to remember each port representing each microservice is frustrating. I wanted a simple way to assign each service a proper local domain. Ergo solves this problem.

Installation

Important These are the only official ways to install ergo.

OSX

brew tap cristianoliveira/tap
brew install ergo

Linux

To install the latest official version

curl -s https://raw.githubusercontent.com/cristianoliveira/ergo/master/install.sh | sh

Or to install a specific version

curl -s https://raw.githubusercontent.com/cristianoliveira/ergo/master/install.sh v0.2.5 | sh

Windows

From powershell run:

Invoke-WebRequest https://raw.githubusercontent.com/cristianoliveira/ergo/master/install.ps1 -out ./install.ps1; ./install.ps1

You can also find the Windows executables in release.

Disclaimer: I use Unix-based systems on a daily basis, so I am not able to test each build alone. :(

Nix

nix profile install 'github:cristianoliveira/nixpkgs#ergoProxy'

More examples see: https://github.com/cristianoliveira/nixpkgs

Go

go install github.com/cristianoliveira/ergo

Make sure you have $GOPATH/bin in your path: export PATH=$PATH:$GOPATH/bin

Usage

Ergo looks for a .ergo file inside the current directory. It must contain the names and URL of the services following the same format as /etc/hosts (domain+space+url). The main difference is it also considers the specified port.

Subdomains for localhost

Run ergo local it'll attempt to bind to localhost:80 and listen for requests to your services as "subdmains" eg. http://serviceone.localhost and http://servicetwo.localhost. (Check examples for more)

Note: It may requires sudo to bind to port 80.

You can give it a different port by ergo local -p <port> and access it through http://serviceone.localhost:<port>.

You can also add a different loopback in /etc/hosts like echo '127.0.0.1 localapp' >> /etc/hosts and run ergo local -domain localapp to access your services through http://serviceone.localapp and http://servicetwo.localapp.

Setting up as a webproxy

You need to set the http://127.0.0.1:2000/proxy.pac configuration on your system network config.

Ergo comes with a setup command that can configure it for you. The current systems supported are:

  • osx
  • linux-gnome
  • windows
ergo setup <operation-system>

In case of errors / it doesn't work, please look at the detailed config session below.

Adding Services and Running

OS X / Linux

echo "ergoproxy http://localhost:3000" > .ergo
ergo run

Now you should be able to access: http://ergoproxy.dev. Ergo redirects anything ending with .dev to the configured URL.

Windows

You should not use the default .dev domain, we suggest .test instead (see #58) unless your service supports https out of the box and you have already a certificate

set ERGO_DOMAIN=.test
echo "ergoproxy  http://localhost:3000" > .ergo
ergo list # you shouldn't see any quotas in the output
ergo run

Now you should be able to access: http://ergoproxy.test. Ergo redirects anything ending with .test to the configured URL.

Simple, right? No magic involved.

Do you want to add more services? It's easy, just add more lines in .ergo:

echo "otherservice http://localhost:5000" >> .ergo
ergo list
ergo run

Restart the ergo server and access: http://otherservice.dev

ergo add otherservice http://localhost:5000 is a shorthand for appending lines to ./.ergo

Ergo's configuration

Ergo accepts different configurations like run in different port (default: 2000) and change domain (default: dev). You can find all this configs on ergo's help running ergo -h.

Configuration

In order to use Ergo domains you need to set it as a proxy. Set the http://127.0.0.1:2000/proxy.pac on:

Networking Web Proxy

OS X

Network Preferences > Advanced > Proxies > Automatic Proxy Configuration

Windows

Settings > Network and Internet > Proxy > Use setup script

Linux

On Ubuntu

System Settings > Network > Network Proxy > Automatic

For other distributions, check your network manager and look for proxy configuration. Use browser configuration as an alternative.

Browser configuration

Browsers can be configured to use a specific proxy. Use this method as an alternative to system-wide configuration.

Keep in mind that if you requested the site before setting the proxy properly, you have to reset the cache of the browser or change the name of the service. In incognito windows cache is disabled by default, so you can use them if you don't wish to delete the cache

Also you should not use the default .dev domain, we suggest .test instead (see #58) unless your service supports https out of the box and you have already a certificate

Chrome

Exit Chrome and start it using the following option:

# Linux
$ google-chrome --proxy-pac-url=http://localhost:2000/proxy.pac

# OS X
$ open -a "Google Chrome" --args --proxy-pac-url=http://localhost:2000/proxy.pac

Firefox

through menus and mouse
  1. Click the hamburger button otherwise click on "Edit" Menu
  2. then "Preferences"
  3. then "Settings" button at the bottom of the page ("General" active in sidebar) with title "Network Settings"
  4. check Automatic Proxy configuration URL and enter value http://localhost:2000/proxy.pac below
  5. hit "ok"
from about:config

network.proxy.autoconfig_url -> http://localhost:2000/proxy.pac

Using on terminal

In order to use ergo as your web proxy on terminal you must set the http_proxy variable. (Only for linux/osx)

export http_proxy="http://localhost:2000"

Ephemeral Setup

As an alternative you can see the scripts inside /resources for running an ephemeral setup. Those scripts set the proxy only while ergo is running.

Contributing

  • Fork it!
  • Create your feature branch: git checkout -b my-new-feature
  • Commit your changes: git commit -am 'Add some feature'
  • Push to the branch: git push origin my-new-feature
  • Submit a pull request, they are welcome!
  • Please include unit tests in your pull requests

Development

Minimal required golang version go1.22. We recommend using GVM for managing your go versions.

Then simply run:

gvm use $(cat .gvmrc)

Building

  make all

Testing

make test
make test-integration # Requires admin permission so use it carefully.

License

MIT

ergo's People

Contributors

adiclepcea avatar ahamilton55 avatar amake avatar castixgithub avatar cristianoliveira avatar cstadach avatar ebastos avatar eugecm avatar jynthia avatar l0010o0001l avatar mileswilson avatar netaskd avatar sadliak avatar sitaramshelke avatar sp-joseluis-ledesma avatar srini156 avatar vectorhacker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

ergo's Issues

bug: Installer error on Ubuntu

As reported by @ebastos , the install script is falling because of some incompatible "bashisms" I think this script should be as POSIX compliant as possible to work in most shells out there. So I am opening this issue for a refactor in this script.

The error in ubuntu:

$ cat /etc/issue.net 
Ubuntu 17.04
$ ls -ld /bin/sh
lrwxrwxrwx 1 root root 4 Jun  6 17:53 /bin/sh -> dash

Which causes the installer to fail:

$ curl -s https://raw.githubusercontent.com/cristianoliveira/ergo/master/install.sh | sh
sh: 5: declare: not found
sh: 6: Syntax error: "(" unexpected
A possible way to get the install script more POSIX would be to get rid of some bashisms. We can do this using case instead of the current associative array.

Another way would be just using x86_64 instead of linux-amd64 and make it simpler.

feature: Add "remove" service command

Today we have the add command for adding new services into .ergo file. Would be nice to have a remove/delete service as well.

It must have:

  • Option to remove by name or url
  • A message in case of service not found
  • Unit tests

In tests use `ergo` from $PATH than relative path.

While trying to understand the code, I tried to run the tests. There we are looking for ergo binary using relative path in ergo_run_test.go. Can we simply replace it ergo, since we might already have it installed in out $PATH?

docs: Create a Demo gif in good quality

That is simple. Just record your screen basically doing the same steps that we have on currently demo. After you will need to parse this video into an Animated GIF. Please make sure that the quality is good enough. Then override the demo.gif with your new one.

Feel free to ask any questions regarding this process.

bug: Error when running ergo without command

I am having an error when running ergo without providing a command.

Expected behavior:
Show USAGE

Actual behavior:

ergo
panic: runtime error: index out of range

goroutine 1 [running]:
main.command(0x12da13e)
        /Users/cristianoliveira/go/src/github.com/cristianoliveira/ergo/main.go:45 +0xc8c
main.main()
        /Users/cristianoliveira/go/src/github.com/cristianoliveira/ergo/main.go:127 +0xb5

The problem is here. We should look if os.Args has more than 1 item before creating the command

func command() func() {
	config := proxy.NewConfig()
>>>	command := flag.NewFlagSet(os.Args[1], flag.ExitOnError)
	configFile := command.String("config", "./.ergo", "Set the services file")
	command.Parse(os.Args[2:])

It should be easy to solve.

Please also provide a test for it

Can't make it work

in the folder start simple http server

➜ python3 -m  http.server 8080 

then configure ergo per documentation

➜ echo "test http://localhost:8080" > .ergo
➜ ergo list
Ergo Proxy current list:
 - http://test.dev -> http://localhost:8080 

➜ ergo run                    
Ergo Proxy listening on port 2000 for domains .dev

Using httpie

➜ http http://test.dev/ 

http: error: ConnectionError: HTTPConnectionPool(host='test.dev', port=80): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f519d5af490>: Failed to establish a new connection: [Errno 111] Connection refused',)) while doing GET request to URL: http://test.dev/

However when I go through python's process, it works

➜ http http://localhost:8080/main.js
HTTP/1.0 200 OK
Content-Length: 189
Content-type: application/javascript
Date: Sat, 27 Jan 2018 19:56:30 GMT
Last-Modified: Sat, 27 Jan 2018 03:34:43 GMT
Server: SimpleHTTP/0.6 Python/3.6.4

import Vue from "vue";
import store from "./vuex/store";
import App from "./components/App.vue";

new Vue({
  store, // inject store to all children
  el: "body",
  components: { App }
});
➜ ergo -v       
v0.2.2

➜ uname -a
Linux dmitry.io 4.14.14-300.fc27.x86_64 #1 SMP Fri Jan 19 13:19:54 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Feature: new command to add service

Create a command that would do the same as echo "service http://service.de" >> .ergo just for convenience.

The idea is a command like this:

ergo add <localname> <url:port>

Once we call this, I hope the app +url will be included into .ergo file

feature: Install script for Windows

The issue #54 brought a good idea. In order to make easy installing ergo for Windows I think we can have a script like install.sh that we have for linux.

Separate unit and integration tests

This is just a suggestion.
I was thinking that maybe it is better to separate the unit tests from the integration tests (which seem to be more end-to-end tests - see what a Google blog says). This is in the Makefile of course.
This way we can test the code with the unit tests without compiling the binary and then run the integration/end-to-end tests only after the build.
I say that these could be end-to-end tests especially when we add the tests for the setup and for the run . As the setup and run part especially should test if the proxy is being used, and also if an outside page will be accessible while running the proxy.
The new flow would be:

  1. Run the unit tests
  2. Run the build
  3. Run the end-to-end tests
  4. Create the releases (if it is the case).
    This would solve the problem with the tests depending on the executable.

Feature: Use .localhost loopback feature

I just noticed that we could youse the 'foo.localhost' and it will point to 127.0.0.1 but the proxy must bind at port 80. We should use this as an alternative way to create the subdomains :)

Feature: subdomains?

Hey, I just came across this via an answer on stackoverflow. I'd love to be able to use this, but I have a few local servers across subdomains, and I do need them to be subdomains, I can't just use different domains for them because they share cookies.

Thanks for the project, and I'm a big Ergo Proxy fan too :)

Feature: Should FreeBSD support be added?

I have already tested the system on FreeBSD (after small modifications).
The idea is that it runs ok on FreeBSD and perhaps it would run the same on every unix.
To make the system easier to use I believe that we should call the setup switch for linux and freebsd: gnome instead of linux-gnome and separately freebsd-gnome.
Both Linux and FreeBSD are used with the Gnome desktop, thus both of them use the same commands (gsettings set and get) to setup the proxy.
By doing so, we can also unite the tests for linux and freebsd.
Being an radical change I decided it is better to ask for opinions.
Should I continue with the port?

refactor: Turn services into a map.

In a discussion on slack channel I got some good feedback about the code and one of the ideas is instead of using a slice of Services use a map. This makes the function GetService practically not necessary plus it guarantees the services to be Unique.

Use a separate temporary config file for testing

Right now there is a repetitive code that copies the original content of the config file at the beginning of the test and then rewrites it at exit so that we can have the same values at each test.
see

A file copy of the original config should be done and that should be used instead. This could be put in a separate method to avoid code repetition.

refactor: Do we need the channels to update the configs?

I got another feedback from the Slack Channel:

WatchConfigFile can run in parallel and change Services by itself behind a mutex, because that's basically what happens right not anyways.

Other:

Anyone access this config can be synchronized using the same mutex. The caller already has the goroutines. This is not an orchestration problem but a synchronization problem.

So I am thinking that we can get rid of the channels and just work with the mutex + gorotine for this case.

Feature: auto config system proxy settings

I quickly set up the following wrapper--maybe something like it should be baked in, and triggered on a flag? This one is Ubuntu-only:

function finish {
  # these should probably revert to original settings
  gsettings set org.gnome.system.proxy mode "none"
  gsettings set org.gnome.system.proxy.http host ""
  gsettings set org.gnome.system.proxy.http port "8080"
}
trap finish EXIT

gsettings set org.gnome.system.proxy mode 'auto'
gsettings set org.gnome.system.proxy autoconfig-url http://127.0.0.1:2000/proxy.pac 

$GOPATH/bin/ergo run

bug: Error when ergo file has a bad format.

While testing on windows I noticed that when running ergo using a bad file it raises the follow error:

ergo run
panic: runtime error: index out of range

goroutine 1 [running]:
github.com/cristianoliveira/ergo/proxy.LoadServices(0x12d8403, 0x7, 0x0, 0x0, 0x0)
        /Users/cristianoliveira/go/src/github.com/cristianoliveira/ergo/proxy/config.go:61 +0x43e
main.main()
        /Users/cristianoliveira/other/ergo/main.go:58 +0x2f2

The file .ergo content:

foo

Improve code quality

By this I mean adding compliance checking with the go coding standards ( gofmt, go vet and golint).

feature: Configuration file.

This issue is needed in order to enable run ergo using a custom TDL like .test or any other the user would like to use.

We need to decide the name of this file and its format.

Bug: Error ERR_ICANN_NAME_COLLISION

I am having the following error sporadically:

Try contacting your system administrator.
ERR_ICANN_NAME_COLLISION

I searched around to understand it and reached this thread.
https://superuser.com/questions/919278/err-icann-name-collision-when-trying-to-use-localhost-dev-in-chrome

It seems it occurs because .dev domain has become a registered ICANN Top Level Domain. So some domains that really exist and are registered can collide.

So I would like to open a discussion for changing the .dev to another TLD which is not registered yet.

My suggestions would be .local but I am not convinced about this option yet

What do you think?

Enhancement: Upgrade log messages

Upgrade log message to this format:

[datetime] "<HTTP Verb> <Route>" <StatusCode>

# Example
[28/Aug/2017 14:16:51] "GET http://feedcast.dev./favicon.ico" 404

Feature: Setup command add support to other linux flavors and windows

The setup command aims to auto-configure your system to use ergo as the proxy. Currently, we only support two systems OSX and Linux-gnome. Would be nice to expand this support to more systems/flavors.

Here is the implementation:
https://github.com/cristianoliveira/ergo/blob/master/commands/setup.go

Your task is:

  • Discover how to set up a proxy by command line. For instance for gnome we do the follow commands: 👨‍🔬 👩‍🔬
gsettings set org.gnome.system.proxy mode 'auto'
gsettings set org.gnome.system.proxy autoconfig-url http://127.0.0.1:2000/proxy.pac 
  • Implement that on commands/setup.go 🛠
  • Test if it actually works 👍
  • Make the pull request. 📦
  • Scores up toward your goal that is the T-shirt we all want 🎉

docs: Fix typos and improve description - Hacktoberfest

Hello, fellow Hacktoberfest contributor!

I am opening this issue especially for Hacktoberfest. I am not a native English speaker and I am so used to read the project readme that I am not able to see all typos it might have.

So I invite you to take a look at it and if you find out either a typo or a weird sentence please feel free to point it out and open a PR with a fix for it. 😄

Also feel free to suggest description changes to make it easier to understand the purpose of this project/app 😃

Please make sure you point this issue on your PR (refers #37)

⚠️UPDATE: We are having a lot of PR for this. Please make sure you took a look at others Open PRs before opening a new one :)

Please feel free to ask anything.

Style: Fix lints reports

Today we have 30% for go lint on goreport. We can do better.

https://goreportcard.com/report/github.com/cristianoliveira/ergo

Golint is a linter for Go source code.

        ergo/commands/setup.go
        Line 12: warning: exported function Setup should have comment or be unexported (golint)
        Line 14: warning: don't use underscores in Go names; var proxy_url should be proxyURL (golint)

        ergo/proxy/config.go
        Line 10: warning: exported type Service should have comment or be unexported (golint)
        Line 15: warning: exported type Config should have comment or be unexported (golint)
        Line 23: warning: exported method Config.GetService should have comment or be unexported (golint)
        Line 35: warning: exported function NewConfig should have comment or be unexported (golint)
        Line 44: warning: exported function LoadServices should have comment or be unexported (golint)

        ergo/commands/url.go
        Line 8: warning: exported function Url should have comment or be unexported (golint)

        ergo/proxy/proxy.go
        Line 37: warning: exported function NewErgoProxy should have comment or be unexported (golint)
        Line 78: warning: exported function ServeProxy should have comment or be unexported (golint)

        ergo/main.go
        Line 11: warning: exported var VERSION should have comment or be unexported (golint)
        Line 13: warning: exported const USAGE should have comment or be unexported (golint)

        ergo/tests/ergo_run_test.go
        Line 22: warning: don't use underscores in Go names; var apps_outoput should be appsOutoput (golint)
        Line 47: warning: don't use underscores in Go names; var apps_outoput should be appsOutoput (golint)
        Line 72: warning: don't use underscores in Go names; var apps_output should be appsOutput (golint)

        ergo/commands/list.go
        Line 8: warning: exported function List should have comment or be unexported (golint)

        ergo/commands/list_names.go
        Line 8: warning: exported function ListNames should have comment or be unexported (golint)

        ergo/commands/run.go
        Line 9: warning: exported function Run should have comment or be unexported (golint)

Feature: show command

Add a ergo show [name] command for showing the url for the given name. It will enable us to do things like this:

# OSX
open $(ergo show foo)

# Linux
xdg-open $(ergo show foo)

# or
curl $(ergo show foo)

tests: Improve unit tests codecoverage

Thanks to @adiclepcea and his great work with the integration tests ergo is mostly covered by tests! 🥂

Although we are mostly covered, it doesn't reflect on codecov.io cause it gets only test coverage by "unit tests" and on the integration tests we use a compiled ergo's binary.

Today at codecov we have the follow report:

folder/file lines lines hit lines partially lines missing %
commands 212 0 0 0 0%
-- -- -- -- -- --
proxy 138 71 6 61 51.44%
-- -- -- -- -- --
main.go 59 48 5 6 81.35%

Would be nice to improve coverage in proxy folder and has at least some in commands 😅

Brew shows "Error: SHA256 mismatch"

Error: SHA256 mismatch
Expected: b46e32dbc38523073728ee53a2db06dfed36e30c935a7dabb3e15b93dd8f6bcc
ergo
v0
1
5
darwin
amd64
tar
gz
Actual: b46e32dbc38523073728ee53a2db06dfed36e30c935a7dabb3e15b93dd8f6bcc
Archive: .../ergo-v0.1.5.tar.gz

Feature: Add support to other protocols

Today we have only support for http:// and it is not possible to map for instance Redis or Mongo:

  • mongodb://localhost: 27017
  • redis://localhost:6379

It would be nice if we can map them

feature: Add flag for changing the default domain`.dev`

Today we use as default the TLD .dev but would be nice to change it when needed or for test. So we should have a flag on run command in order to change it for a custom "domain".

ergo run -domain=.test

Things it must have:

  • Domain validation. it must validate the domains, for instance foo is not but .foo is valid.
  • It must reflect on localhost:2000/proxy.pac
  • A simple flag name. feel free to come up with your idea.
  • Update readme with it.
  • A test would be nice, but if you think it is hard to test we can help you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.