contentserver/client/client.go
2016-03-09 12:13:39 +01:00

132 lines
3.1 KiB
Go

package client
import (
"encoding/json"
"errors"
"fmt"
"io"
"net"
"strconv"
"github.com/foomo/contentserver/content"
"github.com/foomo/contentserver/requests"
"github.com/foomo/contentserver/responses"
"github.com/foomo/contentserver/server"
)
type serverResponse struct {
Reply interface{}
}
// Client a content server client
type Client struct {
Server string
conn net.Conn
}
func (c *Client) closeConnection() error {
if c.conn != nil {
err := c.conn.Close()
if err != nil {
return err
}
c.conn = nil
}
return nil
}
func (c *Client) getConnection() (conn net.Conn, err error) {
if c.conn == nil {
conn, err := net.Dial("tcp", c.Server)
if err != nil {
return nil, err
}
c.conn = conn
}
return c.conn, nil
}
func (c *Client) call(handler string, request interface{}, response interface{}) error {
jsonBytes, err := json.Marshal(request)
if err != nil {
return fmt.Errorf("could not marshal request : %q", err)
}
conn, err := c.getConnection()
if err != nil {
return fmt.Errorf("can not call server - connection error: %q", err)
}
// write header result will be like handler:2{}
jsonBytes = append([]byte(fmt.Sprintf("%s:%d", handler, len(jsonBytes))), jsonBytes...)
// send request
written := 0
l := len(jsonBytes)
for written < l {
n, err := conn.Write(jsonBytes[written:])
if err != nil {
return fmt.Errorf("failed to send request: %q", err)
}
written += n
}
// read response
responseBytes := []byte{}
buf := make([]byte, 4096)
responseLength := 0
for {
n, err := conn.Read(buf)
if err != nil && err != io.EOF {
c.closeConnection()
return fmt.Errorf("an error occured while reading the response: %q", err)
}
if n == 0 {
break
}
responseBytes = append(responseBytes, buf[0:n]...)
if responseLength == 0 {
for index, byte := range responseBytes {
if byte == 123 {
// opening bracket
responseLength, err = strconv.Atoi(string(responseBytes[0:index]))
if err != nil {
return errors.New("could not read response length: " + err.Error())
}
responseBytes = responseBytes[index:]
break
}
}
}
if responseLength > 0 && len(responseBytes) == responseLength {
break
}
}
// unmarshal response
responseJSONErr := json.Unmarshal(responseBytes, &serverResponse{Reply: response})
if responseJSONErr != nil {
// is it an error ?
remoteErr := responses.Error{}
remoteErrJSONErr := json.Unmarshal(responseBytes, remoteErr)
if remoteErrJSONErr == nil {
return remoteErr
}
return fmt.Errorf("could not unmarshal response : %q %q", remoteErrJSONErr, string(responseBytes))
}
//c.closeConnection()
return nil
}
// Update tell the server to update itself
func (c *Client) Update() (response *responses.Update, err error) {
response = &responses.Update{}
err = c.call(server.HandlerUpdate, &requests.Update{}, response)
return
}
// GetContent request site content
func (c *Client) GetContent(request *requests.Content) (response *content.SiteContent, err error) {
response = &content.SiteContent{}
err = c.call(server.HandlerContent, request, response)
return
}