Documentation
¶
Index ¶
- Constants
- Variables
- func Box2Http(b *B) http.Handler
- func DefaultDeserialize(ctx context.Context, r io.Reader, v interface{}) error
- func DefaultHandlerMethodNotAllowed(ctx context.Context)
- func DefaultHandlerResourceNotFound(ctx context.Context)
- func DefaultSerialize(ctx context.Context, w io.Writer, v interface{}) error
- func GetError(ctx context.Context) error
- func GetRequest(ctx context.Context) *http.Request
- func GetResponse(ctx context.Context) http.ResponseWriter
- func GetUrlParameter(ctx context.Context, param string) string
- func HandlerDoNothing(w http.ResponseWriter, r *http.Request)
- func Param(r *http.Request, param string) string
- func SetBoxContext(ctx context.Context, c *C) context.Context
- func SetError(ctx context.Context, err error)
- type A
- func Action(handler interface{}) *A
- func ActionPost(handler interface{}) *A
- func AnyMethod(handler interface{}) *A
- func Connect(handler interface{}) *A
- func Delete(handler interface{}) *A
- func Get(handler interface{}) *A
- func Head(handler interface{}) *A
- func Options(handler interface{}) *A
- func Patch(handler interface{}) *A
- func Post(handler interface{}) *A
- func Put(handler interface{}) *A
- func Trace(handler interface{}) *A
- type Attr
- type B
- type C
- type E
- type H
- type Handler
- type I
- type Interceptor
- type R
- func (r *R) GetActions() []*A
- func (r *R) Group(path string) *R
- func (r *R) Handle(method string, path string, handler interface{}) *A
- func (r *R) HandleFunc(method string, path string, handler http.HandlerFunc) *A
- func (r *R) Match(path string, parameters map[string]string) (result *R)
- func (r *R) Resource(locator string) *R
- func (r *R) Use(interceptor ...I) *R
- func (r *R) WithActions(action ...*A) *R
- func (r *R) WithAttribute(key string, value interface{}) *R
- func (r *R) WithInterceptors(interceptor ...I) *R
Examples ¶
Constants ¶
const ( AttrHttpMethod = "attr_http_method" AttrHttpBind = "attr_http_bind" AttrDoc = "attr_doc" )
const HttpMethodAny = "*"
Variables ¶
var ( ErrResourceNotFound = errors.New("resource_not_found") ErrMethodNotAllowed = errors.New("method_not_allowed") )
var DefaultAccessLogPrintln = log.Println
Functions ¶
func Box2Http ¶
Example (ErrorHandling) ¶
b := box.NewBox()
b.Use(box.PrettyError)
b.Handle("GET", "/articles", func() (*Article, error) {
return nil, errors.New("could not connect to the database")
})
s := httptest.NewServer(b)
defer s.Close()
// go b.ListenAndServe()
resp, _ := http.Get(s.URL + "/articles")
io.Copy(os.Stdout, resp.Body)
Output: could not connect to the database
func DefaultDeserialize ¶ added in v0.6.0
func DefaultHandlerMethodNotAllowed ¶ added in v0.5.0
func DefaultHandlerResourceNotFound ¶ added in v0.5.0
func DefaultSerialize ¶ added in v0.6.0
func GetResponse ¶
func GetResponse(ctx context.Context) http.ResponseWriter
func GetUrlParameter ¶ added in v0.2.0
func HandlerDoNothing ¶ added in v0.6.0
func HandlerDoNothing(w http.ResponseWriter, r *http.Request)
Types ¶
type A ¶
type A struct {
Attr
HttpMethod string
// Name is the name to identify the action AND the invocation to url suffix
Name string
// Bound is true if this action is not an extended action
Bound bool
// Interceptors is the list of actions that will be executed before executing handler
Interceptors []I
// contains filtered or unexported fields
}
An A stands for Action
func ActionPost ¶
func ActionPost(handler interface{}) *A
func (*A) GetHandler ¶ added in v0.3.1
GetHandler overwrite default action name
func (*A) WithAttribute ¶
func (*A) WithInterceptors ¶
type Attr ¶
type Attr map[string]interface{}
func (Attr) GetAttribute ¶
Get Attribute value using key string from Box, Resource or Action.
func (Attr) SetAttribute ¶
Set Attribute key-value to Box, Resource or Action.
type B ¶
type B struct {
// R is the root resource in box
*R
HttpHandler http.Handler
HandleResourceNotFound any
HandleMethodNotAllowed any
Deserializer func(ctx context.Context, r io.Reader, v interface{}) error
Serializer func(ctx context.Context, w io.Writer, v interface{}) error
}
func (*B) ListenAndServe ¶ added in v0.1.4
ListenAndServe is a helper that creates a new http.Server and call to its method ListenAndServe on address :8080
func (*B) Serve ¶
func (b *B) Serve()
Serve is a helper that creates a new http.Server and call to its method ListenAndServe on address :8080 Deprecated: Use the analogous name b.ListenAndServe
func (*B) ServeHTTP ¶ added in v0.1.4
func (b *B) ServeHTTP(w http.ResponseWriter, r *http.Request)
Example ¶
package main
import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"strings"
"time"
"github.com/fulldump/box"
)
type CreateArticleRequest struct {
Title string
Text string
}
type Article struct {
Id string `json:"id"`
Title string `json:"title"`
Text string `json:"text"`
Created time.Time `json:"created"`
}
func main() {
b := box.NewBox()
b.Handle("POST", "/articles", func(input CreateArticleRequest) Article {
fmt.Println("Persist new article...", input)
return Article{
Id: "my-new-id",
Title: input.Title,
Text: input.Text,
Created: time.Unix(1674762079, 0).UTC(),
}
})
s := httptest.NewServer(b)
defer s.Close()
// go b.ListenAndServe()
resp, _ := http.Post(s.URL+"/articles", "application/json", strings.NewReader(`{
"title": "My great article",
"text": "Blah blah blah..."
}`))
io.Copy(os.Stdout, resp.Body)
}
Output: Persist new article... {My great article Blah blah blah...} {"id":"my-new-id","title":"My great article","text":"Blah blah blah...","created":"2023-01-26T19:41:19Z"}
Example (AccessLogMiddleware) ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/fulldump/box"
)
func ListArticles() { /* ... */ }
func CreateArticle() { /* ... */ }
func GetArticle() { /* ... */ }
func DeleteArticle() { /* ... */ }
var mockAccessLogPrintln = func(a ...interface{}) {
a = append([]interface{}{"2023/01/26 21:05:15"}, a...)
fmt.Println(a...)
}
func main() {
// Mock access log
box.DefaultAccessLogPrintln = mockAccessLogPrintln
b := box.NewBox()
b.Use(box.RecoverFromPanic) // use middlewares to print stacktraces
b.Use(box.AccessLog) // use middlewares to print logs
b.Use(box.PrettyError) // use middlewares return pretty errors
b.Handle("GET", "/articles", ListArticles)
b.Handle("POST", "/articles", CreateArticle)
b.Handle("GET", "/articles/{article-id}", GetArticle)
b.Handle("DELETE", "/articles/{article-id}", DeleteArticle)
s := httptest.NewServer(b)
defer s.Close()
// go b.ListenAndServe()
http.Get(s.URL + "/articles")
http.Get(s.URL + "/articles/25")
http.Get(s.URL + "/articles/3")
}
Output: 2023/01/26 21:05:15 GET /articles 2023/01/26 21:05:15 GET /articles/25 2023/01/26 21:05:15 GET /articles/3
Example (CustomInterceptor) ¶
package main
import (
"io"
"net/http"
"net/http/httptest"
"os"
"github.com/fulldump/box"
)
type MyResponse struct {
Name string
Age int
}
func main() {
b := box.NewBox()
b.Handle("GET", "/hello", func(w http.ResponseWriter, r *http.Request) MyResponse {
return MyResponse{
Name: "Fulanez",
Age: 33,
}
})
s := httptest.NewServer(b)
defer s.Close()
// go b.ListenAndServe()
resp, _ := http.Get(s.URL + "/hello")
io.Copy(os.Stdout, resp.Body)
}
Output: {"Name":"Fulanez","Age":33}
Example (GettingStarted) ¶
package main
import (
"io"
"net/http"
"net/http/httptest"
"os"
"github.com/fulldump/box"
)
func main() {
b := box.NewBox()
b.HandleFunc("GET", "/hello", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("World!"))
})
s := httptest.NewServer(b)
defer s.Close()
// go b.ListenAndServe()
resp, _ := http.Get(s.URL + "/hello")
io.Copy(os.Stdout, resp.Body)
}
Output: World!
Example (MyCustomInterceptor) ¶
package main
import (
"context"
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"github.com/fulldump/box"
)
func MyCustomInterceptor(next box.H) box.H {
return func(ctx context.Context) {
w := box.GetResponse(ctx)
w.Header().Set("Server", "MyServer")
next(ctx) // continue the flow
}
}
func main() {
b := box.NewBox()
b.Use(MyCustomInterceptor)
b.Handle("GET", "/articles/{article-id}", func(r *http.Request) *Article {
return &Article{
Id: box.Param(r, "article-id"),
Title: "Example",
}
})
s := httptest.NewServer(b)
defer s.Close()
// go b.ListenAndServe()
resp, _ := http.Get(s.URL + "/articles/77")
fmt.Println("Server:", resp.Header.Get("Server"))
io.Copy(os.Stdout, resp.Body)
}
Output: Server: MyServer {"id":"77","title":"Example","text":"","created":"0001-01-01T00:00:00Z"}
Example (ParametrizedInterceptor) ¶
b := box.NewBox()
b.Use(
box.SetResponseHeader("Server", "My server name"),
box.SetResponseHeader("Version", "v3.2.1"),
)
b.Handle("GET", "/articles/{article-id}", func(r *http.Request) *Article {
return &Article{
Id: box.Param(r, "article-id"),
Title: "Example",
}
})
s := httptest.NewServer(b)
defer s.Close()
// go b.ListenAndServe()
resp, _ := http.Get(s.URL + "/something")
for _, key := range []string{"Server", "Version", "Content-Length"} {
fmt.Println(key+":", resp.Header.Get(key))
}
Output: Server: My server name Version: v3.2.1 Content-Length: 0
Example (UrlParameters) ¶
package main
import (
"io"
"net/http"
"net/http/httptest"
"os"
"github.com/fulldump/box"
)
func main() {
b := box.NewBox()
b.Handle("GET", "/articles/{article-id}", func(w http.ResponseWriter, r *http.Request) string {
articleID := box.Param(r, "article-id")
return "ArticleID is " + articleID
})
s := httptest.NewServer(b)
defer s.Close()
// go b.ListenAndServe()
resp, _ := http.Get(s.URL + "/articles/123")
io.Copy(os.Stdout, resp.Body)
}
Output: "ArticleID is 123"
type C ¶
type C struct {
Resource *R
Action *A
Parameters map[string]string
// TODO: add headers
// TODO: add query
// TODO: add box
// TODO: ¿add marshaler and unmarshaler?
Request *http.Request
Response http.ResponseWriter
// contains filtered or unexported fields
}
An C is a box context to store box related thing in context such as *R, *A, *E, etc
func GetBoxContext ¶ added in v0.2.0
type H ¶
An H stands for Handler
func PrettyError ¶ added in v0.3.0
func RecoverFromPanic ¶ added in v0.3.0
RecoverFromPanic is an interceptor to recover and pretty print a stacktrace
type Interceptor ¶ added in v0.4.2
type Interceptor = I // Just alias to make it more readable
type R ¶
type R struct {
Attr
// Path is a literal or placeholder that matches with a portion of the path
Path string
// Parent is a reference to parent resource
Parent *R
// Children is the list of descendent resources
Children []*R
// Interceptors is the list of actions that will be executed before each
// action or resource under this resource
Interceptors []I
// contains filtered or unexported fields
}
R stands for Resource
func NewResource ¶
func NewResource() *R
func (*R) GetActions ¶ added in v0.1.0
GetActions retrieve the slice of actions defined in this resource
func (*R) Group ¶ added in v0.3.0
Group is an alias of Resource
Example ¶
b := box.NewBox()
v0 := b.Group("/v0")
v0.Use(box.SetResponseHeader("Content-Type", "application/json"))
v0.Handle("GET", "/articles", ListArticles)
v0.Handle("POST", "/articles", CreateArticle)
s := httptest.NewServer(b)
defer s.Close()
// go b.ListenAndServe()
resp, _ := http.Get(s.URL + "/v0/articles")
fmt.Println("Content-Type:", resp.Header.Get("Content-Type"))
Output: Content-Type: application/json
func (*R) HandleFunc ¶ added in v0.2.1
func (*R) WithAttribute ¶
func (*R) WithInterceptors ¶
Add interceptor to this resource