fcgx
Reading Responses
Reading Responses
fcgx returns standard Go *http.Response objects, with helper functions for common operations.
Response Structure
resp, err := client.Get(ctx, params)
if err != nil {
return err
}
defer resp.Body.Close()
// Access response properties
fmt.Println("Status:", resp.Status)
fmt.Println("Status Code:", resp.StatusCode)
fmt.Println("Content-Type:", resp.Header.Get("Content-Type"))
Reading Raw Body
Use ReadBody() to get the response body as bytes:
resp, err := client.Get(ctx, params)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := fcgx.ReadBody(resp)
if err != nil {
return err
}
fmt.Println(string(body))
ReadBody() automatically:
- Reads the entire response body
- Strips HTTP headers if present in the body
- Closes the response body
Reading JSON
Use ReadJSON() to unmarshal JSON responses:
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
resp, err := client.Get(ctx, params)
if err != nil {
return err
}
defer resp.Body.Close()
var user User
if err := fcgx.ReadJSON(resp, &user); err != nil {
return err
}
fmt.Printf("User: %s (%s)\n", user.Name, user.Email)
JSON Maps
For dynamic JSON structures:
var data map[string]interface{}
if err := fcgx.ReadJSON(resp, &data); err != nil {
return err
}
fmt.Printf("Pool: %v\n", data["pool"])
PHP-FPM Status Example
type FPMStatus struct {
Pool string `json:"pool"`
ProcessManager string `json:"process manager"`
StartTime int64 `json:"start time"`
StartSince int `json:"start since"`
AcceptedConn int `json:"accepted conn"`
ListenQueue int `json:"listen queue"`
MaxListenQueue int `json:"max listen queue"`
ListenQueueLen int `json:"listen queue len"`
IdleProcesses int `json:"idle processes"`
ActiveProcesses int `json:"active processes"`
TotalProcesses int `json:"total processes"`
MaxActiveProcesses int `json:"max active processes"`
MaxChildrenReached int `json:"max children reached"`
SlowRequests int `json:"slow requests"`
}
params := map[string]string{
"SCRIPT_NAME": "/status",
"SCRIPT_FILENAME": "/status",
"QUERY_STRING": "json",
}
resp, err := client.Get(ctx, params)
if err != nil {
return err
}
defer resp.Body.Close()
var status FPMStatus
if err := fcgx.ReadJSON(resp, &status); err != nil {
return err
}
fmt.Printf("Pool: %s\n", status.Pool)
fmt.Printf("Active: %d / Total: %d\n", status.ActiveProcesses, status.TotalProcesses)
Manual Body Reading
For streaming or custom processing:
import "io"
resp, err := client.Get(ctx, params)
if err != nil {
return err
}
defer resp.Body.Close()
// Read in chunks
buf := make([]byte, 1024)
for {
n, err := resp.Body.Read(buf)
if n > 0 {
// Process chunk
fmt.Print(string(buf[:n]))
}
if err == io.EOF {
break
}
if err != nil {
return err
}
}
Checking Status Codes
resp, err := client.Get(ctx, params)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := fcgx.ReadBody(resp)
return fmt.Errorf("unexpected status %d: %s", resp.StatusCode, body)
}
Next Steps
- Error Handling - Handle errors gracefully
- Configuration - Customize timeouts