package phpfpm import ( "errors" "io" "net" "strconv" "strings" "time" ) // Create an fcgi client func newFcgiClient(timeout time.Duration, h string, args ...interface{}) (*conn, error) { var con net.Conn if len(args) != 1 { return nil, errors.New("fcgi: not enough params") } var err error switch args[0].(type) { case int: addr := h + ":" + strconv.FormatInt(int64(args[0].(int)), 10) if timeout == 0 { con, err = net.Dial("tcp", addr) } else { con, err = net.DialTimeout("tcp", addr, timeout) } case string: laddr := net.UnixAddr{Name: args[0].(string), Net: h} con, err = net.DialUnix(h, nil, &laddr) default: return nil, errors.New("fcgi: we only accept int (port) or string (socket) params") } if err != nil { return nil, err } if timeout != 0 { if err := con.SetDeadline(time.Now().Add(timeout)); err != nil { return nil, err } } return &conn{rwc: con}, nil } func (c *conn) request(env map[string]string, requestData string) (retout, reterr []byte, err error) { defer c.rwc.Close() var reqID uint16 = 1 err = c.writeBeginRequest(reqID, uint16(roleResponder), 0) if err != nil { return nil, nil, err } err = c.writePairs(typeParams, reqID, env) if err != nil { return nil, nil, err } if len(requestData) > 0 { if err := c.writeRecord(typeStdin, reqID, []byte(requestData)); err != nil { return nil, nil, err } } rec := &record{} var err1 error // receive until EOF or FCGI_END_REQUEST READ_LOOP: for { err1 = rec.read(c.rwc) if err1 != nil && strings.Contains(err1.Error(), "use of closed network connection") { if !errors.Is(err1, io.EOF) { err = err1 } break } if err1 != nil && strings.Contains(err1.Error(), "i/o timeout") { if !errors.Is(err1, io.EOF) { err = err1 } break } switch rec.h.Type { case typeStdout: retout = append(retout, rec.content()...) case typeStderr: reterr = append(reterr, rec.content()...) case typeEndRequest: fallthrough default: break READ_LOOP } } return retout, reterr, err }