mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-28 07:51:47 -05:00
116 lines
2.9 KiB
Go
116 lines
2.9 KiB
Go
package icapclient
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// Client represents the icap client who makes the icap server calls
|
|
type Client struct {
|
|
scktDriver *Driver
|
|
Timeout time.Duration
|
|
}
|
|
|
|
// Do makes does everything required to make a call to the ICAP server
|
|
func (c *Client) Do(req *Request) (*Response, error) {
|
|
|
|
if c.scktDriver == nil { // create a new socket driver if one wasn't explicitly created
|
|
port, err := strconv.Atoi(req.URL.Port())
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
c.scktDriver = NewDriver(req.URL.Hostname(), port)
|
|
}
|
|
|
|
c.setDefaultTimeouts() // assinging default timeouts if not set already
|
|
|
|
if req.ctx != nil { // connect with the given context if context is set
|
|
if err := c.scktDriver.ConnectWithContext(*req.ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
if err := c.scktDriver.Connect(); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
defer c.scktDriver.Close() // closing the socket connection
|
|
|
|
req.SetDefaultRequestHeaders() // assigning default headers if not set already
|
|
|
|
logDebug("The request headers: ")
|
|
dumpDebug(req.Header)
|
|
|
|
d, err := DumpRequest(req) // getting the byte representation of the ICAP request
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := c.scktDriver.Send(d); err != nil { // sending the entire TCP message of the ICAP client to the server connected
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := c.scktDriver.Receive() // taking the response
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resp.StatusCode == http.StatusContinue && !req.bodyFittedInPreview && req.previewSet { // this block suggests that the ICAP request contained preview body bytes and whole body did not fit in the preview, so the serber responded with 100 Continue and the client is to send the remaining body bytes only
|
|
logDebug("Making request for the rest of the remaining body bytes after preview, as received 100 Continue from the server...")
|
|
return c.DoRemaining(req)
|
|
}
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
// DoRemaining requests an ICAP server with the remaining body bytes which did not fit in the preview in the original request
|
|
func (c *Client) DoRemaining(req *Request) (*Response, error) {
|
|
|
|
data := req.remainingPreviewBytes
|
|
|
|
if !bodyAlreadyChunked(string(data)) { // if the body is not already chunke, then add the basic hexa body bytes notation
|
|
ds := string(data)
|
|
addHexaBodyByteNotations(&ds)
|
|
data = []byte(ds)
|
|
}
|
|
|
|
if err := c.scktDriver.Send(data); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp, err := c.scktDriver.Receive()
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return resp, nil
|
|
}
|
|
|
|
// SetDriver sets a new socket driver with the client
|
|
func (c *Client) SetDriver(d *Driver) {
|
|
c.scktDriver = d
|
|
}
|
|
|
|
func (c *Client) setDefaultTimeouts() {
|
|
if c.Timeout == 0 {
|
|
c.Timeout = defaultTimeout
|
|
}
|
|
|
|
if c.scktDriver.DialerTimeout == 0 {
|
|
c.scktDriver.DialerTimeout = c.Timeout
|
|
}
|
|
|
|
if c.scktDriver.ReadTimeout == 0 {
|
|
c.scktDriver.ReadTimeout = c.Timeout
|
|
}
|
|
|
|
if c.scktDriver.WriteTimeout == 0 {
|
|
c.scktDriver.WriteTimeout = c.Timeout
|
|
}
|
|
}
|