Anchora: HTTP/2.0 Static Server
⚓ Powerful yet simple HTTP/2 static server for node. Push enabled!
What?
Anchora is a HTTP static server module for Node.js. Simple, fast, powerful, flexible, yada yada yada...
But really. It does a lot out of the box with no configuration. Even HTTP2 and Push Streams of file dependencies.
This repository contains the Anchora Engine used in and originally developed for but not limited to use in Anchora App (A simple Windows store app providing UI around this engine).
Why?
Why another static server for node? There are many already in the npm registry.
It wasn't initial intention to compete with them.
Anchora was originally developed for an app that would replace Apache or XAMPP and become frontend dev's best friend. But it has since outgrew the app and became npm module, with friendly API, to be used by devs like you ;).
Most importantly - none of the existing modules implement HTTP2 and Push Streams. Anchora does. And comes preconfigured with CORS, generates self-signed HTTPS certificates, and more.
FAQ
- Who is this for Frontend developers and tinkerers.
- What does it do out of the box? All that your heart desires. HTTP2 push streams, CORS, HTTP & HTTPS servers, GZIP, advanced caching (both client and server side), auto generated HTTPS certificates, redirects, ...
- HTTPS? Yes. We'll generate and install CA for you and sign every localhost cert with it.
- Can I use it to test service workers? Just install the CA certificate on your phone.
- So it suports HTTP2? YES! YES! It's the sole reason why I developed yet another static serve.
- And HTTP2 Push Streams? Yup. Automatically, out of the box, with zero configuration.
- How does the Push work? HTML, JS and CSS files are parsed and dependency links extracted and cached (until the file changes again) for future use. But don't worry. It's async and designed to not slow down content serving.
- Can this server run PHP, Ruby, Python or any other CGI script? Well, yes. But it's still experimental, for localhost tinkering until proven stable. See
/examples
for PHP demo. Help with testing from users of said languages would be great - Is this project production ready? Not really, hopefuly some day.
- How stable is it? Fairly. It's used and dogfed daily and maintained regularly. Though Node's 'http2' module is still unstable.
- Caching? Customizable. Tuned for effective development. Frequent files are kept in memory to reduce disk reads,
cache-control=must-revalidate
, 304s are served if file is unchanged (thanks to ETag).
Features
Anchora is designed to support the hottest tech. Automatically and out of the box. With ease.
- HTTP2 push streams.
- Automatic parsing of files and delivering their (sub)dependencies.
- Parses HTML, JS and CSS files, extracts links, generates tree of dependencies. Uses
link-extract
module.
- Caching
- ETag: Creates 'fingerprint' of served files. It ensures serving always up-to-date files. Unlike expiration time based caching.
- Client-side: 304 Not Modified &
must-revalidate
. All files are cached along with their ETags which are then used in future requests. Server only responds if the file changed since (and the file's ETag is different). - Server-side: Stores frequently used files in memory to reduce disk reads.
- By default tuned for effective and blazing fast frontend development.
- HTTPS certificates
- Generates (and installs) Root CA
- Generates self-signed localhost certificates. Per IP. Signed by the CA (automatically trusted by browsers).
- Complies with all the latest security restrictions & annoyances in Chrome.
- Or supply your won cert.
- HTTPS localhost has never been simpler.
- Compression
- GZIP and Deflate
- Passive mode. Tries to serve pre-compressed .gz alternatives of the requested file.
- CORS headers.
- Can run HTTP and HTTPS (or HTTP2 hybrid) server simultaneously
- HTTP to HTTPS upgrade redirect (either forced or requested with
upgrade-insecure-requests
header) - CGI: PHP and other scripting laguages support (experimental).
- Ranges (partial support).
- Custom HTTP headers
- Extensible API (such as Markdown renderer)
Installation & Usage
npm install anchora
Example
import anchora from 'anchora'
var server = anchora.createServer('both')
var server = anchora.createServer()
var server = anchora.createServer('http1')
var server = anchora.createServer('http1', 8080)
var server = anchora.createServer('https', {gzip: true})
var server = anchora.createServer('dev')
var server = anchora.createServer('hybrid', 'dev')
var server = anchora.createServer('http2', 'dev', 3000)
API
anchora.createServer()
Creates server(s). Similar to https.createServer
& https.createServer
except for the listener argument.
Accepts various arguments
createServer([portUnsecure, portSecure])
createServer(port)
createServer('type')
createServer('preset')
createServer({options})
createServer('type', 'preset')
createServer('type', port)
createServer('type', [portUnsecure, portSecure])
createServer('type', port, 'preset')
createServer('type', [portUnsecure, portSecure], 'preset')
createServer('type', port, {options})
createServer('type', [portUnsecure, portSecure], {options})
server#listen([ports])
Starts listening (both) server(s) on previously configure ports or those passed in argument.
server#close()
Closes (both) server(s).
server#listening
Returns true of false is server(s) are running.
Server types
One of following types can be used as a type
argument for .createServer()
.
http
, http1
- creates http
server at port 80https
- creates https
server at port 443http2
- creates http2
server at port 443hybrid
- creates http
& https
servers at ports 80 & 443both
- creates http
& http2
servers at ports 80 & 443
Presets
One of following presets can be used as a preset
argument for .createServer()
.
dev
- Applies following options:
{
folderBrowser: true,
cacheControl: 'must-revalidate',
pushMode: 'aggressive',
gzip: false,
cors: true,
forceUpgrade: false,
allowUpgrade: false,
headers: {'strict-transport-security': 'max-age=0'}
}
prod
, production
- Applies following options:
{
folderBrowser: false,
pushMode: 'optimized',
gzip: true,
allowUpgrade: true,
}
Options
{
port: undefined,
portUnsecure: 80,
portSecure: 443,
type: undefined,
http: true,
https: true,
http2: false,
gzip: false,
encoding: undefined,
root: process.cwd(),
indexFile: 'index.html',
folderBrowser: true,
acceptRanges: true,
cors: true,
corsOrigin: '*',
corsMethods: ['GET', 'POST', 'OPTIONS', 'PUT', 'PATCH', 'DELETE'],
corsHeaders: ['x-requested-with', 'content-type'],
corsCredentials: true,
csp: false,
charset: 'utf-8',
pushMode: 'optimized',
pushMimes: [
'text/html',
'text/css',
'text/javascript',
'application/javascript',
'application/json',
],
cacheFiles: true,
cacheSize: 100 * 1024 * 1024,
cacheMaxFileSize: 5 * 1024 * 1024,
cacheMaxAge: 2 * 60 * 60 * 1000,
cacheCleanupInterval: 5 * 60 * 1000,
cacheMimes: [
'text/cache-manifest',
'text/css',
'text/html',
'text/plain',
'application/javascript',
'application/json',
'application/xml',
'image/'
],
headers: undefined,
cacheControl: 'must-revalidate',
maxAge: undefined,
forceUpgrade: false,
allowUpgrade: true,
redirectCodeHttps: 301,
redirectCode: 302,
unknownMime: 'text/plain',
certPath: undefined,
crtPath: undefined,
keyPath: undefined,
cert: undefined,
key: undefined,
certDir: path.join(process.cwd(), `./certificates/`),
cgi: false,
cgiEnv: undefined,
phpPath: undefined,
rubyPath: undefined,
perlPath: undefined,
plugins: {},
}
How it works.
Anchora uses all three node modules: http
and either of https
or http2
in conjunction (since browsers only support HTTP2 secure connections, i.e. HTTP2 in HTTPS mode) atop which is compat layer for handling both 1.1 and 2.0 requests. ALPN negotiation allows supporting both HTTPS and HTTP2 over the same socket. Anchora then proceeds to open push streams with dependency files if and where available.
See more Node HTTP2 documentation for more on compatibility.
Node's http2
module is still in flux and conscidered experimental. Anchora's push stream implementation might contain few bugs and implementation in browser's is also doubtful (when considering module scripts in Chrome for example). Expect it to not work at some level (should not break but degrade degracefuly though) and do not use it in production yet.
Tested on Node 9.5 - 9.9. Older versions will not work due to changing API of http2
module.
Basic
content-type
content-length
transfer-encoding
GZIP and Deflate compression
Caching, ETAG
cache-control
etag
last-modified
expires
if-modified-since
if-none-match
CORS & CSP
access-control-allow-methods
access-control-allow-headers
access-control-allow-credentials
content-security-policy
Ranges
accept-ranges
range
content-range
if-range
???
Redirects
location
upgrade-insecure-requests
not supported
if-match
if-unmodified-since
if-range
Ideas for the future
- CLI
- host proxy & custom domains - usee 'host' header to use different root folder. Useful when custom domains in hosts file are created where each domain could point to a different project folder.
- service workers?
- Further work on enabling CGI, or perhaps implementation of FastCGI, testing and adding support for more languages other than PHP.
- Conditional requests.
Join the discussion
Wanna come say hi, discuss the ideas and features, help out with fixing bugs or sharing about your workflow so that we could make Anchora suit you even better?
Join our strictly casual discord server or Gitter
Get it as an app!
Anchora powers Anchora App for Windows 10. Get it from Windows Store or check out the source code.
Credits
Made by Mike Kovařík, Mutiny.cz