Skip to content

Instantly share code, notes, and snippets.

@devedetti
Created April 13, 2026 00:56
Show Gist options
  • Select an option

  • Save devedetti/5790d5eb61def084787bb08ec8a1863f to your computer and use it in GitHub Desktop.

Select an option

Save devedetti/5790d5eb61def084787bb08ec8a1863f to your computer and use it in GitHub Desktop.
package main
import (
"context"
"encoding/json"
"net/http"
"time"
)
const (
maxRetries = 3
timeout = 10 * time.Second
)
func handler(w http.ResponseWriter, r *http.Request) {
url := "https://external-service/api"
client := &http.Client{}
for attempt := 0; attempt < maxRetries; attempt++ {
ctx, cancel := context.WithTimeout(r.Context(), timeout)
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
resp, err := client.Do(req)
cancel() // SIEMPRE liberar
if err != nil {
// timeout o error de red → retry
continue
}
if resp.StatusCode == http.StatusOK {
defer resp.Body.Close()
var data map[string]interface{}
json.NewDecoder(resp.Body).Decode(&data)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
return
}
// status != 200 → retry
}
http.Error(w, "external service unavailable", http.StatusBadGateway)
}
func main() {
http.HandleFunc("/endpoint", handler)
http.ListenAndServe(":8080", nil)
}
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
@RestController
public class ExternalController {
private static final int MAX_RETRIES = 3;
private static final int TIMEOUT_MS = 10_000;
private RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(TIMEOUT_MS);
factory.setReadTimeout(TIMEOUT_MS);
return new RestTemplate(factory);
}
@GetMapping("/endpoint")
public ResponseEntity<?> handler() {
String url = "https://external-service/api";
RestTemplate client = restTemplate();
for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
try {
ResponseEntity<String> response = client.getForEntity(url, String.class);
if (response.getStatusCode().is2xxSuccessful()) {
return ResponseEntity.ok(response.getBody());
}
} catch (ResourceAccessException e) {
// timeout / network → retry
continue;
} catch (Exception e) {
// otros errores → retry
continue;
}
}
return ResponseEntity.status(502)
.body("external service unavailable");
}
}
// controller.ts
import { Controller, Get, HttpException, HttpStatus } from '@nestjs/common';
import axios from 'axios';
const MAX_RETRIES = 3;
const TIMEOUT = 10000; // ms
@Controller()
export class AppController {
@Get('/endpoint')
async handler() {
const url = 'https://external-service/api';
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
try {
const response = await axios.get(url, {
timeout: TIMEOUT,
});
if (response.status === 200) {
return response.data;
}
} catch (err) {
// timeout o error → retry
continue;
}
}
throw new HttpException(
'external service unavailable',
HttpStatus.BAD_GATEWAY,
);
}
}
# pseudo-código Django view
import requests
from django.http import JsonResponse
MAX_RETRIES = 3
TIMEOUT_SECONDS = 10
def external_api_view(request):
url = "https://external-service/api"
for attempt in range(MAX_RETRIES):
try:
response = requests.get(
url,
timeout=TIMEOUT_SECONDS # corta la request si pasan 10s
)
# si responde pero con error HTTP, lo tratás aparte
if response.status_code == 200:
return JsonResponse(response.json())
else:
# opcional: decidir si reintentar según status
continue
except requests.Timeout:
# timeout → reintentar
continue
except requests.RequestException:
# error de red → reintentar
continue
# si llegó acá, fallaron los 3 intentos
return JsonResponse(
{"error": "external service unavailable"},
status=502
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment