Skip to content

cURL Testing Commands

Comprehensive testing and diagnostic commands for the Danish Parliament API. Perfect for health checks, debugging, and API exploration.

API Health Checks

1. Basic Connectivity Tests

# Simple connectivity test
curl -I "https://oda.ft.dk/api/Sag"

# Test with timeout
curl --max-time 10 -I "https://oda.ft.dk/api/Sag"

# Test with verbose output for debugging
curl -v "https://oda.ft.dk/api/Sag?%24top=1"

# Check response time
curl -w "Total time: %{time_total}s\nHTTP code: %{http_code}\n" -o /dev/null -s "https://oda.ft.dk/api/Sag?%24top=1"

2. SSL/TLS Verification

# Check SSL certificate
curl -v "https://oda.ft.dk/api/Sag?%24top=1" 2>&1 | grep -E "(TLS|SSL|certificate)"

# Verify certificate chain
openssl s_client -connect oda.ft.dk:443 -servername oda.ft.dk < /dev/null

# Check supported TLS versions
curl --tlsv1.2 -I "https://oda.ft.dk/api/Sag" 2>&1 | head -1

3. Response Analysis

# Get full response headers
curl -D - -o /dev/null -s "https://oda.ft.dk/api/Sag?%24top=1"

# Check content encoding
curl -H "Accept-Encoding: gzip" -v "https://oda.ft.dk/api/Sag?%24top=1" 2>&1 | grep -i "content-encoding"

# Measure response size
curl -w "Response size: %{size_download} bytes\n" -o /dev/null -s "https://oda.ft.dk/api/Sag?%24top=100"

API Functionality Tests

1. Entity Availability Tests

#!/bin/bash

# Test all major entities
ENTITIES=("Sag" "Aktør" "Afstemning" "Stemme" "Dokument" "Møde" "Fil")

echo "Testing entity availability:"
for entity in "${ENTITIES[@]}"; do
    HTTP_CODE=$(curl -s -w "%{http_code}" -o /dev/null "https://oda.ft.dk/api/${entity}?%24top=1")

    if [ "$HTTP_CODE" = "200" ]; then
        echo "✅ $entity: OK"
    else
        echo "L $entity: HTTP $HTTP_CODE"
    fi
done

2. OData Feature Tests

# Test $top parameter
echo "Testing \$top parameter:"
for size in 1 5 10 50 100; do
    COUNT=$(curl -s "https://oda.ft.dk/api/Sag?%24top=${size}" | jq '.value | length')
    echo "  Requested: $size, Received: $COUNT"
done

# Test $skip parameter
echo "Testing \$skip parameter:"
FIRST_ID=$(curl -s "https://oda.ft.dk/api/Sag?%24top=1&%24skip=0" | jq -r '.value[0].id')
SECOND_ID=$(curl -s "https://oda.ft.dk/api/Sag?%24top=1&%24skip=1" | jq -r '.value[0].id')
echo "  First record ID: $FIRST_ID"
echo "  Second record ID: $SECOND_ID"

# Test $inlinecount
echo "Testing \$inlinecount:"
RESPONSE=$(curl -s "https://oda.ft.dk/api/Sag?%24inlinecount=allpages&%24top=1")
COUNT=$(echo "$RESPONSE" | jq -r '."odata.count"')
echo "  Total Sag records: $COUNT"

# Test $filter
echo "Testing \$filter:"
FILTER_RESULT=$(curl -s "https://oda.ft.dk/api/Sag?%24filter=id%20eq%201&%24top=1" | jq '.value | length')
echo "  Filter result count: $FILTER_RESULT"

# Test $expand
echo "Testing \$expand:"
EXPAND_TEST=$(curl -s "https://oda.ft.dk/api/Sag?%24expand=Sagskategori&%24top=1" | jq -r '.value[0] | has("Sagskategori")')
echo "  Expansion successful: $EXPAND_TEST"

# Test $orderby
echo "Testing \$orderby:"
FIRST_DATE=$(curl -s "https://oda.ft.dk/api/Sag?%24orderby=opdateringsdato%20desc&%24top=1" | jq -r '.value[0].opdateringsdato')
LAST_DATE=$(curl -s "https://oda.ft.dk/api/Sag?%24orderby=opdateringsdato%20asc&%24top=1" | jq -r '.value[0].opdateringsdato')
echo "  Latest update: $FIRST_DATE"
echo "  Earliest update: $LAST_DATE"

# Test $select
echo "Testing \$select:"
SELECTED_FIELDS=$(curl -s "https://oda.ft.dk/api/Sag?%24select=id,titel&%24top=1" | jq -r '.value[0] | keys | @csv')
echo "  Selected fields: $SELECTED_FIELDS"

3. Data Quality Tests

# Check for null/empty data patterns
echo "Data quality tests:"

# Check for empty titles
EMPTY_TITLES=$(curl -s "https://oda.ft.dk/api/Sag?%24top=100" | jq '[.value[] | select(.titel == "" or .titel == null)] | length')
echo "  Cases with empty titles: $EMPTY_TITLES"

# Check for recent updates (data freshness)
RECENT_UPDATES=$(curl -s "https://oda.ft.dk/api/Sag?%24filter=opdateringsdato%20gt%20datetime'2025-01-01T00:00:00'&%24inlinecount=allpages&%24top=1" | jq -r '."odata.count"')
echo "  Cases updated in 2025: $RECENT_UPDATES"

# Check for consistent ID patterns
FIRST_IDS=$(curl -s "https://oda.ft.dk/api/Sag?%24top=5" | jq -r '.value[].id' | head -5)
echo "  First 5 case IDs: $(echo $FIRST_IDS | tr '\n' ' ')"

# Test Danish character encoding
DANISH_TEST=$(curl -s "https://oda.ft.dk/api/Aktør?%24filter=substringof('ø',navn)&%24top=1" | jq '.value | length')
echo "  Actors with 'ø' in name: $DANISH_TEST"

Error Condition Tests

1. Expected Error Scenarios

echo "Testing error conditions:"

# Test invalid entity (should return 404)
INVALID_ENTITY=$(curl -s -w "%{http_code}" -o /dev/null "https://oda.ft.dk/api/InvalidEntity")
echo "  Invalid entity: HTTP $INVALID_ENTITY (expect 404)"

# Test invalid ID (should return 404 or empty result)
INVALID_ID=$(curl -s "https://oda.ft.dk/api/Sag(999999999)" | jq '.value | length // "null"')
echo "  Invalid ID result: $INVALID_ID records"

# Test invalid $expand (should return 400)
INVALID_EXPAND=$(curl -s -w "%{http_code}" -o /dev/null "https://oda.ft.dk/api/Sag?%24expand=NonExistentRelation")
echo "  Invalid expansion: HTTP $INVALID_EXPAND (expect 400)"

# Test malformed filter (behavior varies)
MALFORMED_FILTER=$(curl -s -w "%{http_code}" -o /dev/null "https://oda.ft.dk/api/Sag?%24filter=invalid syntax here")
echo "  Malformed filter: HTTP $MALFORMED_FILTER"

# Test very large $top (should be limited to 100)
LARGE_TOP=$(curl -s "https://oda.ft.dk/api/Sag?%24top=10000" | jq '.value | length')
echo "  Large \$top result: $LARGE_TOP records (max 100)"

2. Edge Case Testing

# Test empty results
echo "Testing edge cases:"

# Query that should return no results
NO_RESULTS=$(curl -s "https://oda.ft.dk/api/Sag?%24filter=titel%20eq%20'ThisShouldNotExist12345'" | jq '.value | length')
echo "  No results query: $NO_RESULTS records"

# Test special characters in filter
SPECIAL_CHARS=$(curl -s "https://oda.ft.dk/api/Sag?%24filter=substringof('&',titel)" | jq '.value | length')
echo "  Special character filter: $SPECIAL_CHARS records"

# Test date boundaries
FUTURE_DATE=$(curl -s "https://oda.ft.dk/api/Sag?%24filter=opdateringsdato%20gt%20datetime'2030-01-01T00:00:00'" | jq '.value | length')
echo "  Future date filter: $FUTURE_DATE records"

# Test very old date
OLD_DATE=$(curl -s "https://oda.ft.dk/api/Sag?%24filter=opdateringsdato%20lt%20datetime'1990-01-01T00:00:00'" | jq '.value | length')
echo "  Old date filter: $OLD_DATE records"

Performance Testing

1. Response Time Analysis

#!/bin/bash

# Test response times for different query sizes
echo "Performance testing:"

test_response_time() {
    local query=$1
    local description=$2

    local total_time=$(curl -w "%{time_total}" -o /dev/null -s "$query")
    echo "  $description: ${total_time}s"
}

test_response_time "https://oda.ft.dk/api/Sag?%24top=1" "Single record"
test_response_time "https://oda.ft.dk/api/Sag?%24top=10" "10 records"
test_response_time "https://oda.ft.dk/api/Sag?%24top=100" "100 records"
test_response_time "https://oda.ft.dk/api/Sag?%24expand=Sagskategori&%24top=10" "With expansion"
test_response_time "https://oda.ft.dk/api/Sag?%24filter=substringof('klima',titel)&%24top=50" "With filter"

2. Concurrent Request Testing

#!/bin/bash

# Test concurrent requests (be respectful - max 3-5)
echo "Testing concurrent requests:"

concurrent_test() {
    local concurrent_count=$1
    echo "  Testing $concurrent_count concurrent requests..."

    start_time=$(date +%s.%N)

    for ((i=1; i<=concurrent_count; i++)); do
        curl -s "https://oda.ft.dk/api/Sag?%24top=10&%24skip=$((i*10))" > "/tmp/concurrent_$i.json" &
    done

    wait  # Wait for all background processes

    end_time=$(date +%s.%N)
    duration=$(echo "$end_time - $start_time" | bc)

    echo "    Duration: ${duration}s"

    # Clean up
    rm -f /tmp/concurrent_*.json
}

concurrent_test 3
concurrent_test 5

3. Large Dataset Testing

# Test large dataset retrieval patterns
echo "Large dataset testing:"

# Test pagination performance
echo "  Testing pagination performance:"
for skip in 0 100 1000 5000; do
    time_taken=$(curl -w "%{time_total}" -o /dev/null -s "https://oda.ft.dk/api/Sag?%24top=100&%24skip=${skip}")
    echo "    Skip $skip: ${time_taken}s"
done

# Test complex queries on large datasets
echo "  Testing complex query performance:"
complex_time=$(curl -w "%{time_total}" -o /dev/null -s "https://oda.ft.dk/api/Sag?%24expand=Sagskategori&%24filter=year(opdateringsdato)%20eq%202025&%24top=100")
echo "    Complex query: ${complex_time}s"

Data Validation Tests

1. Schema Consistency

# Validate data schema consistency
echo "Schema validation tests:"

# Check required fields presence
REQUIRED_FIELDS_TEST=$(curl -s "https://oda.ft.dk/api/Sag?%24top=5" | jq -r '
    .value[] | 
    [.id, .titel, .opdateringsdato] | 
    map(type) | 
    @csv
' | head -1)
echo "  Required field types (id,titel,opdateringsdato): $REQUIRED_FIELDS_TEST"

# Check date format consistency
DATE_FORMAT_TEST=$(curl -s "https://oda.ft.dk/api/Sag?%24top=10" | jq -r '
    [.value[].opdateringsdato | test("^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}")] | 
    all
')
echo "  Date format consistency: $DATE_FORMAT_TEST"

# Check ID uniqueness in sample
ID_UNIQUENESS=$(curl -s "https://oda.ft.dk/api/Sag?%24top=100" | jq '
    .value | 
    length as $total | 
    map(.id) | 
    unique | 
    length as $unique | 
    $total == $unique
')
echo "  ID uniqueness in sample: $ID_UNIQUENESS"

2. Relationship Integrity

# Test relationship integrity
echo "Relationship integrity tests:"

# Test foreign key consistency
FK_TEST=$(curl -s "https://oda.ft.dk/api/SagAktør?%24expand=Sag,Aktør&%24top=5" | jq -r '
    .value[] | 
    select(.Sag and .Aktør) | 
    "✅ SagAktør \(.id): Links Sag \(.sagid) to Aktør \(.aktørid)"
')
echo "$FK_TEST" | head -3

# Test expansion consistency  
EXPAND_TEST=$(curl -s "https://oda.ft.dk/api/Sag?%24expand=Sagskategori&%24top=5" | jq '
    [.value[] | select(.Sagskategori)] | length
')
TOTAL_WITH_CATEGORY=$(curl -s "https://oda.ft.dk/api/Sag?%24expand=Sagskategori&%24top=5" | jq '.value | length')
echo "  Expansion success rate: $EXPAND_TEST/$TOTAL_WITH_CATEGORY have categories"

Comprehensive Health Check Script

#!/bin/bash

# Complete API health check
echo "=== Danish Parliament API Health Check ==="
echo "Timestamp: $(date -u)"
echo

# Basic connectivity
echo "1. Basic Connectivity:"
HTTP_STATUS=$(curl -s -w "%{http_code}" -o /dev/null --max-time 10 "https://oda.ft.dk/api/Sag?%24top=1")
if [ "$HTTP_STATUS" = "200" ]; then
    echo "  ✅ API is accessible (HTTP $HTTP_STATUS)"
else
    echo "  L API connection failed (HTTP $HTTP_STATUS)"
    exit 1
fi

# Response time
echo "2. Performance:"
RESPONSE_TIME=$(curl -w "%{time_total}" -o /dev/null -s --max-time 30 "https://oda.ft.dk/api/Sag?%24top=1")
echo "  Response time: ${RESPONSE_TIME}s"

# Data freshness
echo "3. Data Freshness:"
LATEST_UPDATE=$(curl -s "https://oda.ft.dk/api/Sag?%24orderby=opdateringsdato%20desc&%24top=1" | jq -r '.value[0].opdateringsdato')
echo "  Latest case update: $LATEST_UPDATE"

# Record counts
echo "4. Dataset Sizes:"
CASE_COUNT=$(curl -s "https://oda.ft.dk/api/Sag?%24inlinecount=allpages&%24top=1" | jq -r '."odata.count"')
ACTOR_COUNT=$(curl -s "https://oda.ft.dk/api/Aktør?%24inlinecount=allpages&%24top=1" | jq -r '."odata.count"')
echo "  Total cases: $CASE_COUNT"
echo "  Total actors: $ACTOR_COUNT"

# OData functionality
echo "5. OData Features:"
FILTER_TEST=$(curl -s "https://oda.ft.dk/api/Sag?%24filter=id%20eq%201" | jq '.value | length')
EXPAND_TEST=$(curl -s "https://oda.ft.dk/api/Sag?%24expand=Sagskategori&%24top=1" | jq -r '.value[0] | has("Sagskategori")')
echo "  Filtering: $([ "$FILTER_TEST" -ge 0 ] && echo "✅ Working" || echo "L Failed")"
echo "  Expansion: $([ "$EXPAND_TEST" = "true" ] && echo "✅ Working" || echo "L Failed")"

# Recent activity
echo "6. Recent Activity:"
TODAY=$(date +%Y-%m-%d)
RECENT_COUNT=$(curl -s "https://oda.ft.dk/api/Sag?%24filter=startswith(opdateringsdato,'${TODAY}')&%24inlinecount=allpages&%24top=1" | jq -r '."odata.count"')
echo "  Cases updated today: $RECENT_COUNT"

echo
echo "Health check complete!"

# Summary
if [ "$HTTP_STATUS" = "200" ] && [ $(echo "$RESPONSE_TIME < 5.0" | bc) -eq 1 ]; then
    echo "✅ API Status: HEALTHY"
    exit 0
else
    echo "   API Status: DEGRADED"
    exit 1
fi

Debugging Utilities

1. URL Encoding Helper

# Helper function to properly encode OData URLs
encode_odata_url() {
    local base_url="https://oda.ft.dk/api/"
    local entity=$1
    local params=$2

    # Replace $ with %24
    encoded_params=$(echo "$params" | sed 's/\$/%24/g')

    echo "${base_url}${entity}?${encoded_params}"
}

# Usage examples
echo "Encoded URLs:"
echo $(encode_odata_url "Sag" "top=5&filter=id eq 1")
echo $(encode_odata_url "Aktør" "expand=Aktørtype&orderby=navn")

2. Response Inspector

# Detailed response analysis
inspect_response() {
    local url=$1
    echo "Inspecting: $url"

    # Get full response with headers
    RESPONSE=$(curl -i -s "$url")

    # Extract headers and body
    HEADERS=$(echo "$RESPONSE" | sed '/^\r$/q')
    BODY=$(echo "$RESPONSE" | sed '1,/^\r$/d')

    echo "Headers:"
    echo "$HEADERS" | grep -E "(HTTP|Content-|Cache-|Server)"

    echo "Body structure:"
    echo "$BODY" | jq -r 'keys'

    if echo "$BODY" | jq -e '.value' > /dev/null; then
        RECORD_COUNT=$(echo "$BODY" | jq '.value | length')
        echo "Records returned: $RECORD_COUNT"

        if [ "$RECORD_COUNT" -gt 0 ]; then
            echo "First record keys:"
            echo "$BODY" | jq -r '.value[0] | keys | @csv'
        fi
    fi
}

# Usage
inspect_response "https://oda.ft.dk/api/Sag?%24top=3"

These testing commands provide comprehensive coverage for validating API functionality, performance, and data quality. Use them for troubleshooting, monitoring, and ensuring reliable integration with the Danish Parliament API.