mirror of
https://github.com/adnanh/webhook.git
synced 2025-05-10 23:54:42 +00:00
Move some request parsing into hook package
Trying to simplify hookHandler. No functional changes introduced.
This commit is contained in:
parent
4fadb1171f
commit
22c8a1670b
3 changed files with 125 additions and 69 deletions
|
@ -17,7 +17,6 @@ import (
|
|||
"log"
|
||||
"math"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"os"
|
||||
"reflect"
|
||||
|
@ -48,30 +47,6 @@ const (
|
|||
EnvNamespace string = "HOOK_"
|
||||
)
|
||||
|
||||
// Request represents a webhook request.
|
||||
type Request struct {
|
||||
// The request ID set by the RequestID middleware.
|
||||
ID string
|
||||
|
||||
// The Content-Type of the request.
|
||||
ContentType string
|
||||
|
||||
// The raw request body.
|
||||
Body []byte
|
||||
|
||||
// Headers is a map of the parsed headers.
|
||||
Headers map[string]interface{}
|
||||
|
||||
// Query is a map of the parsed URL query values.
|
||||
Query map[string]interface{}
|
||||
|
||||
// Payload is a map of the parsed payload.
|
||||
Payload map[string]interface{}
|
||||
|
||||
// The underlying HTTP request.
|
||||
RawRequest *http.Request
|
||||
}
|
||||
|
||||
// ParameterNodeError describes an error walking a parameter node.
|
||||
type ParameterNodeError struct {
|
||||
key string
|
||||
|
|
116
internal/hook/request.go
Normal file
116
internal/hook/request.go
Normal file
|
@ -0,0 +1,116 @@
|
|||
package hook
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"unicode"
|
||||
|
||||
"github.com/clbanning/mxj"
|
||||
)
|
||||
|
||||
// Request represents a webhook request.
|
||||
type Request struct {
|
||||
// The request ID set by the RequestID middleware.
|
||||
ID string
|
||||
|
||||
// The Content-Type of the request.
|
||||
ContentType string
|
||||
|
||||
// The raw request body.
|
||||
Body []byte
|
||||
|
||||
// Headers is a map of the parsed headers.
|
||||
Headers map[string]interface{}
|
||||
|
||||
// Query is a map of the parsed URL query values.
|
||||
Query map[string]interface{}
|
||||
|
||||
// Payload is a map of the parsed payload.
|
||||
Payload map[string]interface{}
|
||||
|
||||
// The underlying HTTP request.
|
||||
RawRequest *http.Request
|
||||
}
|
||||
|
||||
func (r *Request) ParseJSONPayload() error {
|
||||
decoder := json.NewDecoder(bytes.NewReader(r.Body))
|
||||
decoder.UseNumber()
|
||||
|
||||
var firstChar byte
|
||||
for i := 0; i < len(r.Body); i++ {
|
||||
if unicode.IsSpace(rune(r.Body[i])) {
|
||||
continue
|
||||
}
|
||||
firstChar = r.Body[i]
|
||||
break
|
||||
}
|
||||
|
||||
if firstChar == byte('[') {
|
||||
var arrayPayload interface{}
|
||||
err := decoder.Decode(&arrayPayload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing JSON array payload %+v", err)
|
||||
}
|
||||
|
||||
r.Payload = make(map[string]interface{}, 1)
|
||||
r.Payload["root"] = arrayPayload
|
||||
} else {
|
||||
err := decoder.Decode(&r.Payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing JSON payload %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Request) ParseHeaders(headers map[string][]string) {
|
||||
r.Headers = make(map[string]interface{}, len(headers))
|
||||
|
||||
for k, v := range headers {
|
||||
if len(v) > 0 {
|
||||
r.Headers[k] = v[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Request) ParseQuery(query map[string][]string) {
|
||||
r.Query = make(map[string]interface{}, len(query))
|
||||
|
||||
for k, v := range query {
|
||||
if len(v) > 0 {
|
||||
r.Query[k] = v[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Request) ParseFormPayload() error {
|
||||
fd, err := url.ParseQuery(string(r.Body))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing form payload %+v", err)
|
||||
}
|
||||
|
||||
r.Payload = make(map[string]interface{}, len(fd))
|
||||
|
||||
for k, v := range fd {
|
||||
if len(v) > 0 {
|
||||
r.Payload[k] = v[0]
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Request) ParseXMLPayload() error {
|
||||
var err error
|
||||
|
||||
r.Payload, err = mxj.NewMapXmlReader(bytes.NewReader(r.Body))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing XML payload: %+v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
53
webhook.go
53
webhook.go
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
|
@ -10,19 +9,16 @@ import (
|
|||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/adnanh/webhook/internal/hook"
|
||||
"github.com/adnanh/webhook/internal/middleware"
|
||||
"github.com/adnanh/webhook/internal/pidfile"
|
||||
|
||||
"github.com/clbanning/mxj"
|
||||
chimiddleware "github.com/go-chi/chi/middleware"
|
||||
"github.com/gorilla/mux"
|
||||
fsnotify "gopkg.in/fsnotify.v1"
|
||||
|
@ -373,57 +369,26 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
// parse headers
|
||||
req.Headers = valuesToMap(r.Header)
|
||||
|
||||
// parse query variables
|
||||
req.Query = valuesToMap(r.URL.Query())
|
||||
|
||||
// parse body
|
||||
// var payload map[string]interface{}
|
||||
req.ParseHeaders(r.Header)
|
||||
req.ParseQuery(r.URL.Query())
|
||||
|
||||
switch {
|
||||
case strings.Contains(req.ContentType, "json"):
|
||||
decoder := json.NewDecoder(bytes.NewReader(req.Body))
|
||||
decoder.UseNumber()
|
||||
|
||||
var firstChar byte
|
||||
for i := 0; i < len(req.Body); i++ {
|
||||
if unicode.IsSpace(rune(req.Body[i])) {
|
||||
continue
|
||||
}
|
||||
firstChar = req.Body[i]
|
||||
break
|
||||
}
|
||||
|
||||
if firstChar == byte('[') {
|
||||
var arrayPayload interface{}
|
||||
err := decoder.Decode(&arrayPayload)
|
||||
if err != nil {
|
||||
log.Printf("[%s] error parsing JSON array payload %+v\n", req.ID, err)
|
||||
}
|
||||
|
||||
req.Payload = make(map[string]interface{}, 1)
|
||||
req.Payload["root"] = arrayPayload
|
||||
} else {
|
||||
err := decoder.Decode(&req.Payload)
|
||||
if err != nil {
|
||||
log.Printf("[%s] error parsing JSON payload %+v\n", req.ID, err)
|
||||
}
|
||||
err = req.ParseJSONPayload()
|
||||
if err != nil {
|
||||
log.Printf("[%s] %s", req.ID, err)
|
||||
}
|
||||
|
||||
case strings.Contains(req.ContentType, "x-www-form-urlencoded"):
|
||||
fd, err := url.ParseQuery(string(req.Body))
|
||||
err = req.ParseFormPayload()
|
||||
if err != nil {
|
||||
log.Printf("[%s] error parsing form payload %+v\n", req.ID, err)
|
||||
} else {
|
||||
req.Payload = valuesToMap(fd)
|
||||
log.Printf("[%s] %s", req.ID, err)
|
||||
}
|
||||
|
||||
case strings.Contains(req.ContentType, "xml"):
|
||||
req.Payload, err = mxj.NewMapXmlReader(bytes.NewReader(req.Body))
|
||||
err = req.ParseXMLPayload()
|
||||
if err != nil {
|
||||
log.Printf("[%s] error parsing XML payload: %+v\n", req.ID, err)
|
||||
log.Printf("[%s] %s", req.ID, err)
|
||||
}
|
||||
|
||||
case isMultipart:
|
||||
|
|
Loading…
Add table
Reference in a new issue