Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 116 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,125 @@
# Binaries for programs and plugins

# ==================================================
# Go - arquivos binários compilados
# ==================================================
*.exe
*.exe~
*.dll
*.so
*.dylib
*.a
*.o
*.obj
*.test
*.out

# Test binary, build with `go test -c`
# Binários gerados pelo projeto
/weather-api
/weather-api.exe
/bin/
/build/
/dist/

# ==================================================
# Go - dependências e ferramentas
# ==================================================
vendor/

# ==================================================
# Testes e cobertura
# ==================================================
coverage.out
coverage.txt
coverage.html
coverage.xml
coverage.json
cover.out
coverprofile.out
*.coverprofile
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# ==================================================
# Profiling e diagnósticos
# ==================================================
*.prof
*.pprof
*.cpuprofile
*.memprofile
*.heapprofile
*.trace
*.cover

# ==================================================
# Variáveis de ambiente e segredos
# ==================================================
.env
.env.*
!.env.example
!.env.*.example

# Arquivos de credenciais e chaves privadas
*.pem
*.key
*.p12
*.pfx
*.keystore
secrets.yaml
secrets.yml
secrets.json
credentials.json

# ==================================================
# Logs
# ==================================================
*.log
logs/
log/

# ==================================================
# Arquivos temporários
# ==================================================
*.tmp
*.temp
*.bak
*.swp
*.swo
*.orig
*~
.temp/
tmp/
temp/

# ==================================================
# Sistemas operacionais
# ==================================================
.DS_Store
.DS_Store?
._*
Thumbs.db
Desktop.ini

# ==================================================
# IDEs e editores
# ==================================================
.vscode/
.idea/
*.iml
*.sublime-workspace
*.sublime-project
*.code-workspace
.project
.classpath
.settings/

# dep vendor folder
vendor
# ==================================================
# Go - arquivos gerados por ferramentas
# ==================================================
go.work.sum

# build app file
weather-api
# ==================================================
# CI/CD e ferramentas locais
# ==================================================
coverage/
.nyc_output/
.cache/
.pytest_cache/
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
```go
Comment thread
teobaldotech marked this conversation as resolved.
Resolved
module github.com/robertoduessmann/weather-api

go 1.23.0

toolchain go1.23.2

require (
github.com/PuerkitoBio/goquery v1.10.0
github.com/PuerkitoBio/goquery v1.10.3
github.com/caarlos0/env v3.5.0+incompatible
github.com/gorilla/handlers v1.5.2
github.com/gorilla/mux v1.8.1
github.com/stretchr/testify v1.12.1
)

require (
github.com/andybalholm/cascadia v1.3.2 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/stretchr/testify v1.9.0 // indirect
golang.org/x/net v0.38.0 // indirect
)
```
99 changes: 64 additions & 35 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,42 +1,71 @@
package main
package v2

import (
"log"
"context"
"encoding/json"
"fmt"
"net/http"

"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/robertoduessmann/weather-api/config"
"github.com/robertoduessmann/weather-api/controller"
v2 "github.com/robertoduessmann/weather-api/controller/v2"
"net/url"
"time"
)

func main() {
log.Println("Starting application")

weather := mux.NewRouter()

log.Println("Creating routes")
weather.
Path("/weather/{city}").
Methods(http.MethodGet).
HandlerFunc(controller.CurrentWeather)

weather.
Path("/v2/weather/{city}").
Queries("unit", "{unit}").
Methods(http.MethodGet).
HandlerFunc(v2.CurrentWeather)

weather.
Path("/v2/weather/{city}").
Methods(http.MethodGet).
HandlerFunc(v2.CurrentWeather)

log.Println("Created routes")
port := config.Get().Port
log.Println("Initialize server on port: " + port)
if err := http.ListenAndServe(":"+port, handlers.CORS()(weather)); err != nil {
log.Fatal(err)
// Estrutura do retorno da API OpenWeatherMap
type OpenWeatherResponse struct {
Main struct {
Temp float64 `json:"temp"`
} `json:"main"`
Name string `json:"name"`
}

type WeatherService struct {
APIKey string
HTTPClient *http.Client
}

func NewWeatherService(apiKey string) *WeatherService {
return &WeatherService{
APIKey: apiKey,
HTTPClient: &http.Client{
Timeout: 10 * time.Second, // Timeout para evitar requisições presas
},
}
}

func (s *WeatherService) FetchWeather(ctx context.Context, city, unit string) (*OpenWeatherResponse, error) {
// Mapeia unidades para o padrão da OpenWeatherMap (metric / imperial)
unitsParam := "metric"
if unit == "fahrenheit" {
unitsParam = "imperial"
}

endpoint := fmt.Sprintf(
"https://api.openweathermap.org/data/2.5/weather?q=%s&units=%s&appid=%s",
url.QueryEscape(city), unitsParam, s.APIKey,
)

req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
if err != nil {
return nil, fmt.Errorf("erro ao criar requisição: %w", err)
}

resp, err := s.HTTPClient.Do(req)
if err != nil {
return nil, fmt.Errorf("erro ao chamar API externa: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode == http.StatusNotFound {
return nil, fmt.Errorf("cidade não encontrada")
}

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("resposta inesperada da API: status %d", resp.StatusCode)
}

var data OpenWeatherResponse
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
return nil, fmt.Errorf("erro ao decodificar JSON: %w", err)
}

return &data, nil
}