58 lines
1.5 KiB
Go
58 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
const maxBodySample = 4096
|
|
|
|
// inspect sends the request metadata + body sample to the WAF for inspection.
|
|
// Returns the WAF's HTTP status code or an error if unreachable.
|
|
func inspect(r *http.Request) (int, error) {
|
|
cfg := getConfig()
|
|
|
|
// Sample body.
|
|
var bodySample []byte
|
|
if r.Body != nil {
|
|
bodySample = make([]byte, maxBodySample)
|
|
n, _ := io.ReadFull(r.Body, bodySample)
|
|
bodySample = bodySample[:n]
|
|
// Restore body so downstream can read it.
|
|
r.Body = io.NopCloser(io.MultiReader(bytes.NewReader(bodySample), r.Body))
|
|
}
|
|
|
|
// Build inspection payload with the original URI.
|
|
originalPath := r.Header.Get("X-Zoraxy-Uri")
|
|
if originalPath == "" {
|
|
originalPath = r.URL.String()
|
|
}
|
|
payload, err := json.Marshal(map[string]interface{}{
|
|
"method": r.Method,
|
|
"url": originalPath,
|
|
"host": r.Host,
|
|
"remote_addr": r.RemoteAddr,
|
|
"content_type": r.Header.Get("Content-Type"),
|
|
"content_length": r.ContentLength,
|
|
"headers": r.Header,
|
|
"body_sample": bodySample,
|
|
})
|
|
if err != nil {
|
|
return 0, fmt.Errorf("marshal: %w", err)
|
|
}
|
|
|
|
client := &http.Client{Timeout: time.Duration(cfg.TimeoutMs) * time.Millisecond}
|
|
resp, err := client.Post(cfg.WAFURL+"/inspect", "application/json", bytes.NewReader(payload))
|
|
if err != nil {
|
|
return 0, fmt.Errorf("unreachable: %w", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
log.Printf("Firewall: %s %s → status %d", r.Method, r.URL.Path, resp.StatusCode)
|
|
return resp.StatusCode, nil
|
|
}
|