Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Use ".test" TLD rather than Google-owned ".dev" TLD. (#68)
- .dev is an official gTLD: https://icannwiki.org/.dev
- Chrome is forcing .dev to HTTPS: https://ma.ttias.be/chrome-force-dev-domains-https-via-preloaded-hsts/
- ".test" is a reserved TLD that will not suffer from this issue.
  • Loading branch information
jacksonrayhamilton authored and ysbaddaden committed Jan 8, 2018
1 parent 8770275 commit 2b89e19
Show file tree
Hide file tree
Showing 13 changed files with 66 additions and 41 deletions.
33 changes: 29 additions & 4 deletions README.md
Expand Up @@ -23,15 +23,15 @@ For other systems, you'll have to follow the

## How it works

1. resolves `*.dev` domains to 127.0.0.1 / ::1 (localhost)
1. resolves `*.test` domains to 127.0.0.1 / ::1 (localhost)
2. redirects the :80 and :443 ports to :20559 and :20558
3. receives incoming HTTP requests and extracts the hostname (eg: myapp.dev)
3. receives incoming HTTP requests and extracts the hostname (eg: myapp.test)
4. spawns a Rack applications (found at `~/.prax/myapp`) if any
5. proxies the request to the spawned Rack aplication or to the specified port.

### `.dev` TLD
### `.test` TLD

Prax proposes 2 solutions to resolve `.dev` domains:
Prax proposes 2 solutions to resolve `.test` domains:

- a dnsmasq configuration, either throught NetworkManager or by installing
dnsmasq manually (eg. through your Linux distribution package);
Expand All @@ -48,6 +48,25 @@ is conflicting with a local resolver. I don't have a solution —except to stay
as far away as possible from systemd as possible.


### Other TLDs

If `.test` domains are not your cup of tea, no problem! Prax will route
requests from any TLD to the applications in your `~/.prax` directory, as long
as the domain resolves to localhost.

For instance, if you wished to visit "myapp.dev" instead of "myapp.test", you
could create dnsmasq configuration to resolve ".dev" domains to localhost, too:

```
sudo tee /etc/dnsmasq.d/dev <<EOF
local=/dev/
address=/dev/127.0.0.1
address=/dev/::1
EOF
sudo service dnsmasq restart
```


### Port Redirections

The port redirections are iptables rules, that are installed and removed using
Expand All @@ -56,6 +75,12 @@ each `wlanX` and `ethX` devices found on your machine, to allow incoming
traffic, so you may use xip.io to test on external devices, as mentioned above.


### Issues

In Chrome, if one types "myapp.test" into the URL bar, Chrome will issue a
search. Type "http://myapp.test" or "myapp.test/" instead to visit that URL.


## License

Prax is distributed under the [CeCILL 2.1 license](http://www.cecill.info).
Expand Down
2 changes: 1 addition & 1 deletion ext/README.md
@@ -1,7 +1,7 @@
# NSSwitch hosts resolver plugin

Allows software that rely on NSSwitch to resolve domains for Prax (like
myapp.dev). Command line software like `host` and `dig` won't resolve the
myapp.test). Command line software like `host` and `dig` won't resolve the
address, but `getent` will.

## Install
Expand Down
2 changes: 1 addition & 1 deletion ext/nss_prax.c
Expand Up @@ -60,7 +60,7 @@ _nss_prax_gethostbyname2_r(const char *name,
char *env = getenv("PRAX_DOMAINS");
char *domains;
if (env == NULL) {
domains = strdup("dev");
domains = strdup("test");
} else {
domains = strdup(env);
}
Expand Down
6 changes: 3 additions & 3 deletions install/dnsmasq
@@ -1,3 +1,3 @@
local=/dev/
address=/dev/127.0.0.1
address=/dev/::1
local=/test/
address=/test/127.0.0.1
address=/test/::1
6 changes: 3 additions & 3 deletions libexec/prax-open
Expand Up @@ -8,9 +8,9 @@
#
# $ cd ~/work/myapp
# $ prax open
# open http://myapp.dev
# open http://myapp.test
# $ prax open othername
# open http://othername.dev
# open http://othername.test
set -e

. "$PRAX_ROOT/libexec/shared.sh"
Expand All @@ -23,4 +23,4 @@ else
fi

set -x
xdg-open "http://$name.dev"
xdg-open "http://$name.test"
2 changes: 1 addition & 1 deletion src/prax/application/finders.cr
Expand Up @@ -30,7 +30,7 @@ module Prax

private def self.search(host)
if m = XIP_IO.match(host)
host = m[1] + ".dev"
host = m[1] + ".test"
end
names = host.split('.').tap(&.pop)

Expand Down
2 changes: 1 addition & 1 deletion src/prax/templates/welcome.ecr
Expand Up @@ -9,5 +9,5 @@

<pre><span>$</span> cd /path/to/myapp
<span>$</span> prax link
<span>$</span> firefox http://myapp.dev/</pre>
<span>$</span> firefox http://myapp.test/</pre>
</section>
6 changes: 3 additions & 3 deletions test/failures_test.rb
Expand Up @@ -3,7 +3,7 @@
class FailuresTest < Minitest::Test
def test_rackup_config
File.unlink log_path(:invalid) rescue nil
html = Net::HTTP.get(URI('http://invalid.dev:20557/'))
html = Net::HTTP.get(URI('http://invalid.test:20557/'))

assert_match "Error starting application", html
assert_match "crash on application boot", html
Expand All @@ -12,7 +12,7 @@ def test_rackup_config

def test_rackup_config_runs_nothing
File.unlink log_path('wont-run') rescue nil
html = Net::HTTP.get(URI('http://wont-run.dev:20557/'))
html = Net::HTTP.get(URI('http://wont-run.test:20557/'))

assert_match "Error starting application", html
assert_match "missing run or map statement", html
Expand All @@ -21,7 +21,7 @@ def test_rackup_config_runs_nothing

def test_host_header_is_missing_but_found_in_uri
TCPSocket.open("localhost", 20557) do |socket|
socket.write("GET http://example.dev:20557/ HTTP/1.1\r\n\r\n")
socket.write("GET http://example.test:20557/ HTTP/1.1\r\n\r\n")
assert_equal "HTTP/1.1 200 OK\r\n", socket.gets
end
end
Expand Down
8 changes: 4 additions & 4 deletions test/keepalive_test.rb
Expand Up @@ -3,9 +3,9 @@
#class KeepaliveTest < Minitest::Test
# def test_handles_multiple_request_on_a_single_connection
# TCPSocket.open("localhost", 20557) do |socket|
# socket.write "GET / HTTP/1.1\r\nHost: app1.example.dev\r\nContent-Length: 0\r\n\r\n"
# socket.write "GET / HTTP/1.1\r\nHost: app2.example.dev\r\nContent-Length: 0\r\n\r\n"
# socket.write "GET / HTTP/1.1\r\nHost: example.dev\r\nContent-Length: 0\r\n\r\n"
# socket.write "GET / HTTP/1.1\r\nHost: app1.example.test\r\nContent-Length: 0\r\n\r\n"
# socket.write "GET / HTTP/1.1\r\nHost: app2.example.test\r\nContent-Length: 0\r\n\r\n"
# socket.write "GET / HTTP/1.1\r\nHost: example.test\r\nContent-Length: 0\r\n\r\n"
#
# assert_equal "HTTP/1.1 200 OK\r\n", socket.gets
# assert_match "app1.example", read(socket)
Expand All @@ -20,7 +20,7 @@
#
# def test_no_keepalive_for_connection_close
# TCPSocket.open("localhost", 20557) do |socket|
# socket.write "GET / HTTP/1.1\r\nHost: example.dev\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
# socket.write "GET / HTTP/1.1\r\nHost: example.test\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
# socket.read # won't block for 15 seconds
# end
# end
Expand Down
2 changes: 1 addition & 1 deletion test/port_forwarding_test.rb
Expand Up @@ -26,7 +26,7 @@ def test_forwards_to_given_port
Thread.pass
end

assert_equal response, Net::HTTP.get(URI("http://forward.dev:20557/"))
assert_equal response, Net::HTTP.get(URI("http://forward.test:20557/"))
t1.join
end
end
2 changes: 1 addition & 1 deletion test/praxrc_test.rb
Expand Up @@ -2,7 +2,7 @@

class PraxrcTest < Minitest::Test
def test_praxrc_loaded
assert_equal "itworks", Net::HTTP.get(URI("http://praxrc.dev:20557/"))
assert_equal "itworks", Net::HTTP.get(URI("http://praxrc.test:20557/"))
assert_equal "itworks", Net::HTTP.get(URI("http://praxrc.127.0.0.1.xip.io:20557/"))
end
end
26 changes: 13 additions & 13 deletions test/proxy_test.rb
Expand Up @@ -3,14 +3,14 @@

class ProxyTest < Minitest::Test
def test_proxies_to_rack_applications
assert_equal "example", Net::HTTP.get(URI("http://example.dev:20557/"))
assert_equal "example", Net::HTTP.get(URI("http://www.example.dev:20557/"))
assert_equal "example", Net::HTTP.get(URI("http://example.test:20557/"))
assert_equal "example", Net::HTTP.get(URI("http://www.example.test:20557/"))

assert_equal "app1.example", Net::HTTP.get(URI("http://app1.example.dev:20557/"))
assert_equal "app1.example", Net::HTTP.get(URI("http://www.app1.example.dev:20557/"))
assert_equal "app1.example", Net::HTTP.get(URI("http://app1.example.test:20557/"))
assert_equal "app1.example", Net::HTTP.get(URI("http://www.app1.example.test:20557/"))

assert_equal "app2.example", Net::HTTP.get(URI("http://app2.example.dev:20557/"))
assert_equal "app2.example", Net::HTTP.get(URI("http://w3.app2.example.dev:20557/"))
assert_equal "app2.example", Net::HTTP.get(URI("http://app2.example.test:20557/"))
assert_equal "app2.example", Net::HTTP.get(URI("http://w3.app2.example.test:20557/"))
end

def test_proxies_to_shell_application
Expand All @@ -27,29 +27,29 @@ def test_supports_xip_io
end

def test_returns_multiple_set_cookie_headers
response = Net::HTTP.get_response(URI("http://cookies.dev:20557/"))
response = Net::HTTP.get_response(URI("http://cookies.test:20557/"))
assert_equal ["first=123", "second=456"], response.get_fields("Set-Cookie")
end

def test_supports_bundler_with_special_gems
assert_equal "1.0", Net::HTTP.get(URI("http://bundler.dev:20557/"))
assert_equal "1.0", Net::HTTP.get(URI("http://bundler.test:20557/"))
end

def test_alters_request_headers_and_sets_proxy_headers
response = Net::HTTP.get(URI("http://headers.dev:20557/"))
response = Net::HTTP.get(URI("http://headers.test:20557/"))
headers = JSON.parse(response)

assert_equal "headers.dev:20557", headers["HTTP_HOST"]
assert_equal "headers.test:20557", headers["HTTP_HOST"]
assert_equal "close", headers["HTTP_CONNECTION"]

assert_equal "headers.dev:20557", headers["HTTP_X_FORWARDED_HOST"]
assert_equal "headers.test:20557", headers["HTTP_X_FORWARDED_HOST"]
assert_equal "http", headers["HTTP_X_FORWARDED_PROTO"]
assert_equal "::1", headers["HTTP_X_FORWARDED_FOR"]
assert_equal "::1", headers["HTTP_X_FORWARDED_SERVER"]
end

def test_augments_proxy_headers
Net::HTTP.start("headers.dev", 20557) do |http|
Net::HTTP.start("headers.test", 20557) do |http|
response = http.get("/", {
"X-Forwarded-For" => "192.168.1.53",
"X-Forwarded-Server" => "10.0.3.1",
Expand All @@ -61,7 +61,7 @@ def test_augments_proxy_headers
end

def test_empty_header
response = Net::HTTP.get_response(URI("http://empty-header.dev:20557/"))
response = Net::HTTP.get_response(URI("http://empty-header.test:20557/"))
assert_equal "", response["Access-Control-Expose-Headers"]
assert_equal "an empty header is tolerated", response.body
end
Expand Down
10 changes: 5 additions & 5 deletions test/public_file_test.rb
Expand Up @@ -2,18 +2,18 @@

class PublicFileTest < Minitest::Test
def test_serves_files_in_public_folder
assert_equal "my file contents\n", Net::HTTP.get(URI("http://example.dev:20557/file.txt"))
assert_equal "my file contents\n", Net::HTTP.get(URI("http://example.test:20557/file.txt"))
assert_equal "my file contents\n", Net::HTTP.get(URI("http://example.127.0.0.1.xip.io:20557/file.txt"))
end

def test_serves_files_for_non_rack_application
assert_equal "/index.html\n", Net::HTTP.get(URI("http://public.dev:20557/index.html"))
assert_equal "/folder/index.html\n", Net::HTTP.get(URI("http://public.dev:20557/folder/index.html"))
assert_equal "/index.html\n", Net::HTTP.get(URI("http://public.test:20557/index.html"))
assert_equal "/folder/index.html\n", Net::HTTP.get(URI("http://public.test:20557/folder/index.html"))
end

def test_serves_index_html
assert_equal "/index.html\n", Net::HTTP.get(URI("http://public.dev:20557/"))
assert_equal "/folder/index.html\n", Net::HTTP.get(URI("http://public.dev:20557/folder"))
assert_equal "/index.html\n", Net::HTTP.get(URI("http://public.test:20557/"))
assert_equal "/folder/index.html\n", Net::HTTP.get(URI("http://public.test:20557/folder"))
end

def test_sets_correct_content_type
Expand Down

0 comments on commit 2b89e19

Please sign in to comment.