All Projects → negasus → Traefik2 Luascript

negasus / Traefik2 Luascript

LuaScript middleware for Traefik v2

Programming Languages

go
31211 projects - #10 most used programming language
lua
6591 projects

Projects that are alternatives of or similar to Traefik2 Luascript

Echo Logrus
echo-logrus is a middleware that provides logrus logger support for echo.
Stars: ✭ 27 (-38.64%)
Mutual labels:  middleware
Copper
Copper is a set of Go packages that help you build backend APIs quickly and with less boilerplate.
Stars: ✭ 35 (-20.45%)
Mutual labels:  middleware
Asp.net Core Graphql Middleware
ASP.Net Core GraphQL Middleware
Stars: ✭ 38 (-13.64%)
Mutual labels:  middleware
Whoops
PSR-15 middleware to use Whoops as error handler
Stars: ✭ 29 (-34.09%)
Mutual labels:  middleware
Altair
Lightweight and Robust API Gateway written in Go
Stars: ✭ 34 (-22.73%)
Mutual labels:  middleware
Nex
Aiming to simplify the construction of JSON API service
Stars: ✭ 35 (-20.45%)
Mutual labels:  middleware
Go Bootstrap
Easy way to bootstrap a web server in Go (Routing|Middleware|Https)
Stars: ✭ 27 (-38.64%)
Mutual labels:  middleware
Wretch Middlewares
Collection of middlewares for the Wretch library. 🎁
Stars: ✭ 42 (-4.55%)
Mutual labels:  middleware
Sos
Sandia OpenSHMEM is an implementation of the OpenSHMEM specification over multiple Networking APIs, including Portals 4, the Open Fabric Interface (OFI), and UCX. Please click on the Wiki tab for help with building and using SOS.
Stars: ✭ 34 (-22.73%)
Mutual labels:  middleware
Webpack Isomorphic Dev Middleware
The webpack-dev-middleware, but for isomorphic applications
Stars: ✭ 38 (-13.64%)
Mutual labels:  middleware
Micro Xrce Dds Client
Micro XRCE-DDS Client repository
Stars: ✭ 30 (-31.82%)
Mutual labels:  middleware
Graphql Upload
Middleware and an Upload scalar to add support for GraphQL multipart requests (file uploads via queries and mutations) to various GoLang GraphQL servers
Stars: ✭ 32 (-27.27%)
Mutual labels:  middleware
Redux Json Router
Declarative, Redux-first routing for React/Redux browser applications.
Stars: ✭ 37 (-15.91%)
Mutual labels:  middleware
Adroit
ADR/PSR-7 middleware
Stars: ✭ 28 (-36.36%)
Mutual labels:  middleware
Connect Gzip Static
connect middleware for statically compressed files
Stars: ✭ 39 (-11.36%)
Mutual labels:  middleware
Blog App Buffalo
A blogging app built with Buffalo.
Stars: ✭ 27 (-38.64%)
Mutual labels:  middleware
Htmlcache
Laravel middleware to cache the rendered html
Stars: ✭ 35 (-20.45%)
Mutual labels:  middleware
Codeigniter Middleware
Simplest yet powerful middleware library for codeigniter, can be used to make routes login only, apply roles and permission system, modify, intercept or preprocess requests.
Stars: ✭ 43 (-2.27%)
Mutual labels:  middleware
Znetcs.aspnetcore.authentication.basic
A simple basic authentication middleware.
Stars: ✭ 40 (-9.09%)
Mutual labels:  middleware
Slim Cli
A Slim 3 middleware enabling a mock HTTP request to be made through the CLI.
Stars: ✭ 37 (-15.91%)
Mutual labels:  middleware

Traefik2 LuaScript

LuaScript is middleware for Traefik v2 for execute lua script with access to API

Under cover used LUA VM from Yusuke Inuzuka

An issue

Post on the community portal

About

This middleware allows you to write your business logic in LUA script

  • get an incoming request
  • add/modify request headers
  • add/modify response headers
  • interrupt the request
  • make HTTP calls to foreign services
  • write to traefik log

Usage example

-- middleware_example.lua

local traefik = require('traefik')
local log = require('log')

local h, err = traefik.getRequestHeader('X-Some-Header')
if err ~= nil then
  log.warn('error get header ' .. err)
  return
end

if h == '' then
    traefik.interrupt(401, 'HTTP Header empty or not exists')
    return
end

traefik.setRequestHeader('Authorized', 'SUCCESS')

log.info('continue')

Functions may return an error as a last variable. It is a string with an error message or nil, if no error

Benchmark

See into benchmark folder in this repo

Backend is a simple go application

package main

import (
	"log"
	"net/http"
)

var ok = []byte("ok")

func handler(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(200)
	w.Write(ok)
}

func main() {
	http.HandleFunc("/", handler)
	log.Printf("listen 2000")
	http.ListenAndServe("127.0.0.1:2000", nil)
}

Run load testing with vegeta

echo "GET http://localhost/" | vegeta attack -rate 2000 -duration=60s | tee results.bin | vegeta report

With LUA

A Traefik config

http:
  routers:
    router1:
      rule: "Host(`localhost`)"
      service: service1
      middlewares:
        - example

  middlewares:
    example:
      luascript:
        script: middleware.lua

  services:
    service1:
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:2000"

A Lua script

local traefik = require('traefik')

traefik.setRequestHeader('X-Header', 'Example')
traefik.setResponseHeader('X-Header', 'Example')

A Result

Requests      [total, rate, throughput]  120000, 2000.02, 2000.00
Duration      [total, attack, wait]      59.999868062s, 59.999484357s, 383.705µs
Latencies     [mean, 50, 95, 99, max]    471.058µs, 365.053µs, 993.75µs, 1.26782ms, 18.771475ms
Bytes In      [total, mean]              240000, 2.00
Bytes Out     [total, mean]              0, 0.00
Success       [ratio]                    100.00%
Status Codes  [code:count]               200:120000
Error Set:

Without LUA

A Traefik config

http:
  routers:
    router1:
      rule: "Host(`localhost`)"
      service: service1

  services:
    service1:
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:2000"

A Result

Requests      [total, rate, throughput]  120000, 2000.02, 2000.01
Duration      [total, attack, wait]      59.999708481s, 59.999466875s, 241.606µs
Latencies     [mean, 50, 95, 99, max]    257.527µs, 227.055µs, 339.606µs, 520.189µs, 28.70824ms
Bytes In      [total, mean]              240000, 2.00
Bytes Out     [total, mean]              0, 0.00
Success       [ratio]                    100.00%
Status Codes  [code:count]               200:120000
Error Set:

Installation from sources and run

Download the Traefik sources and go to the directory

git clone https://github.com/containous/traefik
cd traefik

Add this repo as a submodule

git submodule add https://github.com/negasus/traefik2-luascript pkg/middlewares/luascript

Add the code for the middleware config to the file pkg/config/dynamic/middleware.go

type Middleware struct {
  // ...
	LuaScript         *LuaScript         `json:"luascript,omitempty" toml:"luascript,omitempty" yaml:"luascript,omitempty"`
  // ...
}

// ...

// +k8s:deepcopy-gen=true

// LuaScript config
type LuaScript struct {
	Script string `json:"script,omitempty" toml:"script,omitempty" yaml:"script,omitempty"`
}

Add the code for register a middleware to the file pkg/server/middleware/middlewares.go

import (
  // ...
	"github.com/containous/traefik/v2/pkg/middlewares/luascript"  
  // ...
)

// ...

func (b *Builder) buildConstructor(ctx context.Context, middlewareName string, config config.Middleware) (alice.Constructor, error) {
  // ...
  
  // BEGIN LUASCRIPT BLOCK
	if config.LuaScript != nil {
		if middleware == nil {
			middleware = func(next http.Handler) (http.Handler, error) {
				return luascript.New(ctx, next, *config.LuaScript, middlewareName)
			}
		} else {
			return nil, badConf
		}
	}
  // END LUASCRIPT BLOCK
  
	if middleware == nil {
		return nil, fmt.Errorf("invalid middleware %q configuration: invalid middleware type or middleware does not exist", middlewareName)
	}

	return tracing.Wrap(ctx, middleware), nil
}

Build the Traefik

go generate
go build -o ./traefik ./cmd/traefik

Create a config file config.yml

log:
  level: warn

providers:
  file:
    filename: "/path/to/providers.yml"

and providers.yml

http:
  routers:
    router1:
      rule: "Host(`localhost`)"
      service: service1
      middlewares:
        - example

  middlewares:
    example:
      luascript:
        script: /path/to/example.lua

  services:
    service1:
      loadBalancer:
        servers:
          - url: "https://api.github.com/users/octocat/orgs"

Create a lua script example.lua

local traefik = require('traefik')
local log = require('log')

log.warn('Hello from LUA script')
traefik.setResponseHeader('X-New-Response-Header', 'Woohoo')

Run the traefik

./traefik --configFile=config.yml

Call the traefik (from another terminal)

curl -v http://localhost

And, as result, we see a traefik log

WARN[...] Hello from LUA script 	middlewareName=file.example-luascript middlewareType=LuaScript

A response from the github API with our header

...
< X-New-Response-Header: Woohoo
...

Done!

API

Traefik

Traefik module allows get information about current request. Add request/response headers, or interrupt the request.

Usage:

traefik = require('traefik')

Get Request Header

getRequestHeader(name string) value string, error

If header not exists, returns no error and empty string value!

local traefik = require('traefik')
local log = require('log')

local h, err = traefik.getRequestHeader('X-Authorization')
if err ~= nil then
  log.debug('error get header' .. err)
end

Set Request Header

setRequestHeader(name string, value string) error

Set header for pass to backend

err = traefik.setRequestHeader('X-Authorization', 'SomeSecretToken')

Set Response Header

setResponseHeader(name string, value string) error

Set header for return to client

err = traefik.setResponseHeader('X-Authorization', 'SomeSecretToken')

** Interrupt the request and return StatusCode and Body

interrupt(code int, [message string]) error

err = traefik.interrupt(403)

-- or

err = traefik.interrupt(422, 'Validation Error')

Get Request Query Argument

getQueryArg(name string) value string, error

Get value from query args

-- Get 'foo' for URL http://example.com/?token=foo
v, err = traefik.getQueryArg('token')

Get Request

getRequest() value table

Get request info

info = traefik.getRequest()

{
    method = 'GET',
    uri = '...',
    host = '...',
    remoteAddr = '...',
    referer = '...',
    headers = {
        key = 'value',
        ...
    }
}

LOG

Send a message to a traefik logger

error(message string)

warn(message string)

info(message string)

debug(message string)

local log = require('log')

log.error('an error occured')
log.debug('header ' .. h .. ' not exist')

HTTP

Set HTTP requests to remote services

Usage:

http = request('http')

request

request( table) response[, error string]

Send a request

OPTIONS is a table with request options

{
    method = 'POST',    -- http method. By default: GET
    url     = '',       -- URL
    body    = '',       -- request body. By default: empty
    timeout = 100,      -- timeout in milliseconds. By default: 250 (ms)
    headers = {         -- request heders
        key = 'value',
        ...
    }
}

RESPONSE

{
    status  = 200,      -- response status code
    body    = '',       -- response body
    headers = {         -- response headers
        key = value,
        ...
    }
}

get, post, put, delete

get('url', [OPTIONS]) response[, error string]

post('url', [OPTIONS]) response[, error string]

put('url', [OPTIONS]) response[, error string]

delete('url', [OPTIONS]) response[, error string]

Aliases for request with predefined Method and URL

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].