bettercap/modules/http_proxy_js_response.go
2018-03-21 23:52:47 +10:00

133 lines
2.5 KiB
Go

package modules
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"github.com/elazarl/goproxy"
)
type JSResponse struct {
Status int
ContentType string
Headers []JSHeader
Body string
refHash string
resp *http.Response
bodyRead bool
}
func NewJSResponse(res *http.Response) *JSResponse {
cType := ""
headers := make([]JSHeader, 0)
code := 200
if res != nil {
code = res.StatusCode
for name, values := range res.Header {
for _, value := range values {
headers = append(headers, JSHeader{name, value})
if name == "Content-Type" {
cType = value
}
}
}
}
resp := &JSResponse{
Status: code,
ContentType: cType,
Headers: headers,
resp: res,
bodyRead: false,
}
resp.UpdateHash()
return resp
}
func (j *JSResponse) NewHash() string {
hash := fmt.Sprintf("%d.%s", j.Status, j.ContentType)
for _, h := range j.Headers {
hash += fmt.Sprintf(".%s-%s", h.Name, h.Value)
}
return hash
}
func (j *JSResponse) UpdateHash() {
j.refHash = j.NewHash()
}
func (j *JSResponse) WasModified() bool {
// body was read
if j.bodyRead == true {
return true
}
// check if any of the fields has been changed
newHash := j.NewHash()
if newHash != j.refHash {
return true
}
return false
}
func (j *JSResponse) GetHeader(name, deflt string) string {
name = strings.ToLower(name)
for _, h := range j.Headers {
if name == strings.ToLower(h.Name) {
return h.Value
}
}
return deflt
}
func (j *JSResponse) SetHeader(name, value string) {
name = strings.ToLower(name)
for i, h := range j.Headers {
if name == strings.ToLower(h.Name) {
j.Headers[i].Value = value
return
}
}
j.Headers = append(j.Headers, JSHeader{name, value})
}
func (j *JSResponse) RemoveHeader(name string) {
name = strings.ToLower(name)
for i, h := range j.Headers {
if name == strings.ToLower(h.Name) {
j.Headers = append(j.Headers[:i], j.Headers[i+1:]...)
}
}
}
func (j *JSResponse) ToResponse(req *http.Request) (resp *http.Response) {
resp = goproxy.NewResponse(req, j.ContentType, j.Status, j.Body)
if len(j.Headers) > 0 {
for _, h := range j.Headers {
resp.Header.Add(h.Name, h.Value)
}
}
return
}
func (j *JSResponse) ReadBody() string {
defer j.resp.Body.Close()
raw, err := ioutil.ReadAll(j.resp.Body)
if err != nil {
return ""
}
j.Body = string(raw)
j.bodyRead = true
// reset the response body to the original unread state
j.resp.Body = ioutil.NopCloser(bytes.NewBuffer(raw))
return j.Body
}