tfl_api_client 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
- data/.gitignore +37 -0
- data/.travis.yml +29 -0
- data/CHANGELOG.md +9 -0
- data/CONTRIBUTING.md +62 -0
- data/GETTING_STARTED.md +161 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +62 -0
- data/Rakefile +30 -0
- data/lib/tfl_api_client/bike_point.rb +105 -0
- data/lib/tfl_api_client/client.rb +235 -0
- data/lib/tfl_api_client/exceptions.rb +91 -0
- data/lib/tfl_api_client/version.rb +28 -0
- data/lib/tfl_api_client.rb +33 -0
- data/spec/cassettes/bike_point/authorised_client_location.yml +83 -0
- data/spec/cassettes/bike_point/authorised_client_locations.yml +8179 -0
- data/spec/cassettes/bike_point/authorised_client_locations_within_bounding_box.yml +402 -0
- data/spec/cassettes/bike_point/authorised_client_locations_within_locus.yml +106 -0
- data/spec/cassettes/bike_point/authorised_client_search.yml +80 -0
- data/spec/cassettes/bike_point/unauthorised_client_location.yml +50 -0
- data/spec/cassettes/bike_point/unauthorised_client_locations.yml +50 -0
- data/spec/cassettes/bike_point/unauthorised_client_locations_within_bounding_box.yml +50 -0
- data/spec/cassettes/bike_point/unauthorised_client_locations_within_locus.yml +50 -0
- data/spec/cassettes/bike_point/unauthorised_client_search.yml +50 -0
- data/spec/integration/bike_point_spec.rb +158 -0
- data/spec/spec_helper.rb +114 -0
- data/spec/support/coverage.rb +36 -0
- data/spec/support/helpers.rb +81 -0
- data/spec/support/vcr.rb +43 -0
- data/spec/unit/bike_point_spec.rb +87 -0
- data/spec/unit/client_spec.rb +199 -0
- data/tfl_api_client.gemspec +36 -0
- metadata +222 -0
@@ -0,0 +1,235 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2015 Luke Hackett
|
3
|
+
#
|
4
|
+
# MIT License
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
# a copy of this software and associated documentation files (the
|
8
|
+
# "Software"), to deal in the Software without restriction, including
|
9
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
# the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be
|
15
|
+
# included in all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#
|
25
|
+
|
26
|
+
require 'json'
|
27
|
+
require 'logger'
|
28
|
+
require 'openssl'
|
29
|
+
require 'net/http'
|
30
|
+
require 'tfl_api_client/exceptions'
|
31
|
+
|
32
|
+
module TflApi
|
33
|
+
# This is the client class that allows direct access to the subclasses and to
|
34
|
+
# the TFL API. The class contains methods that perform GET and POST requests
|
35
|
+
# to the API.
|
36
|
+
#
|
37
|
+
class Client
|
38
|
+
|
39
|
+
# Parameters that are permitted as options while initializing the client
|
40
|
+
VALID_PARAMS = %w( app_id app_key host logger log_level log_location ).freeze
|
41
|
+
|
42
|
+
# HTTP verbs supported by the Client
|
43
|
+
VERB_MAP = {
|
44
|
+
get: Net::HTTP::Get
|
45
|
+
}
|
46
|
+
|
47
|
+
# Client accessors
|
48
|
+
attr_reader :app_id, :app_key, :host, :logger, :log_level, :log_location
|
49
|
+
|
50
|
+
# Initialize a Client object with TFL API credentials
|
51
|
+
#
|
52
|
+
# @param args [Hash] Arguments to connect to TFL API
|
53
|
+
#
|
54
|
+
# @option args [String] :app_id the application id generated by registering an app with TFL
|
55
|
+
# @option args [String] :app_key the application key generated by registering an app with TFL
|
56
|
+
# @option args [String] :host the API's host url - defaults to api.tfl.gov.uk
|
57
|
+
#
|
58
|
+
# @return [TflApi::Client] a client object to the TFL API
|
59
|
+
#
|
60
|
+
# @raise [ArgumentError] when required options are not provided.
|
61
|
+
#
|
62
|
+
def initialize(args)
|
63
|
+
args.each do |key, value|
|
64
|
+
if value && VALID_PARAMS.include?(key.to_s)
|
65
|
+
instance_variable_set("@#{key.to_sym}", value)
|
66
|
+
end
|
67
|
+
end if args.is_a? Hash
|
68
|
+
|
69
|
+
# Ensure the Application ID and Key is given
|
70
|
+
raise ArgumentError, "Application ID (app_id) is required to interact with TFL's APIs" unless app_id
|
71
|
+
raise ArgumentError, "Application Key (app_key) is required to interact with TFL's APIs" unless app_key
|
72
|
+
|
73
|
+
# Set client defaults
|
74
|
+
@host ||= 'https://api.tfl.gov.uk'
|
75
|
+
@host = URI.parse(@host)
|
76
|
+
|
77
|
+
# Create a global Net:HTTP instance
|
78
|
+
@http = Net::HTTP.new(@host.host, @host.port)
|
79
|
+
@http.use_ssl = true
|
80
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
81
|
+
|
82
|
+
# Logging
|
83
|
+
if @logger
|
84
|
+
raise ArgumentError, 'logger parameter must be a Logger object' unless @logger.is_a?(Logger)
|
85
|
+
raise ArgumentError, 'log_level cannot be set if using custom logger' if @log_level
|
86
|
+
raise ArgumentError, 'log_location cannot be set if using custom logger' if @log_location
|
87
|
+
else
|
88
|
+
@log_level = Logger::INFO unless @log_level
|
89
|
+
@log_location = STDOUT unless @log_location
|
90
|
+
@logger = Logger.new(@log_location)
|
91
|
+
@logger.level = @log_level
|
92
|
+
@logger.datetime_format = '%F T%T%z'
|
93
|
+
@logger.formatter = proc do |severity, datetime, _progname, msg|
|
94
|
+
"[%s] %-6s %s \r\n" % [datetime, severity, msg]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Creates an instance to the BikePoint class by passing a reference to self
|
100
|
+
#
|
101
|
+
# @return [TflApi::Client::BikePoint] An object to BikePoint subclass
|
102
|
+
#
|
103
|
+
def bike_point
|
104
|
+
TflApi::Client::BikePoint.new(self)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Performs a HTTP GET request to the api, based upon the given URI resource
|
108
|
+
# and any additional HTTP query parameters. This method will automatically
|
109
|
+
# inject the mandatory application id and application key HTTP query
|
110
|
+
# parameters.
|
111
|
+
#
|
112
|
+
# @return [hash] HTTP response as a hash
|
113
|
+
#
|
114
|
+
def get(path, query={})
|
115
|
+
request_json :get, path, query
|
116
|
+
end
|
117
|
+
|
118
|
+
# Overrides the inspect method to prevent the TFL Application ID and Key
|
119
|
+
# credentials being shown when the `inspect` method is called. The method
|
120
|
+
# will only print the important variables.
|
121
|
+
#
|
122
|
+
# @return [String] String representation of the current object
|
123
|
+
#
|
124
|
+
def inspect
|
125
|
+
"#<#{self.class.name}:0x#{(self.__id__ * 2).to_s(16)} " +
|
126
|
+
"@host=#{host.to_s}, " +
|
127
|
+
"@log_level=#{log_level}, " +
|
128
|
+
"@log_location=#{log_location.inspect}>"
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
# This method requests the given path via the given resource with the additional url
|
134
|
+
# params. All successful responses will yield a hash of the response body, whilst
|
135
|
+
# all other response types will raise a child of TflApi::Exceptions::ApiException.
|
136
|
+
# For example a 404 response would raise a TflApi::Exceptions::NotFound exception.
|
137
|
+
#
|
138
|
+
# @param method [Symbol] The type of HTTP request to make, e.g. :get
|
139
|
+
# @param path [String] the path of the resource (not including the base url) to request
|
140
|
+
# @param params [Hash]
|
141
|
+
#
|
142
|
+
# @return [HTTPResponse] HTTP response object
|
143
|
+
#
|
144
|
+
# @raise [TflApi::Exceptions::ApiException] when an error has occurred with TFL's API
|
145
|
+
#
|
146
|
+
def request_json(method, path, params)
|
147
|
+
response = request(method, path, params)
|
148
|
+
|
149
|
+
if response.kind_of? Net::HTTPSuccess
|
150
|
+
parse_response_json(response)
|
151
|
+
else
|
152
|
+
raise_exception(response)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Creates and performs HTTP request by the request medium to the given path
|
157
|
+
# with any additional uri parameters. The method will return the HTTP
|
158
|
+
# response object upon completion.
|
159
|
+
#
|
160
|
+
# @param method [Symbol] The type of HTTP request to make, e.g. :get
|
161
|
+
# @param path [String] the path of the resource (not including the base url) to request
|
162
|
+
# @param params [Hash] Additional url params to be added to the request
|
163
|
+
#
|
164
|
+
# @return [HTTPResponse] HTTP response object
|
165
|
+
#
|
166
|
+
def request(method, path, params)
|
167
|
+
full_path = format_request_uri(path, params)
|
168
|
+
request = VERB_MAP[method.to_sym].new(full_path)
|
169
|
+
# TODO - Enable when supporting other HTTP Verbs
|
170
|
+
# request.set_form_data(params) unless method == :get
|
171
|
+
|
172
|
+
@logger.debug "#{method.to_s.upcase} #{path}"
|
173
|
+
@http.request(request)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Returns a full, well-formatted HTTP request URI that can be used to directly
|
177
|
+
# interact with the TFL API.
|
178
|
+
#
|
179
|
+
# @param path [String] the path of the resource (not including the base url) to request
|
180
|
+
# @param params [Hash] Additional url params to be added to the request
|
181
|
+
#
|
182
|
+
# @return [String] Full HTTP request URI
|
183
|
+
#
|
184
|
+
def format_request_uri(path, params)
|
185
|
+
params.merge!({app_id: app_id, app_key: app_key})
|
186
|
+
params_string = URI.encode_www_form(params)
|
187
|
+
URI::HTTPS.build(host: host.host, path: path, query: params_string)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Parses the given response body as JSON, and returns a hash representation of the
|
191
|
+
# the response. Failure to successfully parse the response will result in an
|
192
|
+
# TflApi::Exceptions::ApiException being raised.
|
193
|
+
#
|
194
|
+
# @param response [HTTPResponse] the HTTP response object
|
195
|
+
#
|
196
|
+
# @return [HTTPResponse] HTTP response object
|
197
|
+
#
|
198
|
+
# @raise [TflApi::Exceptions::ApiException] when trying to parse a malformed JSON response
|
199
|
+
#
|
200
|
+
def parse_response_json(response)
|
201
|
+
begin
|
202
|
+
JSON.parse(response.body)
|
203
|
+
rescue JSON::ParserError
|
204
|
+
raise TflApi::Exceptions::ApiException, logger, "Invalid JSON returned from #{host.host}"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Raises a child of TflApi::Exceptions::ApiException based upon the response code being
|
209
|
+
# classified as non-successful, i.e. a non 2xx response code. All non-successful
|
210
|
+
# responses will raise an TflApi::Exceptions::ApiException by default. Popular
|
211
|
+
# non-successful response codes are mapped to internal exceptions, for example a 404
|
212
|
+
# response code would raise TflApi::Exceptions::NotFound.
|
213
|
+
#
|
214
|
+
# @param response [HTTPResponse] the HTTP response object
|
215
|
+
#
|
216
|
+
# @raise [TflApi::Exceptions::ApiException] when an error has occurred with TFL's API
|
217
|
+
#
|
218
|
+
def raise_exception(response)
|
219
|
+
case response.code.to_i
|
220
|
+
when 401
|
221
|
+
raise TflApi::Exceptions::Unauthorized, logger
|
222
|
+
when 403
|
223
|
+
raise TflApi::Exceptions::Forbidden, logger
|
224
|
+
when 404
|
225
|
+
raise TflApi::Exceptions::NotFound, logger
|
226
|
+
when 500
|
227
|
+
raise TflApi::Exceptions::InternalServerError, logger
|
228
|
+
when 503
|
229
|
+
raise TflApi::Exceptions::ServiceUnavailable, logger
|
230
|
+
else
|
231
|
+
raise TflApi::Exceptions::ApiException, logger, "non-successful response (#{response.code}) was returned"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2015 Luke Hackett
|
3
|
+
#
|
4
|
+
# MIT License
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
# a copy of this software and associated documentation files (the
|
8
|
+
# "Software"), to deal in the Software without restriction, including
|
9
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
# the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be
|
15
|
+
# included in all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#
|
25
|
+
|
26
|
+
module TflApi
|
27
|
+
# This module contains classes that define exceptions for various categories.
|
28
|
+
#
|
29
|
+
module Exceptions
|
30
|
+
# This is the base class for Exceptions that is inherited from
|
31
|
+
# RuntimeError.
|
32
|
+
#
|
33
|
+
class ApiException < RuntimeError
|
34
|
+
def initialize(logger, message = '', log_level = Logger::ERROR)
|
35
|
+
logger.add(log_level) { "#{self.class}: #{message}" }
|
36
|
+
super(message)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# This exception class handles cases where invalid credentials are provided
|
41
|
+
# to connect to the TFL API.
|
42
|
+
#
|
43
|
+
class Unauthorized < ApiException
|
44
|
+
def initialize(logger, message = '')
|
45
|
+
message = 'Access denied. Please ensure you have valid TFL credentials.' if message.nil? || message.empty?
|
46
|
+
super(logger, message)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# This exception class handles cases where valid credentials are provided
|
51
|
+
# to connect to the TFL API, but those credentials do not have the access
|
52
|
+
# level to perform the requested task.
|
53
|
+
#
|
54
|
+
class Forbidden < ApiException
|
55
|
+
def initialize(logger, message = '')
|
56
|
+
message = 'Access denied. Your credentials do not permit this request.' if message.nil? || message.empty?
|
57
|
+
super(logger, message, Logger::FATAL)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# This exception class handles cases where a requested resource is not found
|
62
|
+
# on the remote TFL API.
|
63
|
+
#
|
64
|
+
class NotFound < ApiException
|
65
|
+
def initialize(logger, message = '')
|
66
|
+
message = 'Requested resource was not found on the TFL API.' if message.nil? || message.empty?
|
67
|
+
super(logger, message)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# This exception class handles cases where the TFL API returns with a
|
72
|
+
# 500 Internal Server Error.
|
73
|
+
#
|
74
|
+
class InternalServerError < ApiException
|
75
|
+
def initialize(logger, message = '')
|
76
|
+
message = 'TFL API threw an Internal Server Error. Please try again.' if message.nil? || message.empty?
|
77
|
+
super(logger, message)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# This exception class handles cases where the Jenkins is getting restarted
|
82
|
+
# or reloaded where the response code returned is 503
|
83
|
+
#
|
84
|
+
class ServiceUnavailable < ApiException
|
85
|
+
def initialize(logger, message = '')
|
86
|
+
message = 'TFL API is currently unavailable. Please try again.' if message.nil? || message.empty?
|
87
|
+
super(logger, message)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2015 Luke Hackett
|
3
|
+
#
|
4
|
+
# MIT License
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
# a copy of this software and associated documentation files (the
|
8
|
+
# "Software"), to deal in the Software without restriction, including
|
9
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
# the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be
|
15
|
+
# included in all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#
|
25
|
+
|
26
|
+
module TflApi
|
27
|
+
VERSION = '0.1.0'
|
28
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2015 Luke Hackett
|
3
|
+
#
|
4
|
+
# MIT License
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
# a copy of this software and associated documentation files (the
|
8
|
+
# "Software"), to deal in the Software without restriction, including
|
9
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
# the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be
|
15
|
+
# included in all copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
#
|
25
|
+
|
26
|
+
require 'tfl_api_client/version'
|
27
|
+
require 'tfl_api_client/client'
|
28
|
+
require 'tfl_api_client/bike_point'
|
29
|
+
require 'tfl_api_client/exceptions'
|
30
|
+
|
31
|
+
module TflApi
|
32
|
+
# Your code goes here...
|
33
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://api.tfl.gov.uk/BikePoint/BikePoints_10?app_id=TFL_APP_ID&app_key=TFL_APP_KEY
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept-Encoding:
|
11
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
12
|
+
Accept:
|
13
|
+
- "*/*"
|
14
|
+
User-Agent:
|
15
|
+
- Ruby
|
16
|
+
Host:
|
17
|
+
- api.tfl.gov.uk
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Access-Control-Allow-Headers:
|
24
|
+
- Content-Type
|
25
|
+
Access-Control-Allow-Methods:
|
26
|
+
- GET,POST,PUT,DELETE,OPTIONS
|
27
|
+
Access-Control-Allow-Origin:
|
28
|
+
- "*"
|
29
|
+
Age:
|
30
|
+
- '0'
|
31
|
+
Api-Entity-Payload:
|
32
|
+
- Place
|
33
|
+
Cache-Control:
|
34
|
+
- public, must-revalidate, max-age=150, s-maxage=300
|
35
|
+
Content-Type:
|
36
|
+
- application/json; charset=utf-8
|
37
|
+
Date:
|
38
|
+
- Tue, 11 Aug 2015 16:52:37 GMT
|
39
|
+
Server:
|
40
|
+
- Microsoft-IIS/8.5
|
41
|
+
Via:
|
42
|
+
- 1.1 varnish
|
43
|
+
X-Aspnet-Version:
|
44
|
+
- 4.0.30319
|
45
|
+
X-Backend:
|
46
|
+
- api
|
47
|
+
X-Backend-Url:
|
48
|
+
- "/BikePoint/BikePoints_10"
|
49
|
+
X-Banning:
|
50
|
+
- ''
|
51
|
+
X-Cache:
|
52
|
+
- MISS
|
53
|
+
X-Cacheable:
|
54
|
+
- Yes. Cacheable
|
55
|
+
X-Hash-Url:
|
56
|
+
- "/bikepoint/bikepoints_10"
|
57
|
+
X-Ttl:
|
58
|
+
- '300.000'
|
59
|
+
X-Ttl-Rule:
|
60
|
+
- '0'
|
61
|
+
X-Varnish:
|
62
|
+
- 10.75.2.208
|
63
|
+
- '478472446'
|
64
|
+
Content-Length:
|
65
|
+
- '406'
|
66
|
+
Connection:
|
67
|
+
- keep-alive
|
68
|
+
body:
|
69
|
+
encoding: ASCII-8BIT
|
70
|
+
string: '{"$type":"Tfl.Api.Presentation.Entities.Place, Tfl.Api.Presentation.Entities","id":"BikePoints_10","url":"https://api-prod5.tfl.gov.uk/Place/BikePoints_10","commonName":"Park
|
71
|
+
Street, Bankside","placeType":"BikePoint","additionalProperties":[{"$type":"Tfl.Api.Presentation.Entities.AdditionalProperties,
|
72
|
+
Tfl.Api.Presentation.Entities","category":"Description","key":"TerminalName","sourceSystemKey":"BikePoints","value":"001024","modified":"2015-08-11T16:47:52.26"},{"$type":"Tfl.Api.Presentation.Entities.AdditionalProperties,
|
73
|
+
Tfl.Api.Presentation.Entities","category":"Description","key":"Installed","sourceSystemKey":"BikePoints","value":"true","modified":"2015-08-11T16:47:52.26"},{"$type":"Tfl.Api.Presentation.Entities.AdditionalProperties,
|
74
|
+
Tfl.Api.Presentation.Entities","category":"Description","key":"Locked","sourceSystemKey":"BikePoints","value":"false","modified":"2015-08-11T16:47:52.26"},{"$type":"Tfl.Api.Presentation.Entities.AdditionalProperties,
|
75
|
+
Tfl.Api.Presentation.Entities","category":"Description","key":"InstallDate","sourceSystemKey":"BikePoints","value":"1278242460000","modified":"2015-08-11T16:47:52.26"},{"$type":"Tfl.Api.Presentation.Entities.AdditionalProperties,
|
76
|
+
Tfl.Api.Presentation.Entities","category":"Description","key":"RemovalDate","sourceSystemKey":"BikePoints","value":"","modified":"2015-08-11T16:47:52.26"},{"$type":"Tfl.Api.Presentation.Entities.AdditionalProperties,
|
77
|
+
Tfl.Api.Presentation.Entities","category":"Description","key":"Temporary","sourceSystemKey":"BikePoints","value":"false","modified":"2015-08-11T16:47:52.26"},{"$type":"Tfl.Api.Presentation.Entities.AdditionalProperties,
|
78
|
+
Tfl.Api.Presentation.Entities","category":"Description","key":"NbBikes","sourceSystemKey":"BikePoints","value":"11","modified":"2015-08-11T16:47:52.26"},{"$type":"Tfl.Api.Presentation.Entities.AdditionalProperties,
|
79
|
+
Tfl.Api.Presentation.Entities","category":"Description","key":"NbEmptyDocks","sourceSystemKey":"BikePoints","value":"7","modified":"2015-08-11T16:47:52.26"},{"$type":"Tfl.Api.Presentation.Entities.AdditionalProperties,
|
80
|
+
Tfl.Api.Presentation.Entities","category":"Description","key":"NbDocks","sourceSystemKey":"BikePoints","value":"18","modified":"2015-08-11T16:47:52.26"}],"children":[],"lat":51.505974,"lon":-0.092754}'
|
81
|
+
http_version:
|
82
|
+
recorded_at: Tue, 11 Aug 2015 16:52:38 GMT
|
83
|
+
recorded_with: VCR 2.9.3
|