npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

grel-reverse-proxy

v1.0.10

Published

GREL Reverse Proxy Server

Downloads

7

Readme

grel-reverse-proxy

Reverse Proxy Server

Setup an HTTPS reverse proxy server on your desktop to expose static and dynamic sites. Requires SSL certificates. No Code, just config!

I was frustrated with the available options, and didn't want to use NGINX locally. I wanted one that was node based, but used a config file, and allowed me to customize. This is the result. It's been working on my desktop (with 10 domains) since 2019.

Use Cases

  • You want to provide HTTPS access to local server ports without having to expose the ports.
  • You have one or more domain names to use:
    • Some are dynamic, and have their own servers (on different ports).
    • Some are simply static sites, which just need to server files (no need for separate projects)
  • You also have various static content that you want to serve using different virtual paths.
  • You want to be able to control access to some sites based on ip addresses
    • You want to allow certain paths regardless of access control (e.g., domain ownership checks)

Installing

NPM

npm install "grel-reverse-proxy"

GitHub

git clone "https://github.com/grumpygary/grel-reverse-proxy"

Usage

Simple Config

// proxy-config.js
// For more examples, see 'sample-config.js' below and in module source
module.exports = {
    certRoot: "~/my-certs",
    staticRoot: "~/static-www-sites", // referenced by "$" below
    domains: {
        "sub.mydomain.com": {
            staticFolder: "$/sub-domain",
            home: "/index.html", // from root of static folder
        },
  },
}

Running the Server

const revProxyServer = require('grel-reverse-proxy');
let configOptions; // if undefined, will use "proxy-config.js" in cwd
revProxyServer(configOptions); // run server --  see below

Configuration Options

Under construction. See sample-config.js for context.

Global options
------------------------|----------|-------------|-------------------------------------------------
name                    | type     | default     | description
------------------------|----------|-------------|-------------------------------------------------
verbose                 | bool     | false       | log config msgs during startup
staticHeaders           | object   |             | applied to every response (Content-Security-Policy: true or string -- if includes {{sites}} can customize by domain)
certRoot                | string   |             | REQUIRED. Where to find domins certs (names domain folders with .crt .ey and .ca_bundle files)
staticRoot              | string   |             | If using static folders, the folder where static folders are placed (when using "$" & "~")
staticPorts             | number   | 8100        | first port for static sites
port                    | number   | 443         | 
requestIpExpiresSeconds | number   | 30          | Don't log ip addr after this timeout
domains                 | object   |             | domain targets { "domain.com": {}, ... }
allowedIpAddressed      | object   |             | { "::ffff:xxx.xxx": "name" ...} , match beginning of string
allowedUrlPaths         | array    |             | if request url's beginning matches any of these, allow regardless of permissions (useful for domain name ownership files)
pages                   | object   |             | { "statusNNN": htmlBodyForPage, ..., "denied": "access denied" }
------------------------|----------|-------------|-------------------------------------------------
Domain specific options
------------------------|----------|-------------|-------------------------------------------------
root                    | string   |             | root folder of domain: $=staticRoot
staticFolders           | array    |             | specific sites based on url path
staticFolder            | string   |             | site specific root ($ = staticRoot, ~ = user)
redirects               | object   |             | { "request-url": "mapped-url" }
proxyControl            | object   |             | { pset: true } allows remote set,reload (careful!)
port                    | number   |             | localhost port
target                  | string   |             | url of server (using "port" = "https://localhost:port )
permissions             | object   |             | see permissions
errors                  | object   |             | { denied: "string if ppermission denied" } (more to come)
cspSites                | string   |             | if {{sites}} is in the CSP, replce with these

Permissions

------------------------|----------|-------------|-------------------------------------------
safe                    | bool     | true        | when false, enforce permissions
allowedIpAddressed      | object   |             | site version of global option

Sample-Config.js

Some configuration samples.

const allowedIpAddresses = {
    // subnets
    "::ffff:192.168.1.": "~Local-LAN",
    "::ffff:17.": "Apple",
};
const allowedUrlPaths = [
    ".well-known/pki-validation",
];

module.exports = {
    verbose: true,  // useful for debugging config
    certRoot: "", // each domain in names folder; include: domain.crt, domain.key, domain.ca_bundle (rename it)
    staticRoot: "",
    staticPorts: 8100,  // internal: auto-assign base
    port: 443,          // exposed externally
    allowedIpAddresses,
    allowedUrlPaths,
    requestIpExpiresSeconds: 30, // seconds
    staticHeaders: {
        "Content-Security-Policy": true, // use default (pass your own object to override)
    },
    domains: {
        // domains redirecting to other servers
        "domain.com": {
            root: "$", // staticRoot
            staticFolders: [
                { url0: "/urlPart", folder: "$/localFolder", index: "index.html", },
                { url0: "/files", folder: "$/downloads" },
                { url0: "/", folder: "$/local2", index: "index.html", },
            ],
            proxyControl: {
                pset: false, // when true, will use pset to manage proxy remotely (careful!)
            },
        },
        "anotherdomain.com": {
            staticFolder: "~/site1/dist-web", // static off staticRoot
            redirects: {
                "/": "/index.html", // redirect / to /index.html
            },
        },
        "sub2.domain.com": {
            target: "http://localhost:8888", // dynamic (include "://")
            permissions: {
                safe: false,
                allowedIpAddresses: Object.assign({},allowedIpAddresses,{
                }),
            },
            errors: {
                denied: "IP address not allowed.",
            }
        },
        "sub3.domain.com": {
            port: 8897,
            target: "http://localhost:8897",
            home: "/p/index.html", // same as redirects: { "/": "/newPath" }
        },
        "sub4.domain.com": 8877, // will use "http://localhost:8877"
  },
    pages: {
        status404: `
<div style="background-color:blue;color:white;padding:5px;width:500px;">
    <div style="border:1px solid #ffff00;padding:10px;">
    404 - Can't fetch this!
    <br/>
    {{URL}}
    </div>
</div>`,
        denied: ``,
    },
}```