Started implementing the APIs.
This commit is contained in:
parent
9ca087edc9
commit
1350191dd4
4 changed files with 120 additions and 16 deletions
99
api.go
Normal file
99
api.go
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
package bond
|
||||||
|
|
||||||
|
import (
|
||||||
|
//"io"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ContentType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
PlainText ContentType = "text/plain; charset=utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Decoder interface {
|
||||||
|
Decode(any) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApiFunc func(*Context)
|
||||||
|
func (fn ApiFunc) ServeHTTP(w ResponseWriter, r *Request) {
|
||||||
|
fn(&Context{
|
||||||
|
R: r,
|
||||||
|
W: w,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type Context struct {
|
||||||
|
R *Request
|
||||||
|
W ResponseWriter
|
||||||
|
// Custom data to store stuff.
|
||||||
|
Data any
|
||||||
|
dec Decoder
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) SetContentType(typ ContentType) {
|
||||||
|
c.SetHeader("Content-Type", string(typ))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) ContentType() string {
|
||||||
|
ret, ok := c.Header("Content-Type")
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if len(ret) < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return ret[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) SetHeader(k, v string) {
|
||||||
|
c.W.Header().Set(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) Header(name string) ([]string, bool) {
|
||||||
|
ret, ok := c.R.Header[name]
|
||||||
|
return ret, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closes the requests body after finishes scaning.
|
||||||
|
func (c *Context) Close() {
|
||||||
|
c.R.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan the incoming value from body depending
|
||||||
|
// on the content type of the request.
|
||||||
|
func (c *Context) Scan(v any) error {
|
||||||
|
if c.dec == nil {
|
||||||
|
typ := c.ContentType()
|
||||||
|
switch typ {
|
||||||
|
case "application/json" :
|
||||||
|
c.dec = json.NewDecoder(c.R.Body)
|
||||||
|
default:
|
||||||
|
return UnknownContentTypeErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := c.dec.Decode(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) Path() string {
|
||||||
|
return c.R.URL.Path
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) NotFound() {
|
||||||
|
http.NotFound(c.W, c.R)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) Printf(format string, v ...any) (int, error) {
|
||||||
|
return fmt.Fprintf(c.W, format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Context) Query() url.Values {
|
||||||
|
return c.R.URL.Query()
|
||||||
|
}
|
|
@ -7,25 +7,42 @@ import (
|
||||||
var root = bond.Mux().
|
var root = bond.Mux().
|
||||||
Def(
|
Def(
|
||||||
"",
|
"",
|
||||||
bond.ContextFunc(func(c *bond.Context){
|
bond.ApiFunc(func(c *bond.Context){
|
||||||
c.W.Write([]byte("This is the index page"))
|
c.W.Write([]byte("This is the index page"))
|
||||||
}),
|
}),
|
||||||
).Def(
|
).Def(
|
||||||
"hello",
|
"hello",
|
||||||
bond.Mux().Def(
|
bond.Mux().Def(
|
||||||
"en",
|
"en",
|
||||||
bond.ContextFunc(func(c *bond.Context){
|
bond.ApiFunc(func(c *bond.Context){
|
||||||
c.W.Write([]byte("Hello, World!"))
|
c.W.Write([]byte("Hello, World!"))
|
||||||
}),
|
}),
|
||||||
).Def(
|
).Def(
|
||||||
"ru",
|
"ru",
|
||||||
bond.ContextFunc(func(c *bond.Context){
|
bond.ApiFunc(func(c *bond.Context){
|
||||||
c.W.Write([]byte("Привет, Мир!"))
|
c.W.Write([]byte("Привет, Мир!"))
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
).Def(
|
).Def(
|
||||||
"web",
|
"web",
|
||||||
bond.Static("./static"),
|
bond.Static("./static"),
|
||||||
|
).Def(
|
||||||
|
"test",
|
||||||
|
bond.ApiFunc(func(c *bond.Context){
|
||||||
|
c.SetContentType(bond.PlainText)
|
||||||
|
c.Printf(
|
||||||
|
"Path: %q\n" +
|
||||||
|
"Content-Type: %q\n",
|
||||||
|
c.Path(), c.ContentType(),
|
||||||
|
)
|
||||||
|
c.Printf("Query:\n")
|
||||||
|
for k, vs := range c.Query() {
|
||||||
|
c.Printf("\t%q:\n", k)
|
||||||
|
for _, v := range vs {
|
||||||
|
c.Printf("\t\t%q\n", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
@ -6,4 +6,5 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DupDefErr = errors.New("duplicate route define")
|
DupDefErr = errors.New("duplicate route define")
|
||||||
|
UnknownContentTypeErr = errors.New("unknown content type")
|
||||||
)
|
)
|
||||||
|
|
13
handler.go
13
handler.go
|
@ -10,19 +10,6 @@ type HandlerFunc = http.HandlerFunc
|
||||||
type Handler = http.Handler
|
type Handler = http.Handler
|
||||||
type Server = http.Server
|
type Server = http.Server
|
||||||
|
|
||||||
type Context struct {
|
|
||||||
R *Request
|
|
||||||
W ResponseWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
type ContextFunc func(*Context)
|
|
||||||
func (fn ContextFunc) ServeHTTP(w ResponseWriter, r *Request) {
|
|
||||||
fn(&Context{
|
|
||||||
R: r,
|
|
||||||
W: w,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Static(pth string) Handler {
|
func Static(pth string) Handler {
|
||||||
return http.FileServer(http.Dir(pth))
|
return http.FileServer(http.Dir(pth))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue