mirror of
https://github.com/labstack/echo.git
synced 2024-12-24 20:14:31 +02:00
Remove socket supoort
Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
parent
7c9a0b6489
commit
9f6f4e8afb
78
README.md
78
README.md
@ -1,78 +1,2 @@
|
||||
# Bolt
|
||||
Multi transport, multi format REST style network library
|
||||
|
||||
## Socket Specification
|
||||
|
||||
### Trasport
|
||||
- WebSocket
|
||||
- TCP
|
||||
|
||||
### Command (*1-byte*)
|
||||
- INIT (**1**)
|
||||
- AUTH (**2**)
|
||||
- HTTP (**3**)
|
||||
- PUB (**4**)
|
||||
- MPUB (**5**)
|
||||
- SUB (**6**)
|
||||
- USUB (**7**)
|
||||
|
||||
### INIT
|
||||
> Request
|
||||
|
||||
```sh
|
||||
1 # Command (1-byte)
|
||||
99 # Correlation ID (4-byte)
|
||||
8 # Config length (2-byte)
|
||||
{} # Config as JSON (n-byte)
|
||||
```
|
||||
> Config
|
||||
```js
|
||||
{
|
||||
"Format":
|
||||
}
|
||||
```
|
||||
> Response
|
||||
|
||||
```sh
|
||||
99 # Correlation ID (4-byte)
|
||||
200 # Status code (2-byte)
|
||||
```
|
||||
|
||||
### AUTH
|
||||
> Request
|
||||
|
||||
```sh
|
||||
2 # Command (1-byte)
|
||||
99 # Correlation ID (4-byte)
|
||||
30 # Token length (2-byte)
|
||||
1g42*jMG!a?D3eF>Xwt!dI05]Y9egP # Token (n-byte)
|
||||
```
|
||||
> Response
|
||||
|
||||
```sh
|
||||
99 # Correlation ID (4-byte)
|
||||
200 # Status code (2-byte)
|
||||
```
|
||||
|
||||
### HTTP
|
||||
> Request
|
||||
|
||||
```sh
|
||||
3 # Command (1-byte)
|
||||
99 # Correlation ID (4-byte)
|
||||
GET\n # Method (n-byte)
|
||||
/users\n # Path (n-byte)
|
||||
- # Headers
|
||||
64 # Body length (8-byte)
|
||||
- # Body (n-byte)
|
||||
```
|
||||
> Response
|
||||
|
||||
```sh
|
||||
3 # Command (1-byte)
|
||||
200 # Status code (2-byte)
|
||||
|
||||
# For POST, PUT & PATCH
|
||||
64 # Body length (8-byte)
|
||||
- # Body (n-byte)
|
||||
```
|
||||
Coming soon...
|
||||
|
101
bolt.go
101
bolt.go
@ -1,14 +1,9 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
type (
|
||||
@ -18,37 +13,15 @@ type (
|
||||
maxParam byte
|
||||
notFoundHandler HandlerFunc
|
||||
methodNotAllowedHandler HandlerFunc
|
||||
tcpListener *net.TCPListener
|
||||
// udpConn *net.UDPConn
|
||||
pool sync.Pool
|
||||
pool sync.Pool
|
||||
}
|
||||
|
||||
command byte
|
||||
format byte
|
||||
transport byte
|
||||
|
||||
HandlerFunc func(*Context)
|
||||
Format byte
|
||||
)
|
||||
|
||||
const (
|
||||
CmdINIT command = 1 + iota
|
||||
CmdAUTH
|
||||
CmdHTTP
|
||||
CmdPUB
|
||||
CmdSUB
|
||||
CmdUSUB
|
||||
)
|
||||
|
||||
const (
|
||||
TrnspHTTP transport = 1 + iota
|
||||
TrnspWS
|
||||
TrnspTCP
|
||||
)
|
||||
|
||||
const (
|
||||
FmtJSON format = 1 + iota
|
||||
FmtJSON Format = 1 + iota
|
||||
FmtMsgPack
|
||||
FmtBinary = 20
|
||||
)
|
||||
|
||||
const (
|
||||
@ -87,7 +60,6 @@ func New(opts ...func(*Bolt)) (b *Bolt) {
|
||||
b.pool.New = func() interface{} {
|
||||
return &Context{
|
||||
Writer: NewResponse(nil),
|
||||
Socket: new(Socket),
|
||||
params: make(Params, b.maxParam),
|
||||
store: make(store),
|
||||
i: -1,
|
||||
@ -176,7 +148,6 @@ func (b *Bolt) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
// Find and execute handler
|
||||
h, c, s := b.Router.Find(r.Method, r.URL.Path)
|
||||
if h != nil {
|
||||
c.Transport = TrnspHTTP
|
||||
c.Writer.ResponseWriter = rw
|
||||
c.Request = r
|
||||
h(c)
|
||||
@ -190,70 +161,6 @@ func (b *Bolt) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
b.pool.Put(c)
|
||||
}
|
||||
|
||||
func (b *Bolt) handleSocket(conn io.ReadWriteCloser, tp transport) {
|
||||
// TODO: From pool?
|
||||
defer conn.Close()
|
||||
s := &Socket{
|
||||
Transport: tp,
|
||||
config: Config{},
|
||||
conn: conn,
|
||||
Reader: bufio.NewReader(conn),
|
||||
Writer: bufio.NewWriter(conn),
|
||||
bolt: b,
|
||||
}
|
||||
Loop:
|
||||
for {
|
||||
c, err := s.Reader.ReadByte() // Command
|
||||
if err != nil {
|
||||
log.Println(err, 222, c)
|
||||
}
|
||||
cmd := command(c)
|
||||
println(cmd)
|
||||
switch cmd {
|
||||
case CmdINIT:
|
||||
s.Init()
|
||||
case CmdHTTP:
|
||||
s.HTTP()
|
||||
default:
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bolt) RunHTTP(addr string) {
|
||||
func (b *Bolt) Run(addr string) {
|
||||
log.Fatal(http.ListenAndServe(addr, b))
|
||||
}
|
||||
|
||||
func (b *Bolt) RunWS(addr string) {
|
||||
http.Handle("/", websocket.Handler(func(ws *websocket.Conn) {
|
||||
b.handleSocket(ws, TrnspWS)
|
||||
}))
|
||||
log.Fatal(http.ListenAndServe(addr, nil))
|
||||
}
|
||||
|
||||
func (b *Bolt) RunTCP(addr string) {
|
||||
a, _ := net.ResolveTCPAddr("tcp", addr)
|
||||
l, err := net.ListenTCP("tcp", a)
|
||||
if err != nil {
|
||||
log.Fatalf("bolt: %v", err)
|
||||
}
|
||||
b.tcpListener = l
|
||||
go b.serve("tcp")
|
||||
}
|
||||
|
||||
func (b *Bolt) serve(net string) {
|
||||
switch net {
|
||||
case "ws":
|
||||
case "tcp":
|
||||
for {
|
||||
conn, err := b.tcpListener.Accept()
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
go b.handleSocket(conn, TrnspTCP)
|
||||
}
|
||||
default:
|
||||
// TODO: handle it!
|
||||
}
|
||||
}
|
||||
|
118
bolt_test.go
118
bolt_test.go
@ -1,14 +1,17 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
user struct {
|
||||
Id string
|
||||
Name string
|
||||
}
|
||||
)
|
||||
|
||||
var u = user{
|
||||
@ -16,113 +19,6 @@ var u = user{
|
||||
Name: "Joe",
|
||||
}
|
||||
|
||||
func startTCPServer() (b *Bolt, addr string) {
|
||||
var wg sync.WaitGroup
|
||||
b = New()
|
||||
a, _ := net.ResolveTCPAddr("tcp", "localhost:0")
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
b.RunTCP(a.String())
|
||||
}()
|
||||
wg.Wait()
|
||||
addr = b.tcpListener.Addr().String()
|
||||
return
|
||||
}
|
||||
|
||||
func connectTCPServer(addr string) (conn net.Conn, err error) {
|
||||
conn, err = net.DialTimeout("tcp", addr, time.Second)
|
||||
return
|
||||
}
|
||||
|
||||
func TestSocketInit(t *testing.T) {
|
||||
b, addr := startTCPServer()
|
||||
conn, err := connectTCPServer(addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
defer b.tcpListener.Close()
|
||||
|
||||
// Request
|
||||
buf := new(bytes.Buffer)
|
||||
buf.WriteByte(byte(CmdINIT)) // Command
|
||||
cfg := &Config{
|
||||
Format: FmtJSON,
|
||||
}
|
||||
bt, err := json.Marshal(cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
binary.Write(buf, binary.BigEndian, uint16(len(bt))) // Config length
|
||||
buf.Write(bt) // Config
|
||||
buf.WriteTo(conn)
|
||||
|
||||
// Response
|
||||
var n uint16
|
||||
err = binary.Read(conn, binary.BigEndian, &n) // Status code
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != 200 {
|
||||
t.Errorf("status code should be 200, found %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSocketHTTP(t *testing.T) {
|
||||
b, addr := startTCPServer()
|
||||
conn, err := connectTCPServer(addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
defer b.tcpListener.Close()
|
||||
|
||||
// GET
|
||||
b.Get("/users", func(c *Context) {
|
||||
c.Render(200, FmtJSON, u)
|
||||
})
|
||||
buf := new(bytes.Buffer)
|
||||
buf.WriteByte(byte(CmdHTTP)) // Command
|
||||
buf.WriteString("GET\n") // Method
|
||||
buf.WriteString("/users\n") // Path
|
||||
buf.WriteTo(conn)
|
||||
var n uint16
|
||||
err = binary.Read(conn, binary.BigEndian, &n) // Status code
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != 200 {
|
||||
t.Errorf("status code should be 200, found %d", n)
|
||||
}
|
||||
verifyUser(conn, t)
|
||||
|
||||
// POST
|
||||
b.Post("/users", func(c *Context) {
|
||||
c.Bind(c.Socket.config.Format, &user{})
|
||||
c.Render(201, FmtJSON, u)
|
||||
})
|
||||
buf.Reset()
|
||||
buf.WriteByte(byte(CmdHTTP)) // Command
|
||||
buf.WriteString("POST\n") // Method
|
||||
buf.WriteString("/users\n") // Path
|
||||
bt, err := json.Marshal(u)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
binary.Write(buf, binary.BigEndian, int64(len(bt))) // Body length
|
||||
buf.Write(bt) // Body
|
||||
buf.WriteTo(conn)
|
||||
err = binary.Read(conn, binary.BigEndian, &n) // Status code
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n != 201 {
|
||||
t.Errorf("status code should be 201, found %d", n)
|
||||
}
|
||||
verifyUser(conn, t)
|
||||
}
|
||||
|
||||
func verifyUser(rd io.Reader, t *testing.T) {
|
||||
var l int64
|
||||
err := binary.Read(rd, binary.BigEndian, &l) // Body length
|
||||
|
171
client.go
171
client.go
@ -1,171 +0,0 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type (
|
||||
Client struct {
|
||||
host string
|
||||
port string
|
||||
transport transport
|
||||
socket io.ReadWriteCloser
|
||||
reader *bufio.Reader
|
||||
writer *bufio.Writer
|
||||
httpClient HttpClient
|
||||
pool sync.Pool
|
||||
connected bool
|
||||
}
|
||||
HttpClient interface {
|
||||
Do(*http.Request) (*http.Response, error)
|
||||
}
|
||||
)
|
||||
|
||||
func NewClient(opts ...func(*Client)) (c *Client) {
|
||||
c = &Client{
|
||||
host: "localhost",
|
||||
port: "80",
|
||||
transport: TrnspHTTP,
|
||||
httpClient: &http.Client{},
|
||||
}
|
||||
c.pool.New = func() interface{} {
|
||||
return &Context{
|
||||
Request: &http.Request{
|
||||
URL: new(url.URL),
|
||||
},
|
||||
// Response: new(http.Response),
|
||||
// Socket: &Socket{
|
||||
// Header: SocketHeader{},
|
||||
// },
|
||||
client: true,
|
||||
}
|
||||
}
|
||||
// Set options
|
||||
for _, o := range opts {
|
||||
o(c)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Transport(t transport) func(*Client) {
|
||||
return func(c *Client) {
|
||||
c.transport = t
|
||||
}
|
||||
}
|
||||
|
||||
func Host(h string) func(*Client) {
|
||||
return func(c *Client) {
|
||||
c.host = h
|
||||
}
|
||||
}
|
||||
|
||||
func Port(p string) func(*Client) {
|
||||
return func(c *Client) {
|
||||
c.port = p
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Open(cfg *Config) (err error) {
|
||||
switch c.transport {
|
||||
case TrnspWS:
|
||||
case TrnspTCP:
|
||||
c.socket, err = net.Dial("tcp", net.JoinHostPort(c.host, c.port))
|
||||
if err != nil {
|
||||
return fmt.Errorf("bolt: %v", err)
|
||||
}
|
||||
default:
|
||||
return errors.New("bolt: transport not supported")
|
||||
}
|
||||
|
||||
// Request
|
||||
c.writer = bufio.NewWriter(c.socket)
|
||||
c.reader = bufio.NewReader(c.socket)
|
||||
c.writer.WriteByte(byte(CmdINIT)) // Command
|
||||
var cid uint32 = 98
|
||||
if err = binary.Write(c.writer, binary.BigEndian, cid); err != nil { // Correlation ID
|
||||
log.Println(err)
|
||||
}
|
||||
b, err := json.Marshal(cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("bolt: %v", err)
|
||||
}
|
||||
if err = binary.Write(c.writer, binary.BigEndian, uint16(len(b))); err != nil { // Config length
|
||||
}
|
||||
c.writer.Write(b) // Config
|
||||
c.writer.Flush()
|
||||
|
||||
for {
|
||||
var cid uint32
|
||||
binary.Read(c.reader, binary.BigEndian, &cid) // Correlation ID
|
||||
if err != nil {
|
||||
return fmt.Errorf("bolt: %v", err)
|
||||
}
|
||||
println(cid)
|
||||
break
|
||||
}
|
||||
|
||||
// Response
|
||||
var n uint16
|
||||
err = binary.Read(c.reader, binary.BigEndian, &n) // Status code
|
||||
if err != nil {
|
||||
return fmt.Errorf("bolt: %v", err)
|
||||
}
|
||||
if n != 200 {
|
||||
return fmt.Errorf("bolt: status=%d", n)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) Auth() {
|
||||
}
|
||||
|
||||
func (c *Client) Connect(path string) {
|
||||
}
|
||||
|
||||
func (c *Client) Delete() {
|
||||
}
|
||||
|
||||
func (c *Client) Get(path string, hdr Header, hl HandlerFunc) error {
|
||||
return c.Request("GET", path, hdr, hl)
|
||||
}
|
||||
|
||||
func (c *Client) Request(method, path string, hd Header, hl HandlerFunc) (err error) {
|
||||
ctx := c.pool.Get().(*Context)
|
||||
ctx.Transport = c.transport
|
||||
switch c.transport {
|
||||
case TrnspHTTP:
|
||||
ctx.Request.Method = method
|
||||
// ctx.Request.Header = hd
|
||||
ctx.Request.URL.Scheme = "http"
|
||||
ctx.Request.URL.Host = net.JoinHostPort(c.host, c.port)
|
||||
ctx.Request.URL.Path = path
|
||||
ctx.Response, err = c.httpClient.Do(ctx.Request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// ctx.Header = ctx.Response.Header
|
||||
hl(ctx)
|
||||
case TrnspWS, TrnspTCP:
|
||||
c.writer.WriteByte(byte(CmdHTTP)) // Command
|
||||
c.writer.WriteString(method + "\n") // Method
|
||||
c.writer.WriteString(path + "\n") // Path
|
||||
if method == "POST" || method == "PUT" || method == "PATCH" {
|
||||
// binary.Write(c.writer, binary.BigEndian, uint16(len(b))) // Header length
|
||||
// wt.Write(b) // Header
|
||||
}
|
||||
c.writer.Flush()
|
||||
hl(ctx)
|
||||
}
|
||||
return
|
||||
}
|
102
client_test.go
102
client_test.go
@ -1,102 +0,0 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
httpClient struct{}
|
||||
user struct {
|
||||
Id string
|
||||
Name string
|
||||
}
|
||||
)
|
||||
|
||||
func mockTcpServer(method, path string) (b *Bolt) {
|
||||
b = New()
|
||||
b.Handle(method, path, nil)
|
||||
b.RunTCP(":9999")
|
||||
return
|
||||
}
|
||||
|
||||
func mockTcpReq(status uint16, hd Header, body []byte) (c *Client) {
|
||||
c = NewClient()
|
||||
c.transport = TrnspTCP
|
||||
// c.socket = new(bytes.Buffer)
|
||||
c.socket = os.Stdout
|
||||
// l := int64(len(body))
|
||||
// hd.Set("Content-Length", strconv.FormatInt(l, 10))
|
||||
c.socket.Write(body)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *httpClient) Do(req *http.Request) (res *http.Response, err error) {
|
||||
res = &http.Response{}
|
||||
if req.Method == "GET" {
|
||||
res.StatusCode = 200
|
||||
u := &user{"1", "Joe"}
|
||||
d, _ := json.Marshal(u)
|
||||
res.Body = ioutil.NopCloser(bytes.NewBuffer(d))
|
||||
res.Header = make(http.Header)
|
||||
res.Header.Add("Accept", MIME_JSON)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestClientPost(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClientHttpGet(t *testing.T) {
|
||||
c := NewClient()
|
||||
c.httpClient = &httpClient{}
|
||||
hd := make(Header)
|
||||
// hd.Set("Accept", MIME_JSON)
|
||||
if err := c.Get("/users/1", hd, func(ctx *Context) {
|
||||
u := new(user)
|
||||
ctx.Decode(u)
|
||||
if u.Id != "1" {
|
||||
t.Error()
|
||||
}
|
||||
}); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTCPClient(t *testing.T) {
|
||||
b, addr := startTCPServer()
|
||||
defer b.tcpListener.Close()
|
||||
|
||||
// Open
|
||||
host, port, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c := NewClient(Transport(TrnspTCP), Host(host), Port(port))
|
||||
go func() {
|
||||
err = c.Open(&Config{
|
||||
Format: FmtJSON,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}()
|
||||
time.Sleep(32 * time.Millisecond)
|
||||
|
||||
// Get
|
||||
// b.Get("/users", func(c *Context) {
|
||||
// c.Render(200, FmtJSON, u)
|
||||
// })
|
||||
// err = c.Get("/users", nil, func(c *Context) {
|
||||
// })
|
||||
// time.Sleep(32 * time.Millisecond)
|
||||
// if err != nil {
|
||||
// t.Fatal(err)
|
||||
// }
|
||||
}
|
101
context.go
101
context.go
@ -1,27 +1,22 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type (
|
||||
Context struct {
|
||||
Transport transport
|
||||
Request *http.Request
|
||||
Writer *response
|
||||
Response *http.Response
|
||||
Socket *Socket
|
||||
params Params
|
||||
handlers []HandlerFunc
|
||||
store map[string]interface{}
|
||||
l int // Handlers' length
|
||||
i int // Current handler index
|
||||
client bool
|
||||
Request *http.Request
|
||||
Writer *response
|
||||
Response *http.Response
|
||||
params Params
|
||||
handlers []HandlerFunc
|
||||
store map[string]interface{}
|
||||
l int // Handlers' length
|
||||
i int // Current handler index
|
||||
}
|
||||
store map[string]interface{}
|
||||
)
|
||||
@ -34,17 +29,10 @@ func (c *Context) Param(n string) string {
|
||||
return c.params.Get(n)
|
||||
}
|
||||
|
||||
func (c *Context) Bind(f format, i interface{}) (err error) {
|
||||
var bd io.ReadCloser
|
||||
switch c.Transport {
|
||||
case TrnspHTTP:
|
||||
bd = c.Request.Body
|
||||
case TrnspWS, TrnspTCP:
|
||||
bd = c.Socket.Body
|
||||
}
|
||||
func (c *Context) Bind(f Format, i interface{}) (err error) {
|
||||
switch f {
|
||||
case FmtJSON:
|
||||
dec := json.NewDecoder(bd)
|
||||
dec := json.NewDecoder(c.Request.Body)
|
||||
if err = dec.Decode(i); err != nil {
|
||||
log.Printf("bolt: %s", err)
|
||||
}
|
||||
@ -52,69 +40,20 @@ func (c *Context) Bind(f format, i interface{}) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Context) Decode(i interface{}) (err error) {
|
||||
var rd io.Reader
|
||||
|
||||
switch c.Transport {
|
||||
case TrnspHTTP:
|
||||
rd = c.Request.Body
|
||||
if c.client {
|
||||
rd = c.Response.Body
|
||||
defer rd.(io.Closer).Close()
|
||||
}
|
||||
case TrnspWS, TrnspTCP:
|
||||
var cl int64
|
||||
cl, err = strconv.ParseInt(c.Request.Header.Get(HdrContentLength), 10, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
rd = io.LimitReader(c.Socket.Reader, cl)
|
||||
}
|
||||
|
||||
t := c.Request.Header.Get("Content-Type")
|
||||
if c.client {
|
||||
t = c.Request.Header.Get("Accept")
|
||||
}
|
||||
|
||||
switch t {
|
||||
case MIME_MP:
|
||||
default: // JSON
|
||||
dec := json.NewDecoder(rd)
|
||||
if err = dec.Decode(i); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Streaming?
|
||||
func (c *Context) Encode(f format, i interface{}) (b []byte, err error) {
|
||||
// TODO: return error, streaming?
|
||||
func (c *Context) Render(n int, f Format, i interface{}) (err error) {
|
||||
var body []byte
|
||||
switch f {
|
||||
case FmtJSON:
|
||||
b, err = json.Marshal(i)
|
||||
body, err = json.Marshal(i)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: return error
|
||||
func (c *Context) Render(n int, f format, i interface{}) {
|
||||
bd, err := c.Encode(f, i)
|
||||
if err != nil {
|
||||
log.Printf("bolt: %s", err)
|
||||
}
|
||||
|
||||
switch c.Transport {
|
||||
default:
|
||||
// c.Writer.Header().Set(HEADER_CONTENT_TYPE, MIME_JSON)
|
||||
// c.Writer.WriteHeader(int(n))
|
||||
// c.Writer.Write(body)
|
||||
case TrnspWS, TrnspTCP:
|
||||
binary.Write(c.Socket.Writer, binary.BigEndian, uint16(n)) // Status code
|
||||
binary.Write(c.Socket.Writer, binary.BigEndian, int64(len(bd))) // Body length
|
||||
c.Socket.Writer.Write(bd) // Body
|
||||
c.Socket.Writer.Flush()
|
||||
return fmt.Errorf("bolt: %s", err)
|
||||
}
|
||||
// c.Writer.Header().Set(HEADER_CONTENT_TYPE, MIME_JSON)
|
||||
c.Writer.WriteHeader(n)
|
||||
_, err = c.Writer.Write(body)
|
||||
return
|
||||
}
|
||||
|
||||
// Next executes the next handler in the chain.
|
||||
|
@ -1,24 +0,0 @@
|
||||
# to find out the configuration commands, run: h2o --help
|
||||
|
||||
listen: 8080
|
||||
listen:
|
||||
port: 8081
|
||||
ssl:
|
||||
certificate-file: examples/h2o/server.crt
|
||||
key-file: examples/h2o/server.key
|
||||
hosts:
|
||||
"127.0.0.1.xip.io:8080":
|
||||
paths:
|
||||
/:
|
||||
file.dir: examples/doc_root
|
||||
access-log: /dev/stdout
|
||||
"alternate.127.0.0.1.xip.io:8081":
|
||||
listen:
|
||||
port: 8081
|
||||
ssl:
|
||||
certificate-file: examples/h2o/alternate.crt
|
||||
key-file: examples/h2o/alternate.key
|
||||
paths:
|
||||
/:
|
||||
file.dir: examples/doc_root.alternate
|
||||
access-log: /dev/stdout
|
101
socket.go
101
socket.go
@ -1,101 +0,0 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
)
|
||||
|
||||
type (
|
||||
Socket struct {
|
||||
Transport transport
|
||||
Header Header
|
||||
Body io.ReadCloser
|
||||
config Config
|
||||
conn io.ReadWriteCloser
|
||||
Reader *bufio.Reader
|
||||
Writer *bufio.Writer
|
||||
bolt *Bolt
|
||||
initialized bool
|
||||
}
|
||||
Config struct {
|
||||
Format format `json:"format,omitempty"`
|
||||
}
|
||||
Header map[string]string
|
||||
)
|
||||
|
||||
func (s *Socket) Init() {
|
||||
// Request
|
||||
var cid uint32 // Correlation ID
|
||||
err := binary.Read(s.Reader, binary.BigEndian, &cid)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
var l uint16 // Config length
|
||||
err = binary.Read(s.Reader, binary.BigEndian, &l)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
rd := io.LimitReader(s.Reader, int64(l)) // Config
|
||||
dec := json.NewDecoder(rd)
|
||||
if err = dec.Decode(&s.config); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
// Response
|
||||
if err = binary.Write(s.Writer, binary.BigEndian, cid); err != nil { // Correlation ID
|
||||
log.Println(err)
|
||||
}
|
||||
if err = binary.Write(s.Writer, binary.BigEndian, uint16(200)); err != nil { // Status code
|
||||
log.Println(err)
|
||||
}
|
||||
s.Writer.Flush()
|
||||
s.initialized = true
|
||||
}
|
||||
|
||||
func (s *Socket) Auth() {
|
||||
}
|
||||
|
||||
func (s *Socket) HTTP() {
|
||||
// Method
|
||||
m, err := s.Reader.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
m = m[:len(m)-1]
|
||||
|
||||
// Path
|
||||
p, err := s.Reader.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
p = p[:len(p)-1]
|
||||
|
||||
if m == "POST" || m == "PUT" || m == "PATCH" {
|
||||
var l int64
|
||||
err = binary.Read(s.Reader, binary.BigEndian, &l) // Body length
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
s.Body = ioutil.NopCloser(io.LimitReader(s.Reader, l)) // Body
|
||||
}
|
||||
|
||||
h, c, st := s.bolt.Router.Find(m, p)
|
||||
c.Socket = s
|
||||
c.Transport = s.Transport
|
||||
if h != nil {
|
||||
h(c)
|
||||
} else {
|
||||
if st == NotFound {
|
||||
s.bolt.notFoundHandler(c)
|
||||
} else if st == NotAllowed {
|
||||
s.bolt.methodNotAllowedHandler(c)
|
||||
}
|
||||
}
|
||||
s.bolt.pool.Put(c)
|
||||
}
|
20
utils.go
20
utils.go
@ -1,20 +0,0 @@
|
||||
package bolt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
type nopCloser struct {
|
||||
*bytes.Buffer
|
||||
}
|
||||
|
||||
func (nopCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NopCloser returns a ReadWriteCloser with a no-op Close method wrapping
|
||||
// the provided Buffer.
|
||||
func NopCloser(b *bytes.Buffer) io.ReadWriteCloser {
|
||||
return nopCloser{b}
|
||||
}
|
Loading…
Reference in New Issue
Block a user