Using configuration

Pass an object or use Config directly.

CommonJS · representative configuration
const {Server}=require('node-http-server');

const server=new Server({
    host:'127.0.0.1',
    port:8080,
    root:'./public',
    server:{
        noCache:false,
        allowDotfiles:false,
        compression:true,
        maxRequestBodyBytes:1048576
    }
});

server.deploy();
APIBehavior
new Server(values?)Creates an instance with an isolated Config.
server.deploy(values?)Merges supplied values before deployment.
new Config(values?)Creates isolated configuration without deploying.
config.merge(values)Safely merges and returns the same Config instance.
Config.defaultsReturns a fresh copy of all defaults.
Config.mimeTypesReturns a fresh built-in MIME map.
CommonJS subpaths
const Config=require('node-http-server/config');
const mimeTypes=require('node-http-server/mime-types');
ESM subpaths
import Config from 'node-http-server/config';
import mimeTypes from 'node-http-server/mime-types';

Network, roots, and top-level state

Separate binding from Host routing.

KeyDefaultPurposePlayground
host'127.0.0.1'Address passed to listen().Location and host routing
port8080HTTP port; 0 requests an ephemeral port.Location and host routing
rootprocess.cwd()Default static root.Location and host routing
domain'0.0.0.0'Legacy primary Host check; host controls the bind address.Location and host routing
domains{}Additional hostname-to-root mappings.Additional domains JSON
verbosefalseSanitized operational console output.HTTP behavior
servertable belowStatic HTTP behavior and Node timeouts.HTTP behavior + Timeouts
httpsempty valuesCertificate paths and secure listener mode.HTTPS
contentTypebuilt-in mapMIME additions/overrides, or false.File types and restrictions
restrictedType{}Truthy extension keys return 403.File types and restrictions
errorsbuilt-in mapError headers and status bodies.Logging and errors
logfalseNDJSON destination or logging off.Logging and errors
logBodyfalseInclude UTF-8 body in request records.Logging and errors
logFunctionbuilt inCustom request-record writer.Module-only function stub
host versus domain: host chooses the network interface. domain and domains choose accepted HTTP/1 Host or HTTP/2 :authority values and static roots. A mismatch returns 421.
Compiled routing: deploy() builds an O(1) table for domain, domains, and their canonical roots. Live root/domain assignments and domain-map changes invalidate it; the next request rebuilds the table with the current values.
Virtual-host requirement: wildcard domain:'0.0.0.0' or domain:'*' selects the primary root before domains is consulted. Set a nonwildcard primary domain when using the map.
ESM · virtual host roots
new Server({
    root:'./www/default',
    domain:'example.test',
    domains:{
        'docs.example.test':'./www/docs',
        'app.example.test':'./www/app'
    }
}).deploy();

Static server behavior

The server object.

KeyDefaultPurpose
index'index.html'File used for directory requests. There is no directory listing when it is absent.
noCachetrueSends no-cache/no-store/must-revalidate directives. false omits them; set cache lifetime headers through a hook or proxy.
allowDotfilesfalseOnly literal true allows dot-prefixed path segments. The default returns 403 before lookup or SPA fallback.
compressionfalseNegotiates Brotli/gzip for accepted compressible static responses through Node's built-in node:zlib; runtime dependencies stay at zero. Ranges and manual serve() responses retain their selected encoding.
compressionThreshold1024Minimum uncompressed bytes before compression is considered.
brotliQuality4Brotli quality from 0 through 11 for automatically compressed static responses through node:zlib.
spaFallbackfalsetrue uses index; a string chooses another root-relative file.
timeout30000HTTP/1 socket or HTTP/2 session inactivity timeout in milliseconds.
requestTimeout300000HTTP/1 whole-request timeout in milliseconds.
headersTimeout60000HTTP/1 request-header timeout in milliseconds.
keepAliveTimeout5000HTTP/1 keep-alive timeout in milliseconds.
maxRequestBodyBytesfalseMaximum request bytes; false/0 is unlimited.
SPA conditions: fallback applies only after an initial 404, for an extensionless path whose request accepts HTML or */*. Missing assets and non-HTML requests remain 404.
Dotfile opt-in: allowDotfiles:true exposes every dot-prefixed segment in the selected root, including /.git, /.env, and /.well-known. Use a dedicated audited root.

Limits and timeouts

Every disable value is explicit.

Settingfalse0Unit
server.timeoutDisabledDisabledmilliseconds
server.requestTimeoutDisabledDisabledmilliseconds
server.headersTimeoutDisabledDisabledmilliseconds
server.keepAliveTimeoutDisabledDisabledmilliseconds
server.maxRequestBodyBytesUnlimitedUnlimitedbytes
contentTypeAutomatic map removedInvalid map value—
Programmatic null: false, null, and numeric 0 disable timeouts and the body cap through the module API. The CLI accepts false/off/0, not null.

requestTimeout, headersTimeout, and keepAliveTimeout apply to HTTP/1 connections, including HTTPS fallback connections. They do not impose HTTP/2 stream deadlines. timeout controls HTTP/2 session inactivity.

Operational choice: disabled values are supported, not recommended as a universal default. Set finite limits for the traffic and proxy chain you actually operate.

File types and restrictions

Serve, reject, or use the binary fallback.

ConfigurationResult
No entry for extensionapplication/octet-stream.
contentType:{md:'text/markdown; charset=utf-8'}Adds or overrides that extension.
contentType:{secret:false}Filenames ending in .secret return 415 after path policy checks.
contentType:falseRemoves automatic mapping; served files use application/octet-stream.
restrictedType:{key:true}Filenames ending in .key return 403 after path policy checks.
JavaScript · MIME and extension controls
new Server({
    contentType:{
        md:'text/markdown; charset=utf-8',
        secret:false
    },
    restrictedType:{
        key:true,
        pem:true
    }
});

Extension keys omit the leading dot. The built-in map is available through Config.mimeTypes or the node-http-server/mime-types package subpath. If an object is merged after contentType:false, the built-in defaults are restored first and then overlaid.

Error responses

Override headers or individual bodies.

KeyDefault / shapeUse
errors.headersContent-Type: text/plain; charset=utf-8, X-Content-Type-Options: nosniffHeaders applied to built-in error responses.
errors[400]'400 Bad Request'Malformed request.
errors[403|404|405]Status textDenied, missing, or unsupported method.
errors[413|415|416|421|500]Status textLimit/type/range/Host/internal failures.
JavaScript · custom error response
new Server({
    errors:{
        headers:{'Content-Type':'application/json'},
        404:'{"error":"not found"}'
    }
});

Logging

Append NDJSON or provide a writer.

KeyDefaultBehavior
logfalseFile path enables one JSON record per request line.
logBodyfalseAdds the UTF-8 request body when deliberately enabled.
logFunctionbuilt-in append writerReceives the record with this bound to Config; may return a Promise.

The built-in writer adds a timestamp without mutating its input and redacts common credential headers. Serialization/filesystem errors are captured. Protect log destinations and treat any stored request body as sensitive.

JavaScript · custom logger
new Server({
    log:true,
    logFunction(data){
        return sendRecordSomewhere(data);
    }
});

Native Node HTTP/2 over HTTPS

Supply key and certificate paths together.

Configured HTTPS defaults to HTTP/2 through node:http2.createSecureServer() with allowHTTP1:true. TLS negotiates HTTP/2 or HTTP/1.1 on the same port before requests begin. Plain HTTP remains HTTP/1.1. Node.js 22.12 or newer remains the runtime requirement, with zero runtime dependencies.

KeyDefaultPurpose
https.ca''Optional CA certificate path.
https.privateKey''Private-key path.
https.certificate''Certificate path.
https.passphrasefalseOptional private-key passphrase.
https.port443HTTPS port.
https.onlyfalseSkip HTTP when HTTPS is configured.
https.http2trueHTTP/2 with HTTP/1.1 negotiation; false selects the original node:https listener.
ESM · HTTPS only
const server=new Server({
    host:'127.0.0.1',
    https:{
        privateKey:'/path/to/private.key',
        certificate:'/path/to/certificate.pem',
        port:8443,
        only:true
    }
});

server.deploy();

server.secureServer is a Node Http2SecureServer by default. Set https.http2:false when the application requires the original https.Server type or HTTP/1-specific native APIs. https.only controls the separate plain HTTP listener, not the negotiated HTTP version. See the hook contract for HTTP/2 request/response compatibility.

Certificates: generate fresh local material and keep private keys out of source control and every served root. Use the HTTPS guide for transport modes, paired listeners, lifecycle, and troubleshooting.

Validation and merging

Invalid configuration fails before serving.

CheckFailure
Non-plain Config objectTypeError.
Non-plain nested mapTypeError naming the key.
__proto__, constructor, or prototypeRejected as unsafe.
Port outside the integer range 0–65535Deployment throws.
Host emptyDeployment throws.
Invalid root/domain root (missing or non-directory)Deployment throws.
Negative timeout/limit/thresholdDeployment throws.
server.brotliQuality outside integer range 0–11Deployment throws.
Only one of HTTPS key/certificate setDeployment throws.
https.only:true without key/certificateDeployment throws.

Merge precedence is defaults, then constructor values, then later deploy()/merge() overlays. Known nested records shallow-overlay and omitted earlier values persist. Instances, Config.defaults, Config.mimeTypes, and user maps maintain independent mutable nested state. Unknown safe top-level keys remain application-owned metadata.