| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- package handlers
- import (
- "encoding/json"
- "io"
- "net/http"
- "net/url"
- "time"
- )
- const nominatimURL = "https://nominatim.openstreetmap.org/reverse"
- var geocodeClient = &http.Client{Timeout: 5 * time.Second}
- type nominatimResponse struct {
- DisplayName string `json:"display_name"`
- }
- func GeocodeReverse(w http.ResponseWriter, r *http.Request) {
- lat := r.URL.Query().Get("lat")
- lon := r.URL.Query().Get("lon")
- if lat == "" || lon == "" {
- writeError(w, http.StatusBadRequest, "lat and lon are required", nil)
- return
- }
- u, _ := url.Parse(nominatimURL)
- q := u.Query()
- q.Set("lat", lat)
- q.Set("lon", lon)
- q.Set("format", "json")
- q.Set("accept-language", "ru")
- u.RawQuery = q.Encode()
- req, _ := http.NewRequestWithContext(r.Context(), http.MethodGet, u.String(), nil)
- req.Header.Set("User-Agent", "Photoplaces/1.0")
- resp, err := geocodeClient.Do(req)
- if err != nil {
- writeError(w, http.StatusBadGateway, "geocoding service unavailable", err)
- return
- }
- defer resp.Body.Close()
- if resp.StatusCode != http.StatusOK {
- body, _ := io.ReadAll(resp.Body)
- writeJSON(w, http.StatusOK, map[string]interface{}{
- "display_name": nil,
- "raw_error": string(body),
- })
- return
- }
- var data nominatimResponse
- if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
- writeError(w, http.StatusInternalServerError, "failed to parse geocoding response", err)
- return
- }
- writeJSON(w, http.StatusOK, map[string]interface{}{
- "display_name": data.DisplayName,
- })
- }
|