0.3.0 • Published 2 years ago

yymbo v0.3.0

Weekly downloads
2
License
ISC
Repository
-
Last release
2 years ago

Introduction

Yymbo is a simple modular controller based HTTP Server built in TypeScript.

Controllers

Yymbo lets the user set up controllers to handle requests. The controller configuration is set up using decorators:

class MyController {
  @HttpMethod(HttpVerb.GET, "/hello-world")
  public helloWorld(req: Request, res: Response): void {
    res.ok(new TextResponse("Hello, World!"));
  }

  @HttpMethod(HttpVerb.POST, "/hello/:name")
  @Middleware(authMiddleware)
  public helloUser(req: Request, res: Response): void {
    res.ok(new TextResponse(`Hello, ${req.params.name}!`));
  }
}

const controllerServer = new Yymbo();
controllerServer
  .controller(MyController)
  .start({ port: 80 });

Digging into the example above we can see:

  • The server has set up one controller
  • The controller has two endpoints configured via the HttpMethod decorator:
    • GET: /hello-world
    • POST: /hello/{variable}
  • Both of these endpoints return a plain text response with OK status (200)
  • The second endpoint utilises a middleware pipeline called "authMiddleware"
  • The server is running on port 80

Request Body Type-Safety

In this example we can see how Request can take an interface to allow for type safety. This does not stop the user submitting something other than the defined types - and does no checks against the data quality or types - but it does allow intellisense and type-safe coding after your own checks have been performed.

interface ILoginRequest {
    username?: string;
    password?: string;
}

class AuthController {
  @HttpMethod(HttpVerb.POST, "/login")
  public login(req: Request<ILoginRequest>, res: Response): void {
    ... req.body.username is a string | undefined ...
  }
}

Supported web body types currently include:

application/json

URL Parameters

URL Parameters can be added to a path using the :parameter syntax and accessed via Request.params.variableName.

class HelloController {
  @HttpMethod(HttpVerb.GET, "/hello/:name")
  public helloName(req: Request, res: Response): void {
    ... A request to /hello/Tom would make req.params.name equal "Tom" ...
  }
}

Query Parameters

Query Parameters are supported in Yymbo. These can be accessed through the Request.query object:

class HelloController {
  @HttpMethod(HttpVerb.GET, "/hello")
  public helloName(req: Request, res: Response): void {
    ... A request to /hello?name=Tom would make req.query.name equal "Tom" ...
  }
}

Middleware

There are two ways to set up Middlware in Yymbo: Globally or Per Handler. Global Middleware will be utilised for all handlers registered against the server on all controllers. Per Handler Middleware will be utilised for the one handler with the @Middleware decorator. There is nothing to prevent the use of the same middleware in two decorators. Multiple Per Handler middleware can also be declared against one Handler.

Middleware can also respond to requests - if a response is issued by the middleware then the handler method will not be called.

The different options are shown here:

class MyController {
  @HttpMethod(HttpVerb.GET, "/hello-world")
  @Middleware(authMiddleware)
  public helloWorld(req: Request, res: Response): void {
    res.ok(new TextResponse("Hello, World!"));
  }

  @HttpMethod(HttpVerb.GET, "/hello-teapot")
  @Middleware(authMiddleware)
  @Middleware(validateRequestMiddleware)
  public helloTeapot(req: Request, res: Response): void {
    res.ok(new TextResponse("Hello, Teapot!"));
  }
}

const controllerServer = new Yymbo();
controllerServer
  .controller(MyController)
  .globalMiddleware(logRequestsMiddleware)
  .start({ port: 80 });

Middleware is of type IMiddleware and must implement a completeTask method. An example is shown here:

const logRequestsMiddleware = {
  completeTask(req: Request, res: Response): void {
    console.log("A request was made!");
  },
} as IMiddleware;

Response Headers

Response headers can be added globally as an optional parameter on start, or can be added individually inside handlers. Headers set on individual handlers can be set via a function on the response (to be used conditionally) or via a decorator. All three examples are shown here.

class MakeTeaController {
  @HttpMethod(HttpVerb.POST, "/make-tea")
  public makeTea(req: Request, res: Response): void {
      res.setHeader('Cache-Control', 'no-cache');
    ...
  }

  @HttpMethod(HttpVerb.POST, "/make-coffee")
  @Headers([
    ["Cache-Control", "no-cache"],
  ])
  public makeCoffee(req: Request, res: Response): void {
      res.setHeader('Cache-Control', 'no-cache');
    ...
  }
}

const controllerServer = new Yymbo();
controllerServer
  .controller(MakeTeaController)
  .start({ 
    port: 80,
    headers: [
      ['Access-Control-Allow-Origin', '*']
    ]
  });

Preflight Headers

Preflight Headers can be controlled with the PreflightHeaders Decorator. This is to be added as a decorate to the normal controller function.

class MakeTeaController {
  @HttpMethod(HttpVerb.POST, "/make-tea")
  @PreflightHeaders([
    ["custom-header", "custom-value"],
  ])
  public makeTea(req: Request, res: Response): void {
      res.setHeader('Cache-Control', 'no-cache');
    ...
  }
}
0.3.0

2 years ago

0.2.1

2 years ago

0.2.0

2 years ago

0.1.15

2 years ago

0.1.14

2 years ago

0.1.13

2 years ago

0.1.12

2 years ago

0.1.11

2 years ago

0.1.10

2 years ago

0.1.9

2 years ago

0.1.8

2 years ago

0.1.7

2 years ago

0.1.6

2 years ago

0.1.5

2 years ago

0.1.4

2 years ago

0.1.3

2 years ago

0.1.2

2 years ago

0.1.1

2 years ago

0.1.0

2 years ago