Started implementing the APIs.

This commit is contained in:
Andrey Parhomenko 2023-12-07 16:55:23 +03:00
parent 9ca087edc9
commit 1350191dd4
4 changed files with 120 additions and 16 deletions

99
api.go Normal file
View 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()
}

View file

@ -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() {

View file

@ -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")
) )

View file

@ -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))
} }