opendata-api 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +2 -0
- data.tar.gz.sig +0 -0
- data/lib/opendata-api.rb +80 -0
- data/lib/opendata-api/config.rb +29 -0
- data/lib/opendata-api/request.rb +83 -0
- metadata +68 -0
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 10b8aa1b9cba390f86ec972ce6c02667c5bf90c6
|
4
|
+
data.tar.gz: 757f9601ea75c14add7387494ecb594d5546072d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 20305e4c5809641911c815f6b4a786a01c4ef185ce3358dc8617cf22632c17dee9c0ac360dc5341720a07d86e54646a0cab7c2ea0352f4aa39fed768238d6b27
|
7
|
+
data.tar.gz: 5bcedb4a342de52a1332ea2a9be5b879bca876306541e65bc90042c723b86e1da62b9cae6e8486e66537cb68e04a85b0aa7c5222c10038f8408d77a68f11076f
|
checksums.yaml.gz.sig
ADDED
data.tar.gz.sig
ADDED
Binary file
|
data/lib/opendata-api.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
require 'openssl'
|
6
|
+
|
7
|
+
require_relative './opendata-api/config'
|
8
|
+
require_relative './opendata-api/request'
|
9
|
+
|
10
|
+
module OpenDataAPI
|
11
|
+
def self.init(api_key)
|
12
|
+
raise "OpenData API Key required" if api_key.empty?
|
13
|
+
|
14
|
+
uri_base = URI.parse(OpenDataAPI::Constants::BASE_URL)
|
15
|
+
http_base = Net::HTTP.new(uri_base.host, uri_base.port)
|
16
|
+
|
17
|
+
# Store API Key as class variable
|
18
|
+
OpenDataAPIRequest.set_api_key(api_key)
|
19
|
+
|
20
|
+
# Store URI and HTTP base as class variables
|
21
|
+
OpenDataAPIRequest.set_uri_base(uri_base)
|
22
|
+
OpenDataAPIRequest.set_http_base(http_base)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.run(args)
|
26
|
+
api_requests = []
|
27
|
+
args.each do |arg|
|
28
|
+
case arg[:api_name]
|
29
|
+
when 'traffic_volume_counts'
|
30
|
+
# Request for Traffic Volume Counts API
|
31
|
+
uri_traffic_volume_counts_api = URI.parse(
|
32
|
+
OpenDataAPI::Constants::TrafficVolumeCountsAPI::BASE_URL +
|
33
|
+
OpenDataAPI::Constants::TrafficVolumeCountsAPI::API_ENDPOINT +
|
34
|
+
OpenDataAPI::Constants::TrafficVolumeCountsAPI.query_string_params(arg[:format], arg[:table], arg[:limit])
|
35
|
+
)
|
36
|
+
request_for_traffic_volume_counts_api = {
|
37
|
+
api_name: arg[:api_name],
|
38
|
+
api_instance: OpenDataAPIRequest.new(OpenDataAPIRequest.http_base, uri_traffic_volume_counts_api, OpenDataAPIRequest.api_key)
|
39
|
+
}
|
40
|
+
api_requests << request_for_traffic_volume_counts_api
|
41
|
+
when 'trip_planner'
|
42
|
+
# Request for Trip Planner API
|
43
|
+
uri_trip_planner_api = URI.parse(
|
44
|
+
OpenDataAPI::Constants::TripPlannerAPI::BASE_URL +
|
45
|
+
OpenDataAPI::Constants::TripPlannerAPI::API_ENDPOINT +
|
46
|
+
OpenDataAPI::Constants::TripPlannerAPI.query_string_params(arg[:format], arg[:coord_lat], arg[:coord_long], arg[:coord_radius])
|
47
|
+
)
|
48
|
+
request_for_trip_planner_api = {
|
49
|
+
api_name: arg[:api_name],
|
50
|
+
api_instance: OpenDataAPIRequest.new(OpenDataAPIRequest.http_base, uri_trip_planner_api, OpenDataAPIRequest.api_key)
|
51
|
+
}
|
52
|
+
api_requests << request_for_trip_planner_api
|
53
|
+
else
|
54
|
+
raise ArgumentError.new("Invalid API Name")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
begin
|
59
|
+
# Start HTTP(S) Session to re-use across multiple requests
|
60
|
+
Net::HTTP.start(OpenDataAPIRequest.uri_base.hostname, OpenDataAPIRequest.uri_base.port,
|
61
|
+
:use_ssl => OpenDataAPIRequest.uri_base.scheme == 'https') do |http_session|
|
62
|
+
puts http_session.use_ssl? ? "OpenData API HTTPS Session" : "OpenData API HTTP Session"
|
63
|
+
|
64
|
+
http_session.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
65
|
+
http_session.read_timeout = OpenDataAPI::Constants::READ_TIMEOUT
|
66
|
+
|
67
|
+
response = {}
|
68
|
+
# Request #1 to each API (i.e. Traffic Volume Counts API, Trip Planner API, etc)
|
69
|
+
api_requests.each do |request|
|
70
|
+
_res = request[:api_instance].fetch(http_session, request[:api_instance].request, OpenDataAPI::Constants::REQUEST_LIMIT)
|
71
|
+
# puts JSON.pretty_generate(JSON.parse(_res.body))
|
72
|
+
response[request[:api_name].to_sym] = _res.body
|
73
|
+
end
|
74
|
+
response
|
75
|
+
end
|
76
|
+
rescue Exception => e
|
77
|
+
raise "Exception opening TCP connection: #{e}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module OpenDataAPI
|
2
|
+
module Constants
|
3
|
+
# Transport for NSW (TfNSW) Open Data API
|
4
|
+
BASE_URL = 'https://api.transport.nsw.gov.au'
|
5
|
+
READ_TIMEOUT = 500
|
6
|
+
REQUEST_LIMIT = 3
|
7
|
+
|
8
|
+
# Traffic Volume Counts API
|
9
|
+
module TrafficVolumeCountsAPI
|
10
|
+
BASE_URL = 'https://api.transport.nsw.gov.au/v1'
|
11
|
+
API_ENDPOINT = '/roads/spatial'
|
12
|
+
PARAM_FORMAT = 'geojson'
|
13
|
+
def self.query_string_params(format, table, limit)
|
14
|
+
"?format=#{format}&q=select%20*%20from%20#{table}%20limit%20#{limit}%20"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Trip Planner API
|
19
|
+
module TripPlannerAPI
|
20
|
+
BASE_URL = 'https://api.np.transport.nsw.gov.au/v1'
|
21
|
+
API_ENDPOINT = '/tp/coord'
|
22
|
+
PARAM_FORMAT = 'rapidJSON'
|
23
|
+
def self.query_string_params(format, coord_lat = '-33.8688', coord_long = '151.2093', coord_radius = '1000')
|
24
|
+
"?outputFormat=#{format}&coord=#{coord_long}%3A#{coord_lat}%3AEPSG%3A4326&inclFilter=1&" +
|
25
|
+
"type_1=GIS_POINT&radius_1=#{coord_radius}&PoisOnMapMacro=true&version=10.2.1.42"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
class OpenDataAPIRequest
|
2
|
+
attr_reader :request, :api_key
|
3
|
+
|
4
|
+
@@api_key = ''
|
5
|
+
@@uri_base = ''
|
6
|
+
@@http_base = ''
|
7
|
+
|
8
|
+
def initialize(http, uri, api_key)
|
9
|
+
@http = http
|
10
|
+
@uri = uri
|
11
|
+
@api_key = api_key
|
12
|
+
@request = self.generate_request_for_api(uri, api_key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.api_key()
|
16
|
+
@@api_key
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.set_api_key(api_key)
|
20
|
+
@@api_key = api_key
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.uri_base()
|
24
|
+
@@uri_base
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.set_uri_base(uri_base)
|
28
|
+
@@uri_base = uri_base
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.http_base()
|
32
|
+
@@http_base
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.set_http_base(http_base)
|
36
|
+
@@http_base = http_base
|
37
|
+
end
|
38
|
+
|
39
|
+
def generate_request_for_api(uri, api_key)
|
40
|
+
# puts "Generating Request for URI: #{uri.to_s}\nURI Host/Port: #{uri.host}, #{uri.port}"
|
41
|
+
request = Net::HTTP::Get.new(uri)
|
42
|
+
|
43
|
+
request.initialize_http_header({
|
44
|
+
"Accept" => "application/json",
|
45
|
+
"Content-Type" => "application/json",
|
46
|
+
"Authorization" => "apikey #{api_key}",
|
47
|
+
"User-Agent" => "ruby/net::http"
|
48
|
+
})
|
49
|
+
# puts "Generated Request with Headers: #{request.to_hash.inspect}"
|
50
|
+
request
|
51
|
+
end
|
52
|
+
|
53
|
+
# Fetch specific request
|
54
|
+
def fetch(http_session, request, limit = 10)
|
55
|
+
raise "Too many HTTP redirects" if limit == 0
|
56
|
+
response = http_session.request(request) # Net::HTTPResponse object
|
57
|
+
|
58
|
+
case response
|
59
|
+
when Net::HTTPSuccess then
|
60
|
+
if response['content-type'] =~ /json/i
|
61
|
+
# puts """Response:\n\t
|
62
|
+
# Code: #{response.code}\n\t
|
63
|
+
# Message: #{response.message}\n\t
|
64
|
+
# Class: #{response.class.name}\n\t
|
65
|
+
# Headers: \n #{JSON.pretty_generate(response.to_hash)}
|
66
|
+
# Body: \n #{JSON.pretty_generate(JSON.parse(response.body))}
|
67
|
+
# """
|
68
|
+
# puts "Response code #{response.code} for request to: #{request.uri}"
|
69
|
+
response
|
70
|
+
else
|
71
|
+
raise Exception.new("Only JSON response supported")
|
72
|
+
end
|
73
|
+
when Net::HTTPRedirection then
|
74
|
+
location = response['location']
|
75
|
+
# puts Net::HTTP.get(URI.parse(location))
|
76
|
+
warn "Redirected to #{location}"
|
77
|
+
request = Net::HTTP::Get.new(location)
|
78
|
+
self.fetch(http_session, request, limit - 1)
|
79
|
+
else
|
80
|
+
raise Exception.new("Unsupported HTTP Response #{response.inspect}")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: opendata-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Luke Schoen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDdDCCAlygAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMRIwEAYDVQQDDAlsdGZz
|
14
|
+
Y2hvZW4xFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
|
15
|
+
bTAeFw0xNzEyMjIwNTUxMTVaFw0xODEyMjIwNTUxMTVaMEAxEjAQBgNVBAMMCWx0
|
16
|
+
ZnNjaG9lbjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYD
|
17
|
+
Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvvj7phLRWC1L2w4j
|
18
|
+
ZVkfFvZXKo/07aDPvch+oHiHfTwaCnxVrSLAKJmx2TjVrJlVkJfIA9hOhHksWvzJ
|
19
|
+
jihVNhscy1O/6zTP62peu0BVg7PFEGtXqljMSSEKuJOfq33vCp0dVXBZ6mOYebCE
|
20
|
+
0qv5XRNi4pFHLcdccOu3Kt5KKlXPt9QaeLIEvbe6PSLCoP3iuchgVsX0uV/av8U/
|
21
|
+
l983GW73fdiHaSaIAlzOgBlNEEYKk39DE/5JkT7fIQV++KGVcQegQG5xbbwKzXNL
|
22
|
+
cs+FDku1z6iTx5s+dPe5P3vC58YW+JUc+cRLotQDvVwL4SQi/UT4Bpmm20Aa8n6N
|
23
|
+
AAI1KwIDAQABo3kwdzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQU
|
24
|
+
Na7MnwCNDJXxjxzj4YnsfFJh9mYwHgYDVR0RBBcwFYETbHRmc2Nob2VuQGdtYWls
|
25
|
+
LmNvbTAeBgNVHRIEFzAVgRNsdGZzY2hvZW5AZ21haWwuY29tMA0GCSqGSIb3DQEB
|
26
|
+
BQUAA4IBAQBfQvJI8uICi7Q0aEecxTI69lYW9HWWpkfkcohriNoC2t0DipKUB6vl
|
27
|
+
U12RzmfUctLPDOymMechUgu22FneFFSP0zN1ajehbWDUPNTw/KKW8eL9rsQtbs/4
|
28
|
+
hvd0fQGfAfRBGs2S6OJ78bD/R9elp1nTz0C/hmuKc88DNnVOIizBb/40mjH8FgSO
|
29
|
+
U6WBxl3dGZ/mzbvLKjVpRoG0P1CdhDXkHScpBbAvfLwm2W1wsB2EQckKKIfMWflp
|
30
|
+
ewIPdCDEuyq9+uvAyBA8yqLcFO22IV+tO5sVQlK176dm/YMu/4XahSgWWabxb3M5
|
31
|
+
i1pV9bobg0pMrHjsh9BCO8rI+hKrNudb
|
32
|
+
-----END CERTIFICATE-----
|
33
|
+
date: 2017-12-22 00:00:00.000000000 Z
|
34
|
+
dependencies: []
|
35
|
+
description: Wrapper for Transport for New South Wales (TfNSW) Open Data APIs
|
36
|
+
email: ltfschoen@gmail.com
|
37
|
+
executables: []
|
38
|
+
extensions: []
|
39
|
+
extra_rdoc_files: []
|
40
|
+
files:
|
41
|
+
- lib/opendata-api.rb
|
42
|
+
- lib/opendata-api/config.rb
|
43
|
+
- lib/opendata-api/request.rb
|
44
|
+
homepage: https://github.com/ltfschoen/opendata-api
|
45
|
+
licenses:
|
46
|
+
- MIT
|
47
|
+
metadata: {}
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 2.1.0
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.2.0
|
62
|
+
requirements: []
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 2.6.14
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: OpenData API
|
68
|
+
test_files: []
|
metadata.gz.sig
ADDED
Binary file
|