1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00
Files
DankMaterialShell/core/pkg/ipp/adapter-http.go
2025-12-01 12:23:52 -05:00

133 lines
2.6 KiB
Go

package ipp
import (
"bytes"
"crypto/tls"
"fmt"
"io"
"net"
"net/http"
"strconv"
"time"
)
type HttpAdapter struct {
host string
port int
username string
password string
useTLS bool
client *http.Client
}
func NewHttpAdapter(host string, port int, username, password string, useTLS bool) *HttpAdapter {
httpClient := http.Client{
Timeout: 0,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
ResponseHeaderTimeout: 90 * time.Second,
IdleConnTimeout: 120 * time.Second,
},
}
return &HttpAdapter{
host: host,
port: port,
username: username,
password: password,
useTLS: useTLS,
client: &httpClient,
}
}
func (h *HttpAdapter) SendRequest(url string, req *Request, additionalResponseData io.Writer) (*Response, error) {
payload, err := req.Encode()
if err != nil {
return nil, err
}
size := len(payload)
var body io.Reader
if req.File != nil && req.FileSize != -1 {
size += req.FileSize
body = io.MultiReader(bytes.NewBuffer(payload), req.File)
} else {
body = bytes.NewBuffer(payload)
}
httpReq, err := http.NewRequest("POST", url, body)
if err != nil {
return nil, err
}
httpReq.Header.Set("Content-Length", strconv.Itoa(size))
httpReq.Header.Set("Content-Type", ContentTypeIPP)
if h.username != "" && h.password != "" {
httpReq.SetBasicAuth(h.username, h.password)
}
httpResp, err := h.client.Do(httpReq)
if err != nil {
return nil, err
}
defer httpResp.Body.Close()
if httpResp.StatusCode != 200 {
return nil, HTTPError{
Code: httpResp.StatusCode,
}
}
// buffer response to avoid read issues
buf := new(bytes.Buffer)
if httpResp.ContentLength > 0 {
buf.Grow(int(httpResp.ContentLength))
}
if _, err := io.Copy(buf, httpResp.Body); err != nil {
return nil, fmt.Errorf("unable to buffer response: %w", err)
}
ippResp, err := NewResponseDecoder(buf).Decode(additionalResponseData)
if err != nil {
return nil, err
}
if err = ippResp.CheckForErrors(); err != nil {
return nil, fmt.Errorf("received error IPP response: %w", err)
}
return ippResp, nil
}
func (h *HttpAdapter) GetHttpUri(namespace string, object any) string {
proto := "http"
if h.useTLS {
proto = "https"
}
uri := fmt.Sprintf("%s://%s:%d", proto, h.host, h.port)
if namespace != "" {
uri = fmt.Sprintf("%s/%s", uri, namespace)
}
if object != nil {
uri = fmt.Sprintf("%s/%v", uri, object)
}
return uri
}
func (h *HttpAdapter) TestConnection() error {
conn, err := net.Dial("tcp", net.JoinHostPort(h.host, fmt.Sprintf("%d", h.port)))
if err != nil {
return err
}
conn.Close()
return nil
}