ply

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2026 License: MIT Imports: 23 Imported by: 0

README

Ply

One ply over fasthttp — a thin, zero-allocation HTTP layer for Go.

Go Benchmarks Go Report Card Coverage Contributions License Last Commit Issues

Ply employs a Tiered Zero-Copy Routing (TZCR) system that categorizes routes into three levels—static, parametric, and wildcard—for optimal performance. Each route is precompiled and stored in a cache-aware structure, enabling fast, zero-allocation matching. Middleware is executed through efficient handler chaining, and route grouping allows modular design with custom prefixes and middlewares. This approach makes Ply ideal for high-performance applications without sacrificing flexibility.

Ply Key Features are :

  • Middleware-first — use .Use()
  • Ultra-fast router & context engine
  • Built-in async engines (PubSub, Queue, Cache)
  • Extensible and clean internal architecture
  • Optional middleware: Auth, Logger, Recovery
  • Test helpers: app.Test(req) runs requests in-process, no port needed
  • CLI generator: npx create-ply for instant project scaffolding

🔐 Example: Auth Middleware

Use the built-in auth middleware with environment variable AUTH_SECRET:

app.Use(middleware.Auth(os.Getenv("AUTH_SECRET")))

Set your secret in .env:

export AUTH_SECRET=supersecurekey123

🚀 Getting started

Manual Installation Ply
go get github.com/Dziqha/ply
Ply CLI (npx create-ply@latest)

Scaffold Ply apps instantly via CLI.

npx create-ply@latest myapp

Interactive prompts:

  • ✅ Feature name (e.g. user, auth, order)

  • 📁 Feature-based project structure generated automatically

  • ⚙️ Ready-to-extend architecture out of the box

⚠️ We intentionally use Node.js to overcome limitations of Go's CLI tooling, especially for rich interactive workflows.

Running Ply Example
package main

import (
	"github.com/Dziqha/ply"
	"github.com/Dziqha/ply/core"
)

func main() {
	app := ply.New()

	app.Get("/", func(c *core.Context) {
		c.Text(200, "Hello from Ply!")
	})

	app.RunServer(":8080")
}

To run the code, use the go run command, like:

go run example.go

Your Ply app will be available at http://localhost:8080


🧪 Benchmark Overview

Measured on a 6C/12T Ryzen 5 5600H with Go 1.26, wrk on the same host, round-robin reps, median of 3. Method, spread and caveats: Benchmarks docs.

Workload Ply fasthttp Fiber v3 Gin Echo
GET /user/42, c=200, t=6 442,483 453,821 439,446 264,289 256,752
GET /user/42, c=512, t=12 450,054 462,022 441,530 275,065 270,836
In-process, per request 180 ns 173 ns (bare path+switch) 305 ns — —

Ply is a thin layer over fasthttp: within 3% of the engine and 1-2% of Fiber in the thread-matched run, and inside the noise band at oversubscribed concurrency. In-process it costs ~7 ns more than a bare path-plus-switch handler. What the framework adds is zero-allocation routing and built-in engines, not a different HTTP engine.


🤝 Contributing

Contributions are welcome — from fixing typos to suggesting ideas or building features. Ply grows through small steps, open discussions, and shared curiosity. Join the conversation on Discussions.

❤️ About

Ply is handcrafted with performance, simplicity, and extensibility in mind — empowering developers to build Go web backends without the bloat.

Ready to go fast? Build with Ply. 🌀 Give it a ⭐ on GitHub if you like it!


📄 License

This project is licensed under the MIT License

Built with love by @dziqha

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Banner(addr string) string

func CenterText

func CenterText(text string) string

Types

type App

type App struct {
	EngineCtx *core.EngineContext

	ErrorHandler func(*core.Context, error)
	// contains filtered or unexported fields
}

func New

func New() *App

func (*App) Add

func (a *App) Add(methods []string, path string, h core.Handler, hs ...core.Handler) *router.Route

func (*App) All

func (a *App) All(path string, handler core.Handler, handlers ...core.Handler) *router.Route

func (*App) Connect

func (a *App) Connect(path string, h core.Handler, hs ...core.Handler) *router.Route

func (*App) Delete

func (a *App) Delete(path string, handler core.Handler, handlers ...core.Handler) *router.Route

func (*App) Get

func (a *App) Get(path string, handler core.Handler, handlers ...core.Handler) *router.Route

HTTP method shortcuts

func (*App) GetFast

func (a *App) GetFast(path string, handler fasthttp.RequestHandler) *router.Route

func (*App) Group

func (a *App) Group(prefix string, middlewares ...core.Handler) *Group

func (*App) Handler

func (a *App) Handler() fasthttp.RequestHandler

func (*App) Head

func (a *App) Head(path string, handler core.Handler, handlers ...core.Handler) *router.Route

func (*App) MethodNotAllowed

func (a *App) MethodNotAllowed(h core.Handler) *App

func (*App) NotFound

func (a *App) NotFound(h core.Handler) *App

func (*App) Options

func (a *App) Options(path string, handler core.Handler, handlers ...core.Handler) *router.Route

func (*App) Patch

func (a *App) Patch(path string, handler core.Handler, handlers ...core.Handler) *router.Route

func (*App) Post

func (a *App) Post(path string, handler core.Handler, handlers ...core.Handler) *router.Route

func (*App) Put

func (a *App) Put(path string, handler core.Handler, handlers ...core.Handler) *router.Route

func (*App) Route

func (a *App) Route(path string) *router.Route

func (*App) RunServer

func (a *App) RunServer(addr string) error

func (*App) RunTLSServer

func (a *App) RunTLSServer(addr, certFile, keyFile string) error

func (*App) RunWithGracefulShutdown

func (a *App) RunWithGracefulShutdown(addr string) error

func (*App) SetErrorHandler

func (a *App) SetErrorHandler(fn func(*core.Context, error)) *App

func (*App) Shutdown

func (a *App) Shutdown(ctx context.Context) error

func (*App) Static

func (a *App) Static(prefix, dir string) *App

func (*App) Templates

func (a *App) Templates(dir string) *App

func (*App) Test

func (a *App) Test(req *http.Request) *http.Response

Test runs req through the full application (router, middleware, recovery) without opening a network listener, and returns the recorded response. It is meant for tests:

req := httptest.NewRequest(http.MethodGet, "/user/42", nil)
resp := app.Test(req)
if resp.StatusCode != http.StatusOK { ... }
body, _ := io.ReadAll(resp.Body)

The response body is buffered, so it stays readable after the call. The handler is cached after the first call; routes registered later are still matched because the router rebuilds its table lazily.

func (*App) Use

func (a *App) Use(args ...any) *App

func (*App) WithCache

func (a *App) WithCache() *App

func (*App) WithPubsub

func (a *App) WithPubsub() *App

func (*App) WithQueue

func (a *App) WithQueue() *App

func (*App) WrapHandlers

func (a *App) WrapHandlers(hs []core.Handler) fasthttp.RequestHandler

type Group

type Group struct {
	// contains filtered or unexported fields
}

func (*Group) Add

func (g *Group) Add(methods []string, path string, h core.Handler, hs ...core.Handler) *router.Route

func (*Group) All

func (g *Group) All(path string, h core.Handler, hs ...core.Handler) *router.Route

func (*Group) Delete

func (g *Group) Delete(path string, h core.Handler, hs ...core.Handler) *router.Route

func (*Group) Get

func (g *Group) Get(path string, h core.Handler, hs ...core.Handler) *router.Route

func (*Group) Options

func (g *Group) Options(path string, h core.Handler, hs ...core.Handler) *router.Route

func (*Group) Patch

func (g *Group) Patch(path string, h core.Handler, hs ...core.Handler) *router.Route

func (*Group) Post

func (g *Group) Post(path string, h core.Handler, hs ...core.Handler) *router.Route

func (*Group) Put

func (g *Group) Put(path string, h core.Handler, hs ...core.Handler) *router.Route

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL