From f4eaf5e1fba0c7c314c96f9038381b93d1f7eb9e Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Thu, 1 Sep 2022 22:47:37 -0400 Subject: [PATCH] Improved error handling and responses for rpc failures --- proto/location.proto | 11 ++++--- server/current.go | 2 +- server/extended.go | 77 +++++++++++++++++++++----------------------- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/proto/location.proto b/proto/location.proto index 4e305a4..9bcaf52 100644 --- a/proto/location.proto +++ b/proto/location.proto @@ -4,13 +4,13 @@ package weather; option go_package = "codeberg.org/andcscott/OpenWeatherMap-gRPC-API/proto"; -// Sub-message for exact coordinates +// Sub-message for Coordinates message Coordinates { float latitude = 1; float longitude = 2; } -// Sub-message to specify location +// Sub-message for RequestLocation message OneOfLocation { oneof location_id { string city = 1; @@ -19,8 +19,11 @@ message OneOfLocation { } } -// Used to help the API find info for the correct location. If unspecified, an -// attept is still made but results may be inaccurate. +/* Enum to specify the location type for which data is needed. + * Helps the API find info for the correct location. If unspecified, an + * attept is still made. However, results may be inaccurate if city is used, + * or fail entirely if zip code or coordinates are used. + */ enum LocationType { LOCATION_TYPE_UNSPECIFIED = 0; LOCATION_TYPE_CITY = 1; diff --git a/server/current.go b/server/current.go index fd1c02c..750a8b0 100644 --- a/server/current.go +++ b/server/current.go @@ -13,7 +13,7 @@ import ( // Receives a gRPC request for the current forecast // Returns a SendCurrent message containing the forecast in JSON func (s *Server) Current(ctx context.Context, in *pb.RequestCurrent) (*pb.SendCurrent, error) { - log.Println("'Current' function called...") + log.Printf("'Current' called: %v\n", in) url := "https://api.openweathermap.org/data/2.5/weather?" lat, lon, err := getLocation(in.Location.String(), s.ApiKey) diff --git a/server/extended.go b/server/extended.go index 5c758f3..c649a47 100644 --- a/server/extended.go +++ b/server/extended.go @@ -12,6 +12,39 @@ import ( "google.golang.org/grpc/status" ) +// Receives a gRPC request for an extended forecast +// Returns a SendFiveDay message with the forecast as JSON +func (s *Server) FiveDay(ctx context.Context, in *pb.RequestFiveDay) (*pb.SendFiveDay, error) { + log.Printf("'FiveDay' called: %v\n", in) + + url, err := s.createFiveDayUrl(in) + if err != nil { + return nil, status.Errorf( + codes.InvalidArgument, + fmt.Sprintf("Invalid location or location type: %s, %s\n", + in.Location.String(), + in.LocationType.String()), + ) + } + + token := "&appid=" + s.ApiKey + res, err := http.Get(url + token) + if err != nil { + log.Printf("Error fetching extended weather: %v\n", err) + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + log.Printf("Error reading extending weather: %v\n", err) + } + + return &pb.SendFiveDay{ + Payload: string(body), + }, nil +} + +// Assembles the OpenWeather API URL for FiveDay func (s *Server) createFiveDayUrl(in *pb.RequestFiveDay) (string, error) { var lat, lon float32 @@ -31,56 +64,20 @@ func (s *Server) createFiveDayUrl(in *pb.RequestFiveDay) (string, error) { switch in.LocationType { case pb.LocationType_LOCATION_TYPE_CITY: lat, lon, err = getLocation(in.Location.GetCity(), s.ApiKey) - if err != nil { - return "", err - } case pb.LocationType_LOCATION_TYPE_ZIP_CODE: lat, lon, err = getZipLocation(in.Location.GetZipCode(), s.ApiKey) - if err != nil { - return "", err - } case pb.LocationType_LOCATION_TYPE_COORDS: lat = in.Location.GetCoords().Latitude lon = in.Location.GetCoords().Longitude default: + fmt.Println(in.Location.String()) lat, lon, err = getLocation(in.Location.String(), s.ApiKey) - if err != nil { - return "", err - } + } + if err != nil { + return "", err } url = url + fmt.Sprintf("lat=%f", lat) + fmt.Sprintf("&lon=%f", lon) + units return url, nil } - -// Receives a gRPC request for an extended forecast -// Returns a SendExtended message with the forecast in JSON -func (s *Server) FiveDay(ctx context.Context, in *pb.RequestFiveDay) (*pb.SendFiveDay, error) { - log.Println("'FiveDay' function called...") - - url, err := s.createFiveDayUrl(in) - if err != nil { - return nil, status.Errorf( - codes.InvalidArgument, - fmt.Sprintf("Invalid location: %s", in.Location.String()), - ) - } - - token := "&appid=" + s.ApiKey - - res, err := http.Get(url + token) - if err != nil { - log.Printf("Error fetching extended weather: %v\n", err) - } - defer res.Body.Close() - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - log.Printf("Error reading extending weather: %v\n", err) - } - - return &pb.SendFiveDay{ - Payload: string(body), - }, nil -}