mirror of
https://github.com/oarkflow/mq.git
synced 2025-10-06 00:16:49 +08:00
feat: [wip] - Implement html node
This commit is contained in:
@@ -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
12
examples/parse.go
Normal 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
120
utils/form.go
Normal 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()
|
||||||
|
}
|
Reference in New Issue
Block a user