تحويل أوامر curl إلى كود Go - توليد كود Go net/http جاهز للاستخدام لطلبات API
// Go code will appear here // Example: package main import ( "bytes" "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { url := "https://api.example.com/data" // Create request payload payload := map[string]interface{}{ "name": "test", } jsonData, err := json.Marshal(payload) if err != nil { fmt.Println("Error marshaling JSON:", err) return } // Create request req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData)) if err != nil { fmt.Println("Error creating request:", err) return } // Add headers req.Header.Set("Content-Type", "application/json") // Send request client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() // Read response body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response:", err) return } fmt.Println("Status:", resp.Status) fmt.Println("Response:", string(body)) }
فيما يلي بعض أوامر curl الشائعة التي يمكنك تحويلها إلى كود Go:
curl https://api.example.com/users
curl -X POST -H "Content-Type: application/json" -d '{"name":"John","email":"[email protected]"}' https://api.example.com/users
curl -X PUT -H "Authorization: Bearer token123" -d '{"status":"active"}' https://api.example.com/users/1
curl -X DELETE https://api.example.com/users/1
curl -H "X-API-Key: abc123" -H "Accept: application/json" https://api.example.com/data
توفر حزمة net/http في Go طريقة قوية وفعالة لإجراء طلبات HTTP. فيما يلي بعض أنماط HTTP الشائعة في Go:
package main import ( "bytes" "fmt" "io" "io/ioutil" "mime/multipart" "net/http" "os" "path/filepath" ) func main() { url := "https://api.example.com/upload" // Create a buffer to store the multipart form var requestBody bytes.Buffer multipartWriter := multipart.NewWriter(&requestBody) // Open the file file, err := os.Open("document.pdf") if err != nil { fmt.Println("Error opening file:", err) return } defer file.Close() // Create a form file field fileWriter, err := multipartWriter.CreateFormFile("file", filepath.Base("document.pdf")) if err != nil { fmt.Println("Error creating form file:", err) return } // Copy the file content to the form field _, err = io.Copy(fileWriter, file) if err != nil { fmt.Println("Error copying file to form:", err) return } // Add other form fields if needed multipartWriter.WriteField("description", "Sample document upload") // Close the multipart writer multipartWriter.Close() // Create request req, err := http.NewRequest("POST", url, &requestBody) if err != nil { fmt.Println("Error creating request:", err) return } // Set the content type with the boundary req.Header.Set("Content-Type", multipartWriter.FormDataContentType()) req.Header.Set("Authorization", "Bearer YOUR_TOKEN_HERE") // Send request client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() // Read response body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response:", err) return } fmt.Println("Status:", resp.Status) fmt.Println("Response:", string(body)) }
package main import ( "context" "encoding/json" "fmt" "io/ioutil" "net/http" "time" ) func main() { // Create a context with timeout ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Create request req, err := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil) if err != nil { fmt.Println("Error creating request:", err) return } // Send request client := &http.Client{} resp, err := client.Do(req) // Handle errors if err != nil { if ctx.Err() == context.DeadlineExceeded { fmt.Println("Request timed out") } else { fmt.Println("Error sending request:", err) } return } defer resp.Body.Close() // Check status code if resp.StatusCode != http.StatusOK { fmt.Printf("Server returned non-200 status: %s\n", resp.Status) body, _ := ioutil.ReadAll(resp.Body) fmt.Println("Response body:", string(body)) return } // Read and parse response var data map[string]interface{} body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response:", err) return } err = json.Unmarshal(body, &data) if err != nil { fmt.Println("Error parsing JSON:", err) fmt.Println("Raw response:", string(body)) return } fmt.Println("Successfully received data:", data) }
انسخ أمر curl الخاص بك → الصقه في مربع الإدخال → احصل على كود Go فوراً
// Always check for errors in Go resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() // Check status code if resp.StatusCode != http.StatusOK { fmt.Printf("Server returned non-200 status: %s\n", resp.Status) body, _ := ioutil.ReadAll(resp.Body) fmt.Println("Response body:", string(body)) return }
// Create a context with timeout ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Create request with context req, err := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil) if err != nil { fmt.Println("Error creating request:", err) return } // Send request client := &http.Client{} resp, err := client.Do(req) // Check for timeout if err != nil { if ctx.Err() == context.DeadlineExceeded { fmt.Println("Request timed out") } else { fmt.Println("Error sending request:", err) } return }
ج: بينما curl هي أداة سطر أوامر لإجراء طلبات HTTP، توفر حزمة net/http في Go واجهة برمجة تطبيقات برمجية. يوفر Go كتابة أقوى، ودعم تزامن مدمج، وتكامل أفضل مع كود التطبيق الخاص بك، بينما يتفوق curl في الاختبار السريع المخصص والبرمجة النصية.
ج: يستخدم Go defer resp.Body.Close() لضمان تحرير الموارد بشكل صحيح حتى إذا حدثت أخطاء لاحقاً في الدالة. هذا النمط هو نمط مميز في Go ويمنع تسرب الموارد الذي قد يحدث إذا نسيت إغلاق الجسم في جميع مسارات الكود المحتملة.
ج: بدلاً من استخدام ioutil.ReadAll()
، يمكنك معالجة جسم الاستجابة كتدفق باستخدام io.Copy()
أو بقراءة أجزاء باستخدام مخزن مؤقت. هذا مفيد بشكل خاص للاستجابات الكبيرة حيث يكون تحميل الجسم بأكمله إلى الذاكرة غير فعال.
ج: نعم، وهو أمر موصى به! إنشاء http.Client
واحد وإعادة استخدامه عبر الطلبات يسمح بتجميع الاتصالات ويحسن الأداء. العميل آمن للتزامن ويمكن مشاركته بين goroutines دون الحاجة إلى تزامن إضافي.
ج: توفر حزمة context في Go إلغاء طلب أنيق. قم بإنشاء سياق باستخدام context.WithCancel()
أو context.WithTimeout()
، ثم مرره إلى http.NewRequestWithContext()
. يمكنك إلغاء الطلب في أي وقت عن طريق استدعاء دالة الإلغاء.
ج: لتخطي التحقق من شهادة TLS (مثل علامة -k في curl)، قم بتكوين Transport مخصص في عميل HTTP الخاص بك: client := &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}}
ومع ذلك، يجب استخدام هذا للاختبار فقط، لأنه يتجاوز فحوصات الأمان.
ج: يتبع عميل HTTP في Go إعادة التوجيه تلقائياً (حتى 10 مرات افتراضياً)، مشابهاً لـ curl. لتخصيص هذا السلوك، قم بتعيين دالة CheckRedirect
مخصصة في عميل HTTP الخاص بك للتحكم في معالجة إعادة التوجيه أو منع إعادة التوجيه تماماً.
فهم أوامر curl ضروري لاختبار API الفعال مع Go. إليك مرجعاً سريعاً لخيارات curl الشائعة التي يدعمها محولنا:
curl [options] [URL]
-X, --request METHOD
: Specify request method (GET, POST, PUT, DELETE, etc.)-H, --header LINE
: Add header to the request-d, --data DATA
: Send data in POST request-F, --form CONTENT
: Submit form data-u, --user USER:PASSWORD
: Server user and password-k, --insecure
: Allow insecure server connections-I, --head
: Show document info only-v, --verbose
: Make the operation more verbose-s, --silent
: Silent mode--connect-timeout SECONDS
: Maximum time for connectionيتعامل محول Go لدينا مع أوامر curl المعقدة بما في ذلك الرؤوس المتعددة والمصادقة وحمولات البيانات والخيارات المختلفة. ما عليك سوى لصق أمر curl الخاص بك والحصول على كود Go نظيف وحديث باستخدام حزمة net/http.
عند العمل مع حزمة net/http في Go، اتبع أفضل الممارسات التالية للتفاعلات الفعالة والآمنة مع API:
resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() // Important: prevents resource leaks
client := &http.Client{ Timeout: 10 * time.Second, Transport: &http.Transport{ MaxIdleConns: 100, MaxIdleConnsPerHost: 20, IdleConnTimeout: 90 * time.Second, }, } resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return }
resp, err := client.Do(req) if err != nil { var netErr net.Error if errors.As(err, &netErr) && netErr.Timeout() { fmt.Println("Request timed out") } else if errors.Is(err, context.DeadlineExceeded) { fmt.Println("Context deadline exceeded") } else { fmt.Println("Error sending request:", err) } return } defer resp.Body.Close() // Check status code if resp.StatusCode < 200 || resp.StatusCode >= 300 { body, _ := ioutil.ReadAll(resp.Body) fmt.Printf("Error status: %d %s\n", resp.StatusCode, resp.Status) fmt.Printf("Response body: %s\n", string(body)) return } // Read response body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response body:", err) return } // Process response data var result map[string]interface{} if err := json.Unmarshal(body, &result); err != nil { fmt.Println("Error parsing JSON:", err) fmt.Println("Raw response:", string(body)) return }
// Create context with timeout ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Important: prevents context leaks // Create request with context req, err := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil) if err != nil { fmt.Println("Error creating request:", err) return } // Send request resp, err := client.Do(req) // Error handling...
// Define request and response structs type User struct { ID int `json:"id,omitempty"` Name string `json:"name"` Email string `json:"email"` } // Create request data user := User{ Name: "John Doe", Email: "[email protected]", } // Serialize to JSON jsonData, err := json.Marshal(user) if err != nil { fmt.Println("Error marshaling JSON:", err) return } // Create request req, err := http.NewRequest("POST", "https://api.example.com/users", bytes.NewBuffer(jsonData)) // Set headers, send request, etc... // Deserialize response var responseUser User if err := json.Unmarshal(body, &responseUser); err != nil { fmt.Println("Error parsing JSON response:", err) return } fmt.Printf("Created user with ID: %d\n", responseUser.ID)