http

HTTP handling framework

Import

_ <- fat.http

Route

A route is a structure used to map HTTP methods to certain path patterns, specifying what code should be executed when a request comes in. Each route can define a different behavior for each HTTP method (POST, GET, PUT, DELETE).

Constructor

Name Signature Brief
Route (path: Text, post: Method, get: Method, put: Method, delete: Method) Constructs a Route object

each implemented method receives an HttpRequest as argument and shall return an HttpResponse object

HttpRequest

An HttpRequest represents an HTTP request message. This is what your server receives from a client when it makes a request to your server.

Constructor

Name Signature Brief
HttpRequest (method: Text, path: Text, headers: List, params: Scope, body: Any) Constructs an HttpRequest object

the items params and body may be omitted depending on the request received

HttpResponse

An HttpResponse represents an HTTP response message. This is what a server sends back to the client in response to an HTTP request.

Constructor

Name Signature Brief
HttpResponse (status: Number, headers: List/Text, body: Any) Constructs an HttpResponse object

for client mode responses, body will be provided as Text if a textual MIME type can be found in the headers, otherwise it will be provided as Chunk

Methods

Name Signature Brief
setHeaders (headers: List): Void Set headers of requests
post (url: Text, body, wait): HttpResponse Create/post body to url
get (url: Text, wait): HttpResponse Read/get from url
put (url: Text, body, wait): HttpResponse Update/put body to url
delete (url: Text, wait): HttpResponse Delete on url
setName (name: Text): Void Set user agent/server name
verifySSL (enabled: Boolean): Void SSL configuration (client mode)
setSSL (certPath: Text, keyPath: Text): Void SSL configuration (server mode)
listen (port: Number, routes: List/Route, maxMs) Endpoint provider (server mode)

body: Any and wait: Number are always optional parameters, being that if body does not fall under Text or Chunk, it will be automatically converted to JSON during the send process, and wait is the maximum waiting time and the default is 30,000ms (30 seconds)

verifySSL is enabled by default for the client mode

setSSL may not be available, case the system doesn't have OpenSSL

Usage Notes

Client mode

In the HttpResponse.body, you may need to explicitly parse a JSON response to Scope using the fromJSON method. To post a native type as JSON, you can encode it using the toJSON method; however, this is not strictly necessary, as it will be done implicitly. Both methods are available in the fat.recode library.

If headers are not set, the default Content-Type header for Chunk will be application/octet-stream, for Text will be text/plain; charset=UTF-8 and for other types, it will be application/json; charset=UTF-8 (due to implicit conversion).

You can set custom request headers like so:

http <- fat.http

url = ...
token = ...
body = ...

http.setHeaders([
  "Accept: application/json; charset=UTF-8"
  "Content-Type: application/json; charset=UTF-8"
  "Authorization: Bearer " + token  # custom header
])

http.post(url, body)

setting headers will completely replace previous list with new list

When performing async requests, you may need to call setHeaders, setName, and configure verifySSL within each Worker, as these settings are local to each thread.

Server mode

Handling HTTP Responses

You can define the maxMs optional parameter, when calling listen to restrict how long the server will wait for each request to transfer its contents (inbound connection), returning status 408 if exceeded.

The FatScript server automatically handles common HTTP status codes such as 200, 400, 404, 405, 408, 500, and 501. Being 200 the default when constructing an HttpResponse object.

In addition to the common status codes, you can also explicitly return other status codes, such as 201, 202, 203, 204, 205, 301, 401, and 403, by specifying the status code in the HttpResponse object, for example: HttpResponse(status = 401). For all codes mentioned here, the server provides default plain text bodies. However, you have the option to override these defaults and provide your own custom response bodies when necessary.

By automatically handling these status codes and providing default response bodies, the FatScript server simplifies the development process while still allowing you to have control over the response content when needed.

if the status code doesn't belong to any of the above, the server will return a 500 code

See an example of a simple file HTTP server:

_ <- fat.std

# adapt to content location
basePath = '/home/user/contentFolder'

# restrict to some extensions only
mediaTypesByExtension = {
  htm = html = 'text/html'
  js = 'application/javascript'
  json = 'application/json'
  css = 'text/css'
  md = 'text/markdown'
  xml = 'application/xml'
  csv = 'text/csv'
  txt = 'text/plain'
  svg = 'image/svg+xml'
  rss = 'application/rss+xml'
  atom = 'application/atom+xml'
  png = 'image/png'
  jpg = jpeg = 'image/jpeg'
  gif = 'image/gif'
  ico = 'image/x-icon'
  webp = 'image/webp'
  woff = 'font/woff'
  woff2 = 'font/woff2'
}

routes: List/Route = [
  Route(
    '*'
    get = (request: HttpRequest): HttpResponse -> {
      path = basePath + request.path
      type = mediaTypesByExtension(path.split('.')(-1))

      type.isEmpty      => HttpResponse(status = 403)  # forbidden
      file.exists(path) => HttpResponse(
        status = 200
        headers = [ 'Content-Type: {type}' ]
        body = file.readBin(path)
      )
      _                 => HttpResponse(status = 404)  # not found
    }
  )
]

http.listen(8080, routes)

in a real application, request.path must be sanitized before being used to access files on the server; here, it is used directly only as an example

use http.listen(0, routes) to start a server with an auto-assigned port number, and check the actual port assigned to the server through the $port embedded command

results matching ""

    No results matching ""