feat: [wip] - Implement html node

This commit is contained in:
sujit
2024-11-24 11:35:38 +05:45
parent 6541c646db
commit 9e334d7768
3 changed files with 139 additions and 54 deletions

View File

@@ -1,12 +1,10 @@
package dag package dag
import ( import (
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"os" "os"
"strings" "strings"
@@ -14,6 +12,7 @@ import (
"github.com/oarkflow/errors" "github.com/oarkflow/errors"
"github.com/oarkflow/mq" "github.com/oarkflow/mq"
"github.com/oarkflow/mq/utils"
"github.com/oarkflow/mq/consts" "github.com/oarkflow/mq/consts"
"github.com/oarkflow/mq/jsonparser" "github.com/oarkflow/mq/jsonparser"
@@ -216,9 +215,12 @@ func parseRequest(c *fiber.Ctx) (context.Context, []byte, error) {
if body == nil { if body == nil {
return ctx, nil, errors.New("empty form body") return ctx, nil, errors.New("empty form body")
} }
formData := ParseFormToMap(body, &userContext.Query) val, err := utils.DecodeForm(body)
if formData != nil { if err != nil {
return ctx, nil, fmt.Errorf("failed to parse form data: %v", formData) return ctx, nil, fmt.Errorf("failed to parse form data: %v", err.Error())
}
for key, v := range val {
userContext.Query[key] = v
} }
result = userContext.Query result = userContext.Query
default: default:
@@ -232,52 +234,3 @@ func parseRequest(c *fiber.Ctx) (context.Context, []byte, error) {
return ctx, bt, nil return ctx, bt, nil
} }
// ParseFormToMap parses form-encoded data into the provided map
func ParseFormToMap(body []byte, data *map[string]any) error {
if data == nil {
return errors.New("data map is nil")
}
if len(body) == 0 {
return errors.New("empty form body")
}
start := 0
for i := 0; i <= len(body); i++ {
if i == len(body) || body[i] == '&' {
if err := processPair(body[start:i], data); err != nil {
return err
}
start = i + 1
}
}
return nil
}
// processPair processes a key-value pair and inserts it into the map
func processPair(pair []byte, data *map[string]any) error {
if len(pair) == 0 {
return nil // Ignore empty pairs
}
eqIndex := bytes.IndexByte(pair, '=')
if eqIndex == -1 {
return errors.New("malformed key-value pair")
}
// Extract key and value
key := pair[:eqIndex]
value := pair[eqIndex+1:]
// Decode key and value (zero-allocation alternatives can replace this)
decodedKey, err := url.QueryUnescape(string(key))
if err != nil {
return err
}
decodedValue, err := url.QueryUnescape(string(value))
if err != nil {
return err
}
// Insert into the map
(*data)[decodedKey] = decodedValue
return nil
}

12
examples/parse.go Normal file
View File

@@ -0,0 +1,12 @@
package main
import (
"fmt"
"github.com/oarkflow/mq/utils"
)
func main() {
queryString := []byte("fields[0][method]=GET&fields[0][path]=/user/:id&fields[0][handlerMsg]=User Profile&fields[1][method]=POST&fields[1][path]=/user/create&fields[1][handlerMsg]=Create User")
fmt.Println(utils.DecodeForm(queryString))
}

120
utils/form.go Normal file
View File

@@ -0,0 +1,120 @@
package utils
import (
"fmt"
"net/url"
"strings"
)
type form struct {
dest map[string]any
raw string
pathCache map[string]int
}
func newForm(raw string) *form {
f := new(form)
f.raw = raw
f.pathCache = make(map[string]int)
return f
}
func (f *form) reset() {
f.dest = make(map[string]any)
}
func (f *form) decode() (map[string]any, error) {
f.reset()
vals := make(map[string]any)
for _, v := range strings.Split(f.raw, "&") {
if v == "" {
continue
}
index := strings.Index(v, "=")
if index > 0 {
key := v[:index]
val := v[index+1:]
f.insertValue(&vals, key, val)
} else {
f.insertValue(&vals, v, "")
}
}
return f.parseArray(vals), nil
}
func (f *form) insertValue(destP *map[string]any, key string, val string) {
key, _ = url.PathUnescape(key)
var path []string
if strings.Contains(key, "[") || strings.Contains(key, "]") {
var current string
for _, c := range key {
switch c {
case '[':
if len(current) > 0 {
path = append(path, current)
current = ""
}
case ']':
path = append(path, current)
current = ""
continue
default:
current += string(c)
}
}
if len(current) > 0 {
path = append(path, current)
}
} else {
path = append(path, key)
}
dest := *destP
for i, k := range path {
if i == len(path)-1 {
break
}
if k == "" {
c := strings.Join(path, ",")
k = fmt.Sprint(f.pathCache[c])
f.pathCache[c] = f.pathCache[c] + 1
}
if _, ok := dest[k].(map[string]any); !ok {
dest[k] = make(map[string]any)
}
dest = dest[k].(map[string]any)
}
p := path[len(path)-1]
if p == "" {
p = fmt.Sprint(len(dest))
}
val, _ = url.QueryUnescape(val)
dest[p] = val
}
func (f *form) parseArrayItem(dest map[string]any) any {
var arr []any
for i := 0; i < len(dest); i++ {
item, ok := dest[fmt.Sprint(i)]
if !ok {
return dest
}
arr = append(arr, item)
}
return arr
}
func (f *form) parseArray(dest map[string]any) map[string]any {
for k, v := range dest {
mv, ok := v.(map[string]any)
if ok {
f.parseArray(mv)
dest[k] = f.parseArrayItem(mv)
}
}
return dest
}
func DecodeForm(src []byte) (map[string]any, error) {
return newForm(FromByte(src)).decode()
}