Code Monkey home page Code Monkey logo

http-wrapper's Introduction

Deno HTTP Wrapper

Simple Server/Router wrapper around Deno's HTTP module

Example app using Vite and Deno

Example GitHub repo

Intent

I really like Deno as a concept, and I especially like the default HTTP library. I feel like it doesn't need all the abstraction put on top of it to build something pretty good.

The intent of this library is to build a lightweight wrapper around it that provides a more intuitive API around the listenAndServe() function.

Some of the API is inspired by Express.js.

Install

As with all Deno modules, http_wrapper is imported via URL, and not with a package manager:

import {
  Server,
  Router,
  Socket,
} from "https://deno.land/x/[email protected]/mod.ts";

Example

import {
  Server,
  Router,
  Socket,
} from "https://deno.land/x/[email protected]/mod.ts";

// Create a new route
const router = new Router();

// Add an endpoint to the route
// Deno's default ServerRequest object is used

// This endpoint will be accessible at /
router.get("/", async (req) => {
  // Respond using default methods
  req.respond({
    status: 200,
    headers: new Headers({
      "content-type": "text/html",
    }),
    body: await Deno.open("./index.html"),
  });
});

// Create a second endpoint
const bobRouter = new Router("/bob");

// This endpoint will be accessible at /bob
bobRouter.get("/", (req) => {
  req.respond({
    status: 200,
    headers: new Headers({
      "content-type": "application/json",
    }),
    body: JSON.stringify({
      test: "This is a test",
    }),
  });
});

// Create a web socket route at /ws
const socket = new Socket("/ws");

// Add a message event to listen for
socket.on("message", (msg: Broadcast, connId: string): void => {
  console.log("Received");
  socket.emit("message", `[${connId}]: ${msg.body}`);
});

// Create the server
const app = new Server();

// Add routes to server
app.use(router.routes);
app.use(bobRouter.routes);
app.use(socket.routes);

// Add static assets folder
app.static("static", "/static");

// Start the server
app
  .start({ port: 3000 })
  .then((config) => console.log(`Server running on localhost:${config.port}`));

Use

There are two classes: Server and Router.

Router

Router currently supports seven HTTP methods:

  • GET
  • POST
  • PUT
  • DELETE
  • PATCH
  • OPTIONS
  • HEAD

New routes are created as follows:

const router = new Router();

new Router() accepts a string for its constructor of new route (see example above).

A new endpoint for the given route can be added by using its specific method:

router.get("/", (req) => {
  // Perform actions on request
});

The req object is the standard ServerRequest object native to Deno. It is not modified in any way, and you can interact with it directly. The purpose of this library is to make it easy to work with, not to change the interface.

There are a couple of additional objects: query and param, generated by query and path parameters.

// Example of query parameters
// URL called: http://localhost:8000/?id=17
router.get("/", (req, { query }) => {
  req.respond({ body: query.id });
});

// Example of path parameter
// URL called: http://localhost:8000/user/17
router.get("/user/{userId}", (req, { param }) => {
  req.respond({ body: param.userId });
});

Socket

The Socket class is a wrapper around Router, and is initialized the same way.

// Create a new socket endpoint
const socket = new Socket("/ws");

Internally, web socket connections to this endpoint are handled with Deno's standard library:

  • WebSocket
  • acceptable
  • acceptWebSocket
  • isWebSocketCloseEvent

This class wraps the above functionality, and acts as a router around certain events. Messages are stringified JSON, using the below structure:

type Broadcast = {
  from?: string,
  to?: string,
  event?: string,
  body: any,
};

There is currently no client developed to handle this object, just the server implementation, but it should be simple enough to write one.

Socket events are implemented as follows:

const socket = new Socket("/ws");

socket.on("message", (msg: Broadcast, connId: string): void => {
  console.log("Received");
  socket.emit("message", `[${connId}]: ${msg.body}`);
});

An additional to or from value can be set as a third parameter:

const socket = new Socket("/ws");

socket.on("message", (msg: Broadcast, connId: string): void => {
  console.log("Received");
  socket.emit("message", `[${connId}]: ${msg.body}`, {
    to: anotherUserId,
    from: connId,
  });
});

Server

To add a static file folder (useful for serving HTML/CSS/JS files), use the following:

const app = new Server();

// First attribute is local folder where files are located, second is the route to load the files from
app.static("static", "/static");

When you are ready to apply your routes and start your server, run the following:

const app = new Server();

app.use(router.routes); // router.routes is a getter, so you do not need to invoke it as a function.
app.use(socket.routes); // Sockets are added to the server in the same way as routers.

// Using promises to know when the server is up
app
  .start({ port: 3000 })
  .then((config) => console.log(`Server running on localhost:${config.port}`));

// Using await to know when the server is up
await app.start({ port: 3000 });

console.log("Server running on localhost:3000");

The benefit of using promises is having the config object returned that you passed in, but it isn't important if you don't want to see it.

License

This project is MIT Licensed.

http-wrapper's People

Contributors

cstapetrei avatar lindsaykwardell avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

http-wrapper's Issues

Native HTTP

Will this be updated to deno native http/ws? Native will be stable in 1.13.0
I see this as a very useful library. thanks.

Add support for parsing the body

Add a method to handle parsing the body of a request. This can either be via middleware (like Express) or built-in, such as a check against the header content-type. I prefer the latter, so that parsing does not need to be something the developer thinks about.

router.post("/", (req, { body }) => {
  // Do something with the body
}

Support query/path parameters

Support for query and path parameters. API is still up in the air.

const router = new Router("/user");

router.use("/{userId}", req => {...});

Add support for middleware to routes

Support is required for middleware on routes. One use case is for authentication/authorization.

Potential example API:

Middleware applied to Router class object.

const router = new Router("/api");

router.use((req: ServerRequest): boolean => {
  // Perform middleware action
  // Return true if valid, false if the request should be interrupted.

  return true;
});

Middleware applied when adding routes to Server

const someMiddleware2 = (req: ServerRequest): boolean => {
  return true;
}

const app = new Server();

app.use(router.routes, (req: ServerRequest): boolean => {...}, someMiddleware2);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.