136 lines
3.9 KiB
Go
136 lines
3.9 KiB
Go
|
|
package operations
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"service-operation/types"
|
|
)
|
|
|
|
type HTTPOperation struct {
|
|
timeout time.Duration
|
|
client *http.Client
|
|
}
|
|
|
|
func NewHTTPOperation(timeout time.Duration) *HTTPOperation {
|
|
return &HTTPOperation{
|
|
timeout: timeout,
|
|
client: &http.Client{
|
|
Timeout: timeout,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (h *HTTPOperation) Execute(url, method string) (*types.OperationResult, error) {
|
|
result := &types.OperationResult{
|
|
Type: types.OperationHTTP,
|
|
StartTime: time.Now(),
|
|
HTTPMethod: method,
|
|
}
|
|
|
|
// Default to GET if no method specified
|
|
if method == "" {
|
|
method = "GET"
|
|
result.HTTPMethod = "GET"
|
|
}
|
|
|
|
// Ensure URL has protocol
|
|
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
|
|
url = "https://" + url
|
|
}
|
|
|
|
start := time.Now()
|
|
|
|
req, err := http.NewRequest(method, url, nil)
|
|
if err != nil {
|
|
result.Error = fmt.Sprintf("Failed to create request: %v", err)
|
|
result.Success = false
|
|
result.EndTime = time.Now()
|
|
return result, nil
|
|
}
|
|
|
|
// Set a user agent
|
|
req.Header.Set("User-Agent", "ServiceOperation/1.0")
|
|
|
|
resp, err := h.client.Do(req)
|
|
|
|
result.ResponseTime = time.Since(start)
|
|
result.EndTime = time.Now()
|
|
|
|
if err != nil {
|
|
// More detailed error messages
|
|
if strings.Contains(err.Error(), "timeout") {
|
|
result.Error = fmt.Sprintf("🕐 Request timeout after %.2fs - Server did not respond within the expected time", h.timeout.Seconds())
|
|
} else if strings.Contains(err.Error(), "connection refused") {
|
|
result.Error = "🚫 Connection refused - Server is not accepting connections on this port"
|
|
} else if strings.Contains(err.Error(), "no such host") {
|
|
result.Error = "🌐 DNS resolution failed - Host not found"
|
|
} else if strings.Contains(err.Error(), "certificate") {
|
|
result.Error = "🔒 SSL/TLS certificate error - Certificate verification failed"
|
|
} else {
|
|
result.Error = fmt.Sprintf("🔌 Connection error: %v", err)
|
|
}
|
|
result.Success = false
|
|
return result, nil
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
result.HTTPStatusCode = resp.StatusCode
|
|
result.ContentLength = resp.ContentLength
|
|
result.Success = resp.StatusCode >= 200 && resp.StatusCode < 400
|
|
|
|
// Capture important headers
|
|
result.HTTPHeaders = make(map[string]string)
|
|
for key, values := range resp.Header {
|
|
if len(values) > 0 {
|
|
switch strings.ToLower(key) {
|
|
case "content-type", "server", "cache-control", "content-encoding", "x-powered-by":
|
|
result.HTTPHeaders[key] = values[0]
|
|
}
|
|
}
|
|
}
|
|
|
|
// Read response body for keyword checking and additional details
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err == nil && len(body) > 0 {
|
|
result.ResponseBody = string(body)
|
|
// Update content length if not set by server
|
|
if result.ContentLength <= 0 {
|
|
result.ContentLength = int64(len(body))
|
|
}
|
|
}
|
|
|
|
// Create detailed status message with emoji
|
|
if !result.Success {
|
|
switch {
|
|
case resp.StatusCode >= 500:
|
|
result.Error = fmt.Sprintf("🔥 Server Error (HTTP %d): %s - The server encountered an internal error", resp.StatusCode, resp.Status)
|
|
case resp.StatusCode >= 400:
|
|
result.Error = fmt.Sprintf("❌ Client Error (HTTP %d): %s - The request was invalid or unauthorized", resp.StatusCode, resp.Status)
|
|
case resp.StatusCode >= 300:
|
|
result.Error = fmt.Sprintf("↩️ Redirect (HTTP %d): %s - Resource has moved", resp.StatusCode, resp.Status)
|
|
default:
|
|
result.Error = fmt.Sprintf("⚠️ Unexpected Status (HTTP %d): %s", resp.StatusCode, resp.Status)
|
|
}
|
|
} else {
|
|
// Success message with emoji
|
|
switch resp.StatusCode {
|
|
case 200:
|
|
result.Error = "✅ OK - Request successful"
|
|
case 201:
|
|
result.Error = "🆕 Created - Resource created successfully"
|
|
case 202:
|
|
result.Error = "⏳ Accepted - Request accepted for processing"
|
|
case 204:
|
|
result.Error = "📭 No Content - Request successful, no content returned"
|
|
default:
|
|
result.Error = fmt.Sprintf("✅ Success (HTTP %d): %s", resp.StatusCode, resp.Status)
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
} |