rem

package module
v1.1.5 Latest Latest
Warning

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

Go to latest
Published: Mar 11, 2023 License: MIT Imports: 9 Imported by: 0

README

TheDeveloper10/rem

Package TheDeveloper10/rem implements a request router and dispatcher for matching incoming requests to their respective handler.

The name REM comes from the state of sleep called REM. The same way sleep is a rest from engineering this package is a rest from swiss knife packages that solve all of your problems and create a thousand more.

The main features are:

  • It implements the http.Handler interface so it is compatible with net/http (this allows for use of other packages such as github.com/rs/cors)
  • Requests can be matched based on URL paths and HTTP Methods
  • URL paths can have optional variables


Install

With a correctly configured Go toolchain:

go get -u github.com/TheDeveloper10/rem@v1.1.1

Examples

This is a very simple example that describes the entire package really well. First we create a new rem.Router and then we use it to create new routes. The process of creating routes is really easy: we just use the Get for handling GET HTTP method, Post for handling POST HTTP method, etc. for the rest of the methods and then we assign the handlers that we want the data to go through.

In all of the cases in this example we go through AuthMiddleware. That's just a middleware used for authentication of the call. If the call passes through the AuthMiddleware it goes to the respective handler (e.g. GetProductsHandle).

func main() {
	// Create a new router
	router := rem.NewRouter()
	
	// Add a new route
	router.
		NewRoute("/products").
		Get(AuthMiddleware, GetProductsHandle).
		Post(AuthMiddleware, CreateProductsHandle)
	    
	
	// Add a new route
	router.
		NewRoute("/products/:productId").
		Get(AuthMiddleware, GetProductHandle).
		Put(AuthMiddleware, ReplaceProductHandle).
		Delete(AuthMiddleware, DeleteProductHandle)
	
	// Start the HTTP server
	http.ListenAndServe(":80", router)
}

Creating your own handlers:

type userResponse struct {
	id string `json:"id"`
}

func main() {
	router := rem.NewRouter()
	
	router.
		NewRoute("/users").
		Post(func(response rem.IResponse, request rem.IRequest) bool {
			request.
				Status(http.StatusCreated).
				JSON(useResponse{
					id: "jxIZp17"
				})
        
			// In case of a single handler it doesn't matter what you 
			// return (true or false). It only matters when there's more 
			// than one handler because that's how the route decides to 
			// continue passing to the next handler.
			return true
		})
}

Middlewares and handlers:

func AuthMiddleware(response rem.IResponse, request rem.IRequest) bool {
	authHeader, status := request.GetHeaders().Get("Authentication")
	if !status {
		response.Status(http.StatusUnauthorized)
		// Returning false means it will not continue to the next handler
		return false
	}
	
	// Obviously here you won't perform this type of authentication...
	if authHeader != "1234" {
		response.Status(http.StatusUnauthorized)
		return false
	}
	
	return true
}

func GetProductsHandler(response rem.IResponse, request rem.IRequest) bool {
	response.
		JSON([]Product{
			{ id: "nXJf", price: 39.99, name: "Super new shoes" },
			{ id: "zeq2", price: 1999.99, name: "Newest Phone" },
			{ id: "cv41", price: 4.99, name: "New headphones" },
		}).
		Status(http.StatusOK)
	
	return true
}

type Product struct {
	id    string
	price float32
	name  string
}

Path and Query parameters in URL:

type Product struct {
	Id    string  `json:"id"`
	Price float32 `json:"price"`
	Name  string  `json:"name"` 
}

func GetProductHandler(response rem.IResponse, request rem.IRequest) bool {
	productId, status1 := request.GetURLParameters().Get("productId")
	if !status1 {
		response.Status(http.StatusBadRequest)
	    return true	
    }
	
	priceStr, status2 := request.GetQueryParameters().Get("price")
	
	priceVal := 3.99
	if status2 {
		priceFloat, err := strconv.ParseFloat(priceStr, 64)
		if err == nil {
		    priceVal = float32(priceFloat)
		}
	}
	
	// e.g. for request GET /products/ZxF?price=40 the result will be:
	// { "id": "ZxF", "price": 40, "Name": "Some Name" }

	// and for request GET /products/qwe the result will be:
	// { "id": "qwe", "price": 3.99, "Name": "Some Name" }

	response.
		Status(http.StatusOK).
		JSON(Product{
		    Id: productId,
			Price: priceVal,
			Name: "Some name"
		})
	
	return true
}

func main() {
	router := rem.NewRouter()
	
	router.
		NewRoute("/products/:productId").
		Get(GetProductHandler)
	
	http.ListenAndServe(":80", router)
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BasicRequest

type BasicRequest struct {
	URL             string
	Method          string
	Headers         KeyValues
	Cookies         []*http.Cookie
	URLParameters   KeyValue
	QueryParameters KeyValues
	Body            io.ReadCloser
	Request         *http.Request
}

func (*BasicRequest) GetBody

func (br *BasicRequest) GetBody() io.ReadCloser

func (*BasicRequest) GetCookies

func (br *BasicRequest) GetCookies() []*http.Cookie

func (*BasicRequest) GetHeaders

func (br *BasicRequest) GetHeaders() KeyValues

func (*BasicRequest) GetMethod

func (br *BasicRequest) GetMethod() string

func (*BasicRequest) GetQueryParameters

func (br *BasicRequest) GetQueryParameters() KeyValues

func (*BasicRequest) GetRequest added in v1.1.5

func (br *BasicRequest) GetRequest() *http.Request

func (*BasicRequest) GetURL

func (br *BasicRequest) GetURL() string

func (*BasicRequest) GetURLParameters

func (br *BasicRequest) GetURLParameters() KeyValue

type BasicRoute

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

func NewBasicRoute

func NewBasicRoute(url string) *BasicRoute

func (*BasicRoute) Delete added in v1.1.0

func (br *BasicRoute) Delete(handlers ...Handler) IRoute

func (*BasicRoute) Get added in v1.1.0

func (br *BasicRoute) Get(handlers ...Handler) IRoute

func (*BasicRoute) Match

func (br *BasicRoute) Match(targetURL string) bool

func (*BasicRoute) MultiMethod added in v1.1.1

func (br *BasicRoute) MultiMethod(methods []string, handlers ...Handler) IRoute

func (*BasicRoute) Patch added in v1.1.0

func (br *BasicRoute) Patch(handlers ...Handler) IRoute

func (*BasicRoute) Post added in v1.1.0

func (br *BasicRoute) Post(handlers ...Handler) IRoute

func (*BasicRoute) Put added in v1.1.0

func (br *BasicRoute) Put(handlers ...Handler) IRoute

type HTTPResponseWriterWrapper

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

A wrapper of http.ResponseWriter that implements IResponse

func WrapHTTPResponseWriter added in v1.1.3

func WrapHTTPResponseWriter(rw http.ResponseWriter) *HTTPResponseWriterWrapper

func (*HTTPResponseWriterWrapper) Bytes

func (w *HTTPResponseWriterWrapper) Bytes(bytes []byte) IResponse

Write bytes to the body

func (*HTTPResponseWriterWrapper) Header

func (w *HTTPResponseWriterWrapper) Header(key string, value string) IResponse

Set a new header (Writes directly to http.ResponseWriter because the only thing that matters is the headers to be written first)

func (*HTTPResponseWriterWrapper) JSON

func (w *HTTPResponseWriterWrapper) JSON(data interface{}) IResponse

Write JSON to the body (also sets Content-Type header)

func (*HTTPResponseWriterWrapper) Status

func (w *HTTPResponseWriterWrapper) Status(statusCode int) IResponse

Writes a status code

func (*HTTPResponseWriterWrapper) Text

Write text to the body

type Handler

type Handler func(writer IResponse, request IRequest) bool

type IRequest

type IRequest interface {
	GetURL() string
	GetMethod() string
	GetHeaders() KeyValues
	GetCookies() []*http.Cookie
	GetURLParameters() KeyValue

	GetQueryParameters() KeyValues
	GetBody() io.ReadCloser
	GetRequest() *http.Request
	// contains filtered or unexported methods
}

func NewBasicRequest

func NewBasicRequest(req *http.Request) IRequest

type IResponse

type IResponse interface {
	Status(statusCode int) IResponse
	Header(key string, value string) IResponse
	Bytes(data []byte) IResponse
	Text(text string) IResponse
	JSON(data interface{}) IResponse
}

type IRoute

type IRoute interface {
	Match(url string) bool

	Get(handlers ...Handler) IRoute
	Post(handlers ...Handler) IRoute
	Patch(handlers ...Handler) IRoute
	Put(handlers ...Handler) IRoute
	Delete(handlers ...Handler) IRoute
	MultiMethod(methods []string, handlers ...Handler) IRoute
	// contains filtered or unexported methods
}

type KeyValue

type KeyValue map[string]string

func (KeyValue) Get

func (kv KeyValue) Get(key string) string

type KeyValues

type KeyValues map[string][]string

func (KeyValues) Get

func (kv KeyValues) Get(key string) string

type MockRequest added in v1.1.3

type MockRequest struct {
	URL             string
	Method          string
	Headers         KeyValues
	Cookies         []*http.Cookie
	URLParameters   KeyValue
	QueryParameters KeyValues

	// Fill in at most one of them
	// Leave the rest empty
	Body     string      // body that is a string
	BodyJSON interface{} // object that will be converted to JSON and used as a body
}

func (*MockRequest) GetBody added in v1.1.3

func (mr *MockRequest) GetBody() io.ReadCloser

func (*MockRequest) GetCookies added in v1.1.3

func (mr *MockRequest) GetCookies() []*http.Cookie

func (*MockRequest) GetHeaders added in v1.1.3

func (mr *MockRequest) GetHeaders() KeyValues

func (*MockRequest) GetMethod added in v1.1.3

func (mr *MockRequest) GetMethod() string

func (*MockRequest) GetQueryParameters added in v1.1.3

func (mr *MockRequest) GetQueryParameters() KeyValues

func (*MockRequest) GetRequest added in v1.1.5

func (mr *MockRequest) GetRequest() *http.Request

func (*MockRequest) GetURL added in v1.1.3

func (mr *MockRequest) GetURL() string

func (*MockRequest) GetURLParameters added in v1.1.3

func (mr *MockRequest) GetURLParameters() KeyValue

type MockResponse added in v1.1.3

type MockResponse struct {
	StatusCode int
	Headers    KeyValues
	Body       []byte
}

func NewMockResponse added in v1.1.3

func NewMockResponse() *MockResponse

func (*MockResponse) Bytes added in v1.1.3

func (mr *MockResponse) Bytes(data []byte) IResponse

func (*MockResponse) CompareBody added in v1.1.3

func (mr *MockResponse) CompareBody(other *MockResponse) bool

func (*MockResponse) CompareHeaders added in v1.1.3

func (mr *MockResponse) CompareHeaders(other *MockResponse) bool

func (*MockResponse) CompareStatus added in v1.1.3

func (mr *MockResponse) CompareStatus(other *MockResponse) bool

func (*MockResponse) Header added in v1.1.3

func (mr *MockResponse) Header(key string, value string) IResponse

func (*MockResponse) JSON added in v1.1.3

func (mr *MockResponse) JSON(data interface{}) IResponse

func (*MockResponse) Status added in v1.1.3

func (mr *MockResponse) Status(statusCode int) IResponse

func (*MockResponse) Text added in v1.1.3

func (mr *MockResponse) Text(text string) IResponse

type Router

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

func NewRouter

func NewRouter() *Router

func (*Router) AddRoute

func (r *Router) AddRoute(route IRoute) IRoute

Add a new route to the router

func (*Router) NewRoute

func (r *Router) NewRoute(url string) IRoute

Create and add a new basic route

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(res http.ResponseWriter, req *http.Request)

Handle HTTP requests

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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