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
- Full-featured HTTP/S proxy.
- Modular plugin-based design.
- Middleware-oriented supporting multiple interfaces (e.g: http.Handler, Negroni, Alice…).
- Good interpolarity with existent middleware from the community.
- Idiomatic built on top of
net/http
. - Expressive and simple programmatic API.
- Command-line interface.
- Declarative configuration file.
- Admin REST API.
- Strong plugin ecosystem (e.g: metrics, service discovery, balancer…).
- Admin web UI (coming soon).
- Hot-reloading. Dynamic configuration in runtime.
- Small, hackable API and core.
- Fast (benchmarks coming soon).
- WebSocket proxy (beta).
- HTTP/2 support.
- Just Go. No third-party dependencies.
- Official Docker image.
Installation
go get -u gopkg.in/vinxi/vinxi.v0
Components
- mux - Simple, versatile and composable multiplexer for vinxi.
- context - Unobstructive context implementation for request-aware data sharing.
- intercept - HTTP traffic interceptor and modifier made easy.
- balancer - Simple traffic balancer supporting simple well-known distribution algorithms.
- replay - Replay HTTP traffic to multiple servers.
- router - Featured, composable and fast router with hierarchical middleware layer.
- forward - Default HTTP and WebSocket traffic forwarder.
- layer - Default middleware layer used in vinxi ecosystem.
- apachelog - Apache-style logging middleware.
- consul - Consul service discovery provider with optional traffic balancing.
- auth - HTTP authentication middleware supporting multiple schemes.
- ratelimit - Efficient token bucket rate limiter for your proxies.
- log - Structured, versatile, scoped logging layer.
- trace - Structured and versatile traffic tracing instrumentation.
- cors - W3C standard compliant full-featured CORS support.
- metrics - Extensible metrics instrumentation and reporting.
- ip - IP CIDR range based filtering and multiplexer for your proxies.
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).