expand_more

vinxi is a hackable, composable, middleware-oriented web proxy toolkit written in Go.

vinxi was designed to build extensible and versatile web proxy solutions for a variety of purposes.

vinxi core is lightweight and relies on a component-based architecture. It provides a generic set of built-in production-oriented components that are ready to plug in and use.

Still beta under active development.

Features

Installation

go get -u gopkg.in/vinxi/vinxi.v0

Components

Examples

Simple forward proxy

Forwards all the traffic to a specific host.

package main

import (
  "fmt"
  "gopkg.in/vinxi/vinxi.v0"
)

func main() {
  vs := vinxi.NewServer(vinxi.ServerOptions{Port: 3100})

  // Forward all the traffic to httpbin.org
  vs.Forward("http://httpbin.org")

  fmt.Printf("Server listening on port: %d\n", 3100)
  err := vs.Listen()
  if err != nil {
    fmt.Errorf("Error: %s\n", err)
  }
}

Multiplexer composition

Uses the built-in multiplexer for traffic handling composition.

package main

import (
  "fmt"
  "net/http"

  "gopkg.in/vinxi/forward.v0"
  "gopkg.in/vinxi/mux.v0"
  "gopkg.in/vinxi/router.v0"
  "gopkg.in/vinxi/vinxi.v0"
)

func main() {
  fmt.Printf("Server listening on port: %d\n", 3100)
  vs := vinxi.NewServer(vinxi.ServerOptions{Host: "localhost", Port: 3100})

  m := mux.New()
  m.If(mux.MatchHost("localhost:3100"))

  m.Use(func(w http.ResponseWriter, r *http.Request, h http.Handler) {
    w.Header().Set("Server", "vinxi")
    h.ServeHTTP(w, r)
  })

  m.Use(router.NewRoute("/foo").Handler(func(w http.ResponseWriter, req *http.Request) {
    w.Write([]byte("foo bar"))
  }))

  m.Use(forward.To("http://127.0.0.1:8080"))

  vs.Vinci.Use(m)
  vs.Vinci.Forward("http://127.0.0.1")

  err := vs.Listen()
  if err != nil {
    fmt.Errorf("Error: %s\n", err)
  }
}

Simple traffic routing

Uses the built-in router for handle and forward traffic.

package main

import (
  "fmt"
  "net/http"
  "gopkg.in/vinxi/vinxi.v0"
)

func main() {
  vs := vinxi.NewServer(vinxi.ServerOptions{Host: "localhost", Port: 3100})
  v := vs.Vinxi

  v.Use(func(w http.ResponseWriter, r *http.Request, h http.Handler) {
    w.Header().Set("Server", "vinxi")
    h.ServeHTTP(w, r)
  })

  v.UsePhase("error", func(w http.ResponseWriter, r *http.Request, h http.Handler) {
    w.Header().Set("Server", "vinxi")
    w.WriteHeader(500)
    w.Write([]byte("server error"))
  })

  v.Get("/ip").Forward("http://httpbin.org")
  v.Get("/headers").Forward("http://httpbin.org")
  v.Get("/image/:name").Forward("http://httpbin.org")
  v.All("/post").Forward("http://httpbin.org")

  v.Forward("http://example.com")

  fmt.Printf("Server listening on port: %d\n", 3100)
  err := vs.Listen()
  if err != nil {
    fmt.Errorf("Error: %s\n", err)
  }
}

CLI

vinxi provides a full-feateured command-line interface with a declarative configuration file capable of detailed configuration of one or multiple proxy servers.

Note: still a work in progress.

Installation

go get -u gopkg.in/vinxi/vinxictl.v0

Usage

vinxictl 0.1.0

Usage:
  vinxictl -p 80
  vinxictl -p 80 -c config.toml

Options:
  -a <addr>                 bind address [default: *]
  -p <port>                 bind port [default: 8080]
  -h, -help                 output help
  -v, -version              output version
  -c, -config               Config file path
  -f                        Target server URL to forward traffic by default
  -mrelease <num>           OS memory release inverval in seconds [default: 30]
  -cpus <num>               Number of used cpu cores.
                            (default for current machine is 8 cores)

API

See godoc to browse the self-documented API.

Manager

vinxi provides the manager package who has been designed to provide a both programmatic and HTTP API interfaces to manage one or multiple vinxi server instances.

For more details, see the specific manager documentation:

Admin API

vinxi provides a full-featured programmatic API to easily manage vinxi server instance via the manager package.

Manager programmatic API documentation is available via godoc.

Admin HTTP API

vinxi comes with an internal RESTful API for administration purposes. API commands can be run on any node, and vinxi will keep the configuration consistent and up-to-date in real time across the different vinxi server instances.

The RESTful Admin API server listens on port 8000 by default.

RESTful Admin API is part of manager package. Read more about the manager here.

Content Types

vinxi RESTful API is a JSON only HTTP interface. Responses and payloads as designed to render and read JSON only data structures.

The MIME content type used as HTTP Content-Type header must be:

application/json

Authentication

You can protect the admin HTTP API with a basic authentication mechanism.

Admin HTTP API is not protected by default.

HTTP basic authentication

You can define multiple user/password credentials to authenticate users.

Endpoints

Node information

GET /
Response
HTTP 200 OK
{
  "hostname": "vinxi-server",
  "version": "0.1.0",
  "runtime": "go1.6",
  "platform": "darwin",
  "cpus": 8,
  "gorutines": 13,
  "links": {
    "catalog": "/catalog",
    "instances": "/instances",
    "manager": "/manager",
    "plugins": "/plugins",
    "scopes": "/scopes"
  }
}

Global plugins

List plugins

GET /plugins
Response
[
  {
    "id": "UGEZGfua5S3U0nDS",
    "name": "auth",
    "description": "Authorization and authentication protection",
    "config": {
      "scheme": "Bearer",
      "token": "s3cr3t"
    }
  }
]

Register plugin

POST /plugins
Request Body
{
  "name":"auth", 
  "config": {
    "token": "s3cr3t"
  }
}
Response
{
  "id": "UGEZGfua5S3U0nDS",
  "name": "auth",
  "description": "Authorization and authentication protection",
  "config": {
    "scheme": "Bearer",
    "token": "s3cr3t"
  }
}

Get plugin

GET /plugins/{id}
Response
{
  "id": "UGEZGfua5S3U0nDS",
  "name": "auth",
  "description": "Authorization and authentication protection",
  "config": {
    "scheme": "Bearer",
    "token": "s3cr3t"
  }
}

Delete plugin

DELETE /plugins/{id}
Response
HTTP 204 No Content

Instances

List instances

GET /instances
Response
HTTP 200 OK
[
  {
    "info": {
      "id": "KamlJHrvH2owdzIG",
      "name": "default",
      "description": "This a default proxy",
      "hostname": "vinxi-server",
      "platform": "darwin",
      "server": {
        "port": 3100,
        "readTimeout": 0,
        "writeTimeout": 0,
        "address": ""
      }
    },
    "scopes": [
      {
        "id": "jd7CDZ48IsQ0RJqu",
        "name": "custom",
        "rules": [
          {
            "id": "MizprxflGgjeQe06",
            "name": "path",
            "description": "Matches HTTP request URL path againts a given path pattern",
            "config": {
              "path": "\/foo\/(.*)"
            }
          }
        ],
        "plugins": [
          {
            "id": "AsgTHxwUgUcg9oet",
            "name": "forward",
            "description": "Forward HTTP traffic to remote servers",
            "config": {
              "url": "http:\/\/httpbin.org"
            }
          }
        ]
      }
    ]
  }
]

Get instance

GET /instances/{id}
Response
HTTP 200 OK
{
  "info": {
    "id": "KamlJHrvH2owdzIG",
    "name": "default",
    "description": "This a default proxy",
    "hostname": "test",
    "platform": "darwin",
    "server": {
      "port": 3100,
      "readTimeout": 0,
      "writeTimeout": 0,
      "address": ""
    }
  },
  "scopes": [
    {
      "id": "jd7CDZ48IsQ0RJqu",
      "name": "custom",
      "rules": [
        {
          "id": "MizprxflGgjeQe06",
          "name": "path",
          "description": "Matches HTTP request URL path againts a given path pattern",
          "config": {
            "path": "\/foo\/(.*)"
          }
        }
      ],
      "plugins": [
        {
          "id": "AsgTHxwUgUcg9oet",
          "name": "forward",
          "description": "Forward HTTP traffic to remote servers",
          "config": {
            "url": "http:\/\/httpbin.org"
          }
        }
      ]
    }
  ]
}

Delete instance

DELETE /instances/{id}
Response
HTTP 204 No Content

Authors

License

Most is released under MIT License. Some code is under Apache License 2.0 (see specific file header for details).