func (self *Balanser) Request(w http.ResponseWriter, r *http.Request) ([]error, error) { if r.Method != "GET" { return nil, util.ClientError(errors.New("Can only process GET requests!")) } url := *r.URL url.Scheme = "http" var resErrors []error = nil failed := map[string]struct{}{} for { if len(failed) == self.count { return resErrors, errors.New("All backends are broken!") } backend, err := self.router.Choose() if err != nil { return resErrors, err } if _, ok := failed[backend]; ok { continue } url.Host = backend nreq, err := http.NewRequest("GET", url.String(), r.Body) if err != nil { return resErrors, errors.NewErr(err) } nreq.Header = r.Header resp, err := (&http.Client{}).Do(nreq) if err != nil { failed[backend] = struct{}{} resErrors = append(resErrors, errors.NewErr(err)) continue } defer resp.Body.Close() for k, hs := range resp.Header { for _, val := range hs { w.Header().Add(k, val) } } w.WriteHeader(resp.StatusCode) _, err = io.Copy(w, resp.Body) return resErrors, errors.NewErr(err) } }
func GetParam(r *http.Request, name string) (string, error) { sval, ok := r.Form[name] if !ok || len(sval) != 1 { return "", errors.New("No " + name + " in request params!") } return sval[0], nil }
func NewChooser(name string, backends []string) (chooser.BackendChooser, error) { if name == "random" { return chooser.NewRandomChooser(backends), nil } if name == "roundrobin" { return chooser.NewRoundRobinChooser(backends), nil } return nil, errors.New("Unknown name: \"" + name + "\".") }
func GetParamOr(r *http.Request, name string, def string) (string, error) { sval, ok := r.Form[name] if !ok { return def, nil } if len(sval) != 1 { return "", errors.New("Too many " + name + " in request params!") } return sval[0], nil }
func (self *Balanser) Request(client *net.TCPConn) error { defer client.Close() failed := map[string]struct{}{} for { if len(failed) == self.count { return errors.New("All backends are broken!") } backend, err := self.router.Choose() if err != nil { return err } if _, ok := failed[backend]; ok { continue } conn, err := net.Dial("tcp", backend) if err != nil { failed[backend] = struct{}{} continue } server := conn.(*net.TCPConn) clientClosed := make(chan error, 1) go func() { _, err := io.Copy(server, client) clientClosed <- errors.NewErr(err) }() serverClosed := make(chan error, 1) go func() { _, err := io.Copy(client, server) serverClosed <- errors.NewErr(err) }() select { case err = <-clientClosed: server.SetLinger(0) server.CloseRead() case err = <-serverClosed: } return err } }
func (self *FileReader) ReadByte() (byte, error) { n, err := self.file.Read(self.buf) if err == io.EOF { return 0, err } if err != nil { return 0, errors.NewErr(err) } if n != 1 { return 0, errors.New("Read " + strconv.Itoa(n) + " bytes, instead of one!") } self.offset += 1 return self.buf[0], nil }
func (self *FileReader) ReadLenval() (uint64, []byte, error) { start := self.offset l, err := binary.ReadUvarint(self) diff := self.offset - start if err == io.EOF { return diff, nil, err } if err != nil { return diff, nil, errors.NewErr(err) } res := make([]byte, l) n, err := self.Read(res) diff += uint64(n) if err != nil { return diff, nil, err } if n != int(l) { return diff, nil, errors.New("Read " + strconv.Itoa(n) + " bytes, instead of " + strconv.Itoa(int(l)) + "!") } return diff, res, nil }