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

hannahttp

v1.2.3

Published

HannaHTTP is a work-in-progress simple express.js alternative. Up to this point, it's already better than express.js due to the internal usage of promises, so no callback hell, and also less-hacky methods of transforming the response body. Further it auto

Downloads

8

Readme

HannaHTTP

HannaHTTP is a work-in-progress simple express.js alternative. Up to this point, it's already better than express.js due to the internal usage of promises, so no callback hell, and also less-hacky methods of transforming the response body. Further it automatically picks the proper transfer encoding, to speed up the process, and prevent the server from having too large buffers. With this I mean, that if it detects transform streams or an unknown size, it will automatically write the response chunked.

Also one thing that sets this apart from express, is the way requests are handled. In express the parameters are stored in the request object, which obviously doesn't make any sense, because a request can match multiple pieces of middleware, of which each has different patterns and other paramteres, which is why there is a separate match object given to each piece of middleware, containing the paramters and remainder of the match. With remainder I mean the remaining part of the URI when the user has used the * wildcard at the end of the matching path.

Dependencies

  1. consolidate

Features

  1. Full-Blown HTTP Router with pattern matching.
  2. Async API.
  3. Automatic LetsEncrypt certificates using CertBot.
  4. Virtual Hosting.
  5. Static File Serving.
  6. Customizable Full-Response Caching.
  7. Customizable Adaptive Compression.
  8. Body Parsers.

Built-In Middleware

The library contains many pieces of middleware that will supply the user (you) with all the built in funcionality you could desire. This prevents you from having to install crappy external libraries (which express.js usually requires you to do).

  1. Compression (Compresses the response with either: Deflate, GZIP or Brotli).
  2. Body Reader (Reads the request body based on the Content-Length).
  3. Body JSON Parser (Parses the read request body to json).
  4. Body X-WWW-FORM-URIENCODED Parser (Parses form data from the read request body).
  5. Cache (Caches complete responses for a given amount of time).
  6. Static File Serving (Serves static files in the given directory).
  7. LetsEncrypt Certbot (Generates and maintains letsencrypt certificates).
  8. Virtual Hosting (Calls different routers based on the requested host).

Example

const {
  useBodyReader,
  HTTPServerPlain,
  HTTPSimpleRouter,
  HTTPSettings,
  useJsonBodyParser,
  useCompression,
  HTTPSessionLogLevel,
  useStatic,
} = require("hannahttp");
const path = require("path");

// Creates the router and the settings.
const router = new HTTPSimpleRouter();
const settings = new HTTPSettings();

// By changing the log level in the settings, we can see what happens
//  in the request (trace shows all details).
settings.sessionLogLevel = HTTPSessionLogLevel.Trace;

// The request body is not read by default (since the headers aren't handled yet).
//  so in order to read the request body, this piece of middleware needs to be called.
router.use(useBodyReader());

// Now in order to actually decode the json body, we need to call this middleware.
//  this middleware parses the json body, and stores it in req.u.body;
router.use(useJsonBodyParser());

// Now to compress text-based responses, we can use the compress middleware
//  which will either use GZIP or Deflate depending on the Accept-Encoding
//  and the server configuration (as bellow). The match regex can be adjuested
//  to determine which files will be compressed (since we don't want blobs to be
//  compressed as this is too expensive).
router.use(
  useCompression({
    match: /(\.html|\.txt|\.css|\.js)$/,
    useGzip: true,
    useDeflate: true,
  })
);

// Simple example of a nested router. A nested router can be
//  used to speed up request handing since less regular expressions
//  need to be matched, again use a all match (*) so the remainder
//  can be used by the nested router.
const nestedRouter = new HTTPSimpleRouter();

nestedRouter.get('/example', async (match, req, res) => {
  await res.text('Yes! It works...');

  // Returning false will prevent the next piece of middelware
  //  from being called, returning true will call the next one.
  return false;
});

router.get('/nested/*', nestedRouter);

// Here we serve static files in the given directory (in our case 'static').
//  remember that we need to define an all match (*) so that the middleware
//  will get the remainder, and use that as a file path.
router.get("/static/*", useStatic(path.join(__dirname, "static")));

// Example of simple response.
router.get("/", async (match, req, res) => {
  await res.text("Hello world!");
  return false;
});

// Example showing parameters (starting with :) and the all match (at the end of uri with *).
//  the match object will contain the parameters, and the remainder (the matched part by *).
router.get("/:param1/:param2/:param3/*", async (match, req, res) => {
  await res.json({
    match,
  });

  return false;
});

// Here an all match is used to send a 404 page.
router.any("/*", async (match, req, res) => {
  await res.text(`Page '${match.remainder}' not found!`, 404);
  
  return false;
});

// Creates the server and starts listening.
const server = new HTTPServerPlain(8080, "0.0.0.0", 100, router, settings);
server.start();