For dynamic content, we could use Dart's HTTP server, but we probably wouldn't expose it directly to the Internet and rather put in behind a reverse proxy.
If you really wanted to expose your server to anyone, you need to tell the HTTP server to accept connections from all IPs with ANY_IP_V4
instead of LOOPBACK_IP_V4
:
var addr = InternetAddress.ANY_IP_V4
This also applies to WebSockets servers.
Accessing Dart servers via Apache or nginx reverse proxies lets you stay with LOOPBACK_IP_V4
(127.0.0.1
, aka localhost), which is generally safer.
As we said, we can use Apache to serve all static content and proxy all nonstatic requests to the Dart HTTP server. You can modify your hosts
file to point dart.localhost
to 127.0.0.1
if you're already using virtual hosts on your computer and add a new directive to the Apache configuration:
<VirtualHost *:80> DocumentRoot "/project/path/Chapter_07_route_http_server/public" ServerName dart.localhost RewriteEngine on RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f RewriteRule ^/(.*)$ http://127.0.0.1:8081/$1 [P,QSA,L] <Directory "/project/path/Chapter_07_route_http_server/public"> Order allow,deny Allow from all </Directory> </VirtualHost>
If you've ever used PHP with Apache, you've probably already met .htaccess
files to pass all nonstatic requests to index.php
. These rewrite rules use exactly the same principle. They check whether a requested URI is an existing file with RewriteCond %{REQUEST_FILENAME} !-f
and if it is not, they pass the request to http://127.0.0.1:8081/<request-uri>
, where our Dart HTTP server is running. The response is automatically sent back to the client.
The [P]
flag at the end is crucial because it activates Apache's reverse proxy. Using this kind of reverse proxy in Apache requires mod_proxy
, mod_proxy_html
, and mod_rewrite
modules installed.
We can test that it really works by looking at the Apache access log and comparing it with the Dart server's requests. For example, I see these logs in my /var/log/apache/access_log
file:
127.0.0.1 [15:38:20] "GET /dart-logo.png HTTP/1.1" 200 21903 127.0.0.1 [15:38:24] "GET / HTTP/1.1" 200 29 127.0.0.1 [15:40:22] "GET /article/my-article HTTP/1.1" 200 40 127.0.0.1 [15:40:22] "GET /subdir/random-file.txt HTTP/1.1" 200 17
These are requests to the Apache server, which should pass two of them to the Dart server, and it did:
$ dart bin/server.dart Server running ... / /article/my-article
The same principle works for the nginx configuration:
location / { root "/project/path/Chapter_07_route_http_server/public"; try_files $uri @darthttpserver; } location @darthttpserver { proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:8081; }
The try_files
directive tests whether $uri
exists as a file under the root
directory, and if it doesn't, it makes an internal redirect to @darthttpserver
, where we pass the request to the Dart HTTP server.
With nginx, we can be a little more generous and redefine HTTP headers sent to the Dart server with proxy_set_header
. Here, we're setting headers such as client's real IP, because from Dart's point of view, it seems like all requests come from localhost.
Although it's possible to run the Dart code as a CGI script, it's not a good idea for real-world applications. It basically runs a standalone Dart VM for each request, which causes a new process to spawn, allocates memory, loads Dart libraries, compiles them, and runs your code. It causes significant overhead, which can be easily avoided by running Dart as an HTTP server.
There is also an Apache module called mod_dart
that promised embedding Dart VM into Apache workers. The same approach is commonly used with Apache and mod_php5
. Unfortunately, the project is currently not maintained any more. Rumors among Dartisans say that you can compile it with a few modifications but it's stale and possibly unstable with security holes and you should never use it.
If you have to use Apache, stay with reverse proxying requests as we saw earlier.
3.145.52.188