Puro REST Framework
  • Getting started
  • Architecture and Protocol
  • Entities
  • Controllers
  • Plugins
Powered by GitBook
On this page
  • Introduction
  • Defining a controller
  • Defining a schema
  • HTTP exceptions

Was this helpful?

Controllers

PreviousEntitiesNextPlugins

Last updated 6 years ago

Was this helpful?

Introduction

The controller's purpose is to handle a set of requests related to the same resource.

The class supports four different methods, called "handlers", to implement the basic on the resource:

Controller Method

HTTP Method

HTTP Status Code

create

POST

201

read

GET

200

update

UPDATE

204

remove

DELETE

204

The CRUD function delete has been mapped with the method remove in order to prevent conflicts with the reserved keyword "delete" in JavaScript/TypeScript.

The controller handler receives the request instance and returns a response content. Unless otherwise specified, the framework automatically sets the most appropriate for the request.

Defining a controller

All the the controllers in a Puro application should be stored in the directory "controllers/".

The following example shows the simplest controller you can create:

controllers/HelloController.ts
import { Controller, Request } from '@puro/core';

export class HelloController extends Controller {
  async read(request: Request) {
    return 'Hello World';
  }
}

It only handles GET requests to a resource and returns the string "Hello world" as response content.

curl -X GET http://127.0.0.1:8080/api/hello
{
  "status": 200,
  "content": "Hello World"
}
curl -X DELETE http://127.0.0.1:8080/api/hello
{
  "status": 405,
  "content": "Method Not Allowed"
}

Defining a schema

A very interesting feature of Puro REST Framework is the built-in request validation. To achieve this result you need to define a "schema" for the controller handler that you want to validate.

controllers/BookController.schema.ts
import { Book } from '../entities/Book';

export const updateSchema = {
  bookId: {
    isEntityId: { type: Book, name: 'book' }
  },
  title: {
    isNotEmpty: true,
    isLength: { min: 3, max: 128 }
  },
  description: {
    isLength: { min: 0, max: 256 }
  }
};

The schema is a dictionary where the key is the name of the parameter that we want to validate and the value is an object containing the constraints we want to apply to that specific parameter.

The parameters are searched in the URL parameters, the request body, and the URL query string, in that order.

isAfter, isAlpha, isAlphanumeric, isAscii, isBase64, isBefore, isBoolean, isByteLength, isCreditCard, isCurrency, isDecimal, isEmail, isEntityId, isFQDN, isFloat, isHash, isHexadecimal, isIP, isIPRange, isISO8601, isNotEmpty, isRFC3339, isISO31661Alpha2, isISO31661Alpha3, isIn, isInt, isJSON, isJWT, isLatLong, isLength, isLowercase, isMACAddress, isMimeType, isMobilePhone, isNumeric, isPort, isPostalCode, isURL, isUUID, isUppercase, and isWhitelisted.

controllers/BookController.ts
import { Controller, Schema, Request } from '@puro/core';

import { updateSchema } from './BookController.schema';

export class BookController extends Controller {
  @Schema(updateSchema)
  async update(request: Request) {
    const { book } = request.entities;
    const { title, description } = request.bucket;

    book.title = title;
    book.description = description;
    book.save();

    return 'The book has been updated.';
  }
}

HTTP exceptions

TODO

Exception Class

HTTP Status Code

HTTP Response Message

HttpException

-

-

BadRequestHttpException

400

"Bad Request"

AccessDeniedHttpException

403

"Forbidden"

NotFoundHttpException

404

"Not Found"

MethodNotAllowedHttpException

405

"Method Not Allowed"

InvalidParameterHttpException

422

"Invalid Parameter"

For example, assuming we have a for the resource /api/books/{:bookId}, we could define a schema for the controller handler update as the following:

Puro REST Framework uses to support the following constraints:

Controller
CRUD operations
HTTP Status Code
BookController
validator.js