Skip to content
Merged
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
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ You can find the latest published Docker images on Docker Hub:
* `TRIP_UPDATES_URL` - Trip Updates URL for GTFS-RT.
* `VEHICLE_POSITIONS_URL` - Vehicle Positions URL for GTFS-RT.
* `REFRESH_INTERVAL` - Refresh interval in seconds. Usually 10-30.
* `AGENCY_ID` - Your GTFS-RT agency ID. Ostensibly the same as your GTFS agency ID.
* Specify one or the other:
* `AGENCY_ID_LIST` - Your GTFS-RT agency IDs. These should match the IDs in your agency.txt file. Format: abxoxo
* `AGENCY_ID` - Optional: Your GTFS-RT agency ID. Ostensibly the same as your GTFS agency ID.
* Authentication (Optional)
* Example: Specifying `FEED_API_KEY` = `X-API-KEY` and `FEED_API_VALUE` = `12345` will result in `X-API-KEY: 12345` being passed on every call to your GTFS-RT URLs.
* `FEED_API_KEY` - If your GTFS-RT API requires you to pass an authentication header, you can represent the key portion of it by specifying this value.
Expand Down
30 changes: 23 additions & 7 deletions bin/validate.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/bin/bash

output=$(curl -s "http://localhost:8080/api/where/current-time.json?key=test" | jq '.data.entry.time')
# Timeout for curl requests in seconds
CURL_TIMEOUT=120

output=$(curl -s --max-time $CURL_TIMEOUT "http://localhost:8080/api/where/current-time.json?key=test" | jq '.data.entry.time')

if [[ ! -z "$output" && "$output" =~ ^[0-9]+$ ]]; then
echo "current-time.json endpoint works."
Expand All @@ -10,7 +13,20 @@ else
fi

# Get the first agency from agencies-with-coverage
agency_response=$(curl -s "http://localhost:8080/api/where/agencies-with-coverage.json?key=test")
agency_response=$(curl -s --max-time $CURL_TIMEOUT "http://localhost:8080/api/where/agencies-with-coverage.json?key=test")

# Debug: Show raw response if empty or small
if [[ -z "$agency_response" || ${#agency_response} -lt 100 ]]; then
echo "Debug: Raw agency response: '$agency_response'"
fi

# Check if response is valid JSON
if ! echo "$agency_response" | jq empty 2>/dev/null; then
echo "Error: Invalid JSON response from agencies-with-coverage endpoint"
echo "Response: $agency_response"
exit 1
fi

agency_count=$(echo "$agency_response" | jq '.data.list | length')

if [[ "$agency_count" -gt 0 ]]; then
Expand All @@ -23,7 +39,7 @@ else
fi

# Get routes for the agency
routes_response=$(curl -s "http://localhost:8080/api/where/routes-for-agency/${AGENCY_ID}.json?key=test")
routes_response=$(curl -s --max-time $CURL_TIMEOUT "http://localhost:8080/api/where/routes-for-agency/${AGENCY_ID}.json?key=test")
route_count=$(echo "$routes_response" | jq '.data.list | length')
if [[ "$route_count" -gt 0 ]]; then
echo "routes-for-agency/${AGENCY_ID}.json endpoint works (found $route_count routes)."
Expand All @@ -35,7 +51,7 @@ else
fi

# Get stops for the route
stops_response=$(curl -s "http://localhost:8080/api/where/stops-for-route/${ROUTE_ID}.json?key=test")
stops_response=$(curl -s --max-time $CURL_TIMEOUT "http://localhost:8080/api/where/stops-for-route/${ROUTE_ID}.json?key=test")
route_id_check=$(echo "$stops_response" | jq -r '.data.entry.routeId')
if [[ ! -z "$route_id_check" && "$route_id_check" == "$ROUTE_ID" ]]; then
echo "stops-for-route/${ROUTE_ID}.json endpoint works."
Expand All @@ -47,7 +63,7 @@ else
fi

# Get stop details
stop_response=$(curl -s "http://localhost:8080/api/where/stop/${STOP_ID}.json?key=test")
stop_response=$(curl -s --max-time $CURL_TIMEOUT "http://localhost:8080/api/where/stop/${STOP_ID}.json?key=test")
stop_id_check=$(echo "$stop_response" | jq -r '.data.entry.id')
if [[ ! -z "$stop_id_check" && "$stop_id_check" == "$STOP_ID" ]]; then
echo "stop/${STOP_ID}.json endpoint works."
Expand All @@ -62,7 +78,7 @@ fi

# Test stops-for-location using coordinates from the stop
LOCATION_URL="http://localhost:8080/api/where/stops-for-location.json?lat=${STOP_LAT}&lon=${STOP_LON}&key=test"
location_response=$(curl -s "$LOCATION_URL")
location_response=$(curl -s --max-time $CURL_TIMEOUT "$LOCATION_URL")
out_of_range=$(echo "$location_response" | jq '.data.outOfRange')
stops_found=$(echo "$location_response" | jq '.data.list | length')
if [[ ! -z "$out_of_range" && "$out_of_range" == "false" && "$stops_found" -gt 0 ]]; then
Expand All @@ -75,7 +91,7 @@ else
fi

# Test arrivals-and-departures-for-stop endpoint
arrivals_response=$(curl -s "http://localhost:8080/api/where/arrivals-and-departures-for-stop/${STOP_ID}.json?key=test")
arrivals_response=$(curl -s --max-time $CURL_TIMEOUT "http://localhost:8080/api/where/arrivals-and-departures-for-stop/${STOP_ID}.json?key=test")
arrivals_stop_id=$(echo "$arrivals_response" | jq -r '.data.entry.stopId')
arrivals_count=$(echo "$arrivals_response" | jq '.data.entry.arrivalsAndDepartures | length // 0')

Expand Down
3 changes: 2 additions & 1 deletion docker-compose.standalone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ services:
- JDBC_PASSWORD=oba_password
- TEST_API_KEY=test # For test only, remove in production
- TZ=America/Los_Angeles
- AGENCY_ID=unitrans
- GTFS_URL=https://unitrans.ucdavis.edu/media/gtfs/Unitrans_GTFS.zip
- GTFS_TIDY_ARGS=v
- GTFS_TIDY_ARGS=OeD

ports:
# Access the webapp on your host machine at a path like
Expand Down
27 changes: 26 additions & 1 deletion oba/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,33 @@ else
HAS_API_KEY=""
fi

# Handle AGENCY_ID_LIST properly - if it's a JSON array, use it directly, otherwise treat as empty
if [ -n "$AGENCY_ID_LIST" ]; then
# Remove the outer quotes if they exist and use the array directly
AGENCY_ID_LIST_JSON="$AGENCY_ID_LIST"
else
AGENCY_ID_LIST_JSON="[]"
fi

# Build the JSON string with proper handling of AGENCY_ID_LIST
JSON_CONFIG=$(cat <<EOF
{
"GTFS_RT_AVAILABLE": "$GTFS_RT_AVAILABLE",
"TRIP_UPDATES_URL": "$TRIP_UPDATES_URL",
"VEHICLE_POSITIONS_URL": "$VEHICLE_POSITIONS_URL",
"ALERTS_URL": "$ALERTS_URL",
"REFRESH_INTERVAL": "$REFRESH_INTERVAL",
"AGENCY_ID": "$AGENCY_ID",
"AGENCY_ID_LIST": $AGENCY_ID_LIST_JSON,
"HAS_API_KEY": "$HAS_API_KEY",
"FEED_API_KEY": "$FEED_API_KEY",
"FEED_API_VALUE": "$FEED_API_VALUE"
}
EOF
)

hbs_renderer -input "$FEDERATION_XML_SOURCE" \
-json '{"GTFS_RT_AVAILABLE": "'$GTFS_RT_AVAILABLE'", "TRIP_UPDATES_URL": "'$TRIP_UPDATES_URL'", "VEHICLE_POSITIONS_URL": "'$VEHICLE_POSITIONS_URL'", "ALERTS_URL": "'$ALERTS_URL'", "REFRESH_INTERVAL": "'$REFRESH_INTERVAL'", "AGENCY_ID": "'$AGENCY_ID'", "HAS_API_KEY": "'$HAS_API_KEY'", "FEED_API_KEY": "'$FEED_API_KEY'", "FEED_API_VALUE": "'$FEED_API_VALUE'"}' \
-json "$JSON_CONFIG" \
-output "$FEDERATION_XML_DESTINATION"

#####
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,17 @@
<property name="refreshInterval" value="{{ REFRESH_INTERVAL }}" />
{{/if}}

<property name="agencyId" value="{{ AGENCY_ID }}" />
{{#if AGENCY_ID_LIST.length}}
<property name="agencyIds">
<list>
{{#each AGENCY_ID_LIST}}
<value>{{ this }}</value>
{{/each}}
</list>
</property>
{{else if AGENCY_ID}}
<property name="agencyId" value="{{ AGENCY_ID }}" />
{{/if}}

{{#if HAS_API_KEY}}
<property name="headersMap">
Expand Down
55 changes: 55 additions & 0 deletions oba/config/template_renderer/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,61 @@ func TestRenderTemplate(t *testing.T) {
}
}

func TestRenderTemplateWithArray(t *testing.T) {
// Create a temporary template file
tempFile, err := os.CreateTemp("", "test-template-*.hbs")
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
defer os.Remove(tempFile.Name()) // clean up

// Write test template content
templateContent := "Hello, {{name}}! Your favorite colors are {{#each colors}}{{this}} {{else}}unknown{{/each}}."
if _, err := tempFile.Write([]byte(templateContent)); err != nil {
t.Fatalf("Failed to write to temp file: %v", err)
}
if err := tempFile.Close(); err != nil {
t.Fatalf("Failed to close temp file: %v", err)
}

// Set up test cases
testCases := []struct {
name string
jsonData string
expected string
}{
{
name: "Basic rendering",
jsonData: `{"name": "Alice", "colors": ["blue", "green"]}`,
expected: "Hello, Alice! Your favorite colors are blue green .",
},
{
name: "only one item rendering",
jsonData: `{"name": "Alice", "colors": ["green"]}`,
expected: "Hello, Alice! Your favorite colors are green .",
},
{
name: "only one item rendering",
jsonData: `{"name": "Alice", "colors": []}`,
expected: "Hello, Alice! Your favorite colors are unknown.",
},
}

// Run test cases
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result, err := renderTemplate(tempFile.Name(), tc.jsonData)
if err != nil {
t.Fatalf("renderTemplate returned an error: %v", err)
}

if !strings.Contains(result, tc.expected) {
t.Errorf("Expected output to contain %q, but got %q", tc.expected, result)
}
})
}
}

func TestRenderTemplateErrors(t *testing.T) {
// Test with non-existent file
_, err := renderTemplate("non-existent-file.hbs", "{}")
Expand Down
Loading