Skip to content

Commit a5f67f9

Browse files
api get transport stations endpoint
1 parent 9c42cdb commit a5f67f9

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

api/get_transport_stations.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package api
2+
3+
import (
4+
"net/http"
5+
"strconv"
6+
7+
"github.com/gin-gonic/gin"
8+
"github.com/sndcds/grains/grains_api"
9+
)
10+
11+
type TransportStationResult struct {
12+
Id int `json:"id"`
13+
Name *string `json:"name,omitempty"`
14+
Lon *float64 `json:"lon,omitempty"`
15+
Lat *float64 `json:"lat,omitempty"`
16+
GtfsStationCode *string `json:"gtfs_station_code,omitempty"`
17+
City *string `json:"city,omitempty"`
18+
Country *string `json:"country,omitempty"`
19+
GtfsParentStation *string `json:"gtfs_parent_station,omitempty"`
20+
GtfsWheelchairBoard *int `json:"gtfs_wheelchair_boarding,omitempty"`
21+
GtfsZoneId *string `json:"gtfs_zone_id,omitempty"`
22+
DistanceMeters float64 `json:"distance_m"` // calculated
23+
}
24+
25+
func (h *ApiHandler) GetTransportStations(gc *gin.Context) {
26+
ctx := gc.Request.Context()
27+
apiRequest := grains_api.NewRequest(gc, "transport-stations")
28+
29+
// Parse query params
30+
latStr := gc.Query("lat")
31+
lonStr := gc.Query("lon")
32+
radius := GetContextParamIntDefault(gc, "radius", 5000)
33+
apiRequest.SetMeta("radius", radius)
34+
35+
if latStr == "" || lonStr == "" {
36+
apiRequest.Error(http.StatusBadRequest, "lat and lon are required")
37+
return
38+
}
39+
apiRequest.SetMeta("lat", latStr)
40+
apiRequest.SetMeta("lon", lonStr)
41+
42+
lat, err := strconv.ParseFloat(latStr, 64)
43+
if err != nil {
44+
apiRequest.Error(http.StatusBadRequest, "invalid lat")
45+
return
46+
}
47+
lon, err := strconv.ParseFloat(lonStr, 64)
48+
if err != nil {
49+
apiRequest.Error(http.StatusBadRequest, "invalid lon")
50+
return
51+
}
52+
53+
// PostgreSQL query with ST_DWithin and distance
54+
query := `
55+
SELECT
56+
id,
57+
name,
58+
gtfs_station_code,
59+
city,
60+
country,
61+
gtfs_parent_station,
62+
gtfs_wheelchair_boarding,
63+
gtfs_zone_id,
64+
ST_X(geo_pos) AS lon,
65+
ST_Y(geo_pos) AS lat,
66+
ST_Distance(
67+
geo_pos::geography,
68+
ST_SetSRID(ST_MakePoint($1, $2), 4326)::geography
69+
) AS distance_m
70+
FROM uranus.transport_station
71+
WHERE ST_DWithin(
72+
geo_pos::geography,
73+
ST_SetSRID(ST_MakePoint($1, $2), 4326)::geography,
74+
$3
75+
)
76+
ORDER BY distance_m;
77+
`
78+
79+
rows, err := h.DbPool.Query(ctx, query, lon, lat, radius)
80+
if err != nil {
81+
apiRequest.InternalServerError()
82+
return
83+
}
84+
defer rows.Close()
85+
86+
var results []TransportStationResult
87+
for rows.Next() {
88+
var s TransportStationResult
89+
if err := rows.Scan(
90+
&s.Id,
91+
&s.Name,
92+
&s.GtfsStationCode,
93+
&s.City,
94+
&s.Country,
95+
&s.GtfsParentStation,
96+
&s.GtfsWheelchairBoard,
97+
&s.GtfsZoneId,
98+
&s.Lon,
99+
&s.Lat,
100+
&s.DistanceMeters,
101+
); err != nil {
102+
apiRequest.InternalServerError()
103+
return
104+
}
105+
results = append(results, s)
106+
}
107+
108+
apiRequest.Success(http.StatusOK, results, "")
109+
}

uranus-api.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ func main() {
112112

113113
publicRoute.GET("/venue/:venueId", apiHandler.GetVenue)
114114

115+
publicRoute.GET("/transport/stations", apiHandler.GetTransportStations)
116+
115117
publicRoute.GET("/user/:userId/avatar/:size", apiHandler.GetUserAvatar) // TODO: check!
116118
publicRoute.GET("/user/:userId/avatar", apiHandler.GetUserAvatar) // TODO: check!
117119

0 commit comments

Comments
 (0)