Files
2026-04-24 15:36:53 -03:00

122 lines
3.2 KiB
Go

package handlers
import (
"docker-manager/docker"
"encoding/json"
"fmt"
"io"
"net/http"
)
func ListContainersHandler(w http.ResponseWriter, r *http.Request, client *docker.Client) {
var containers []map[string]interface{}
if err := client.GetJSON("/containers/json?all=true", &containers); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
if containers == nil {
w.Write([]byte("[]"))
} else {
json.NewEncoder(w).Encode(containers)
}
}
func StartContainerHandler(w http.ResponseWriter, r *http.Request, client *docker.Client, id string) {
if resp, err := client.Do("POST", fmt.Sprintf("/containers/%s/start", id), nil); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
} else {
defer resp.Body.Close()
w.WriteHeader(resp.StatusCode)
}
}
func StopContainerHandler(w http.ResponseWriter, r *http.Request, client *docker.Client, id string) {
if resp, err := client.Do("POST", fmt.Sprintf("/containers/%s/stop", id), nil); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
} else {
defer resp.Body.Close()
w.WriteHeader(resp.StatusCode)
}
}
func RestartContainerHandler(w http.ResponseWriter, r *http.Request, client *docker.Client, id string) {
if resp, err := client.Do("POST", fmt.Sprintf("/containers/%s/restart", id), nil); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
} else {
defer resp.Body.Close()
w.WriteHeader(resp.StatusCode)
}
}
func RemoveContainerHandler(w http.ResponseWriter, r *http.Request, client *docker.Client, id string) {
if resp, err := client.Do("DELETE", fmt.Sprintf("/containers/%s?force=true", id), nil); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
} else {
defer resp.Body.Close()
w.WriteHeader(resp.StatusCode)
}
}
func GetLogsHandler(w http.ResponseWriter, r *http.Request, client *docker.Client, id string) {
body, err := client.DoStream("GET", fmt.Sprintf("/containers/%s/logs?stdout=true&stderr=true&tail=200", id), nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer body.Close()
// Docker logs returns docker stream format, need to parse it
logs := parseLogs(body)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"logs": logs})
}
// Docker log stream format: [8 bytes header][payload]
// Header: [1 byte stream type][3 bytes padding][4 bytes payload length]
func parseLogs(body io.Reader) string {
var result string
buffer := make([]byte, 4096)
for {
n, err := body.Read(buffer)
if err != nil && err != io.EOF {
break
}
if n == 0 {
break
}
// Parse docker stream format
data := buffer[:n]
for i := 0; i < len(data); {
if i+8 > len(data) {
break
}
// Skip 8-byte header
i += 8
// Read until next header or end
start := i
for i < len(data) && i+8 <= len(data) {
i += 8
if i > len(data) {
i = len(data)
break
}
}
if start < len(data) {
result += string(data[start : len(data)])
i = len(data)
}
}
}
// Fallback: if stream format parsing fails, just return the raw data as text
if result == "" {
return string(buffer)
}
return result
}