[wip] server
Signed-off-by: Anton Nesterov <anton@demiurg.io>
This commit is contained in:
parent
476afeac50
commit
8fd9a369d1
|
@ -15,3 +15,8 @@ type Dialect interface {
|
||||||
GetColumnName(key string) string
|
GetColumnName(key string) string
|
||||||
NormalizeValue(interface{}) interface{}
|
NormalizeValue(interface{}) interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var DIALECTS = map[string]Dialect{
|
||||||
|
"sqlite3": SQLite{},
|
||||||
|
"sqlite": SQLite{},
|
||||||
|
}
|
||||||
|
|
|
@ -26,11 +26,17 @@ type Request struct {
|
||||||
var allowedMethods = strings.Split(builder.BUILDER_CLIENT_METHODS, "|")
|
var allowedMethods = strings.Split(builder.BUILDER_CLIENT_METHODS, "|")
|
||||||
|
|
||||||
func (q *Request) Parse(dialect adapter.Dialect) (adapter.Query, error) {
|
func (q *Request) Parse(dialect adapter.Dialect) (adapter.Query, error) {
|
||||||
|
if q.Db == "" {
|
||||||
|
return adapter.Query{}, fmt.Errorf("Request format: db url is required")
|
||||||
|
}
|
||||||
|
if len(q.Commands) == 0 {
|
||||||
|
return adapter.Query{}, fmt.Errorf("Request format: commands are required")
|
||||||
|
}
|
||||||
b := builder.New(dialect)
|
b := builder.New(dialect)
|
||||||
for _, cmd := range q.Commands {
|
for _, cmd := range q.Commands {
|
||||||
if !slices.Contains(allowedMethods, cmd.Method) {
|
if !slices.Contains(allowedMethods, cmd.Method) {
|
||||||
return adapter.Query{}, fmt.Errorf(
|
return adapter.Query{}, fmt.Errorf(
|
||||||
"method %s is not allowed, awailable methods are %v",
|
"method %s is not allowed, available methods are %v",
|
||||||
cmd.Method,
|
cmd.Method,
|
||||||
allowedMethods,
|
allowedMethods,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,3 +1,25 @@
|
||||||
module l12.xyz/dal/server
|
module l12.xyz/dal/server
|
||||||
|
|
||||||
go 1.22.6
|
go 1.22.6
|
||||||
|
|
||||||
|
replace l12.xyz/dal/filters v0.0.0 => ../filters
|
||||||
|
|
||||||
|
replace l12.xyz/dal/builder v0.0.0 => ../builder
|
||||||
|
|
||||||
|
replace l12.xyz/dal/adapter v0.0.0 => ../adapter
|
||||||
|
|
||||||
|
replace l12.xyz/dal/utils v0.0.0 => ../utils
|
||||||
|
|
||||||
|
require l12.xyz/dal/proto v0.0.0
|
||||||
|
|
||||||
|
replace l12.xyz/dal/proto v0.0.0 => ../proto
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
github.com/tinylib/msgp v1.2.0 // indirect
|
||||||
|
l12.xyz/dal/adapter v0.0.0 // indirect
|
||||||
|
l12.xyz/dal/builder v0.0.0 // indirect
|
||||||
|
l12.xyz/dal/filters v0.0.0 // indirect
|
||||||
|
l12.xyz/dal/utils v0.0.0 // indirect
|
||||||
|
)
|
||||||
|
|
6
pkg/server/go.sum
Normal file
6
pkg/server/go.sum
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986 h1:jYi87L8j62qkXzaYHAQAhEapgukhenIMZRBKTNRLHJ4=
|
||||||
|
github.com/philhofer/fwd v1.1.3-0.20240612014219-fbbf4953d986/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/tinylib/msgp v1.2.0 h1:0uKB/662twsVBpYUPbokj4sTSKhWFKB7LopO2kWK8lY=
|
||||||
|
github.com/tinylib/msgp v1.2.0/go.mod h1:2vIGs3lcUo8izAATNobrCHevYZC/LMsJtw4JPiYPHro=
|
55
pkg/server/handler.go
Normal file
55
pkg/server/handler.go
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"l12.xyz/dal/adapter"
|
||||||
|
"l12.xyz/dal/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func QueryHandler(db adapter.DBAdapter) http.Handler {
|
||||||
|
dialect, ok := adapter.DIALECTS[db.Type]
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Errorf("dialect %s not found", db.Type))
|
||||||
|
}
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
bodyReader, err := r.GetBody()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := io.ReadAll(bodyReader)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := proto.Request{}
|
||||||
|
req.UnmarshalMsg(body)
|
||||||
|
|
||||||
|
query, err := req.Parse(dialect)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(query, "QueryHandler")
|
||||||
|
rows, err := db.Query(query)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/x-msgpack")
|
||||||
|
defer rows.Close()
|
||||||
|
for rows.Next() {
|
||||||
|
row := []byte{}
|
||||||
|
rows.Scan(row)
|
||||||
|
w.Write(row)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
27
pkg/server/handler_test.go
Normal file
27
pkg/server/handler_test.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"l12.xyz/dal/adapter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestQueryHandler(t *testing.T) {
|
||||||
|
body := []byte(`{
|
||||||
|
"something": "wrong",
|
||||||
|
}`)
|
||||||
|
req, err := http.NewRequest("POST", "/", bytes.NewBuffer(body))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
handler := QueryHandler(adapter.DBAdapter{
|
||||||
|
Type: "sqlite3",
|
||||||
|
})
|
||||||
|
handler.ServeHTTP(rr, req)
|
||||||
|
fmt.Println(rr.Code == 400)
|
||||||
|
}
|
Loading…
Reference in a new issue