blob: 641a855109108d5c7f0a8ef5de18de638488c5d5 [file] [log] [blame]
#!/usr/bin/ruby
#
# Copyright Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require 'webrick'
require 'json'
require 'net/http'
if ARGV.length < 1 then
puts "usage: #{$PROGRAM_NAME} port"
exit(-1)
end
port = Integer(ARGV[0])
server = WEBrick::HTTPServer.new :BindAddress => '*', :Port => port
trap 'INT' do server.shutdown end
server.mount_proc '/health' do |req, res|
res.status = 200
res.body = {'status' => 'Details is healthy'}.to_json
res['Content-Type'] = 'application/json'
end
server.mount_proc '/details' do |req, res|
pathParts = req.path.split('/')
headers = get_forward_headers(req)
begin
begin
id = Integer(pathParts[-1])
rescue
raise 'please provide numeric product id'
end
details = get_book_details(id, headers)
res.body = details.to_json
res['Content-Type'] = 'application/json'
rescue => error
res.body = {'error' => error}.to_json
res['Content-Type'] = 'application/json'
res.status = 400
end
end
# TODO: provide details on different books.
def get_book_details(id, headers)
if ENV['ENABLE_EXTERNAL_BOOK_SERVICE'] === 'true' then
# the ISBN of one of Comedy of Errors on the Amazon
# that has Shakespeare as the single author
isbn = '0486424618'
return fetch_details_from_external_service(isbn, id, headers)
end
return {
'id' => id,
'author': 'William Shakespeare',
'year': 1595,
'type' => 'paperback',
'pages' => 200,
'publisher' => 'PublisherA',
'language' => 'English',
'ISBN-10' => '1234567890',
'ISBN-13' => '123-1234567890'
}
end
def fetch_details_from_external_service(isbn, id, headers)
uri = URI.parse('https://www.googleapis.com/books/v1/volumes?q=isbn:' + isbn)
http = Net::HTTP.new(uri.host, ENV['DO_NOT_ENCRYPT'] === 'true' ? 80:443)
http.read_timeout = 5 # seconds
# DO_NOT_ENCRYPT is used to configure the details service to use either
# HTTP (true) or HTTPS (false, default) when calling the external service to
# retrieve the book information.
#
# Unless this environment variable is set to true, the app will use TLS (HTTPS)
# to access external services.
unless ENV['DO_NOT_ENCRYPT'] === 'true' then
http.use_ssl = true
end
request = Net::HTTP::Get.new(uri.request_uri)
headers.each { |header, value| request[header] = value }
response = http.request(request)
json = JSON.parse(response.body)
book = json['items'][0]['volumeInfo']
language = book['language'] === 'en'? 'English' : 'unknown'
type = book['printType'] === 'BOOK'? 'paperback' : 'unknown'
isbn10 = get_isbn(book, 'ISBN_10')
isbn13 = get_isbn(book, 'ISBN_13')
return {
'id' => id,
'author': book['authors'][0],
'year': book['publishedDate'],
'type' => type,
'pages' => book['pageCount'],
'publisher' => book['publisher'],
'language' => language,
'ISBN-10' => isbn10,
'ISBN-13' => isbn13
}
end
def get_isbn(book, isbn_type)
isbn_dentifiers = book['industryIdentifiers'].select do |identifier|
identifier['type'] === isbn_type
end
return isbn_dentifiers[0]['identifier']
end
def get_forward_headers(request)
headers = {}
# Keep this in sync with the headers in productpage and reviews.
incoming_headers = [
# All applications should propagate x-request-id. This header is
# included in access log statements and is used for consistent trace
# sampling and log sampling decisions in Istio.
'x-request-id',
# Lightstep tracing header. Propagate this if you use lightstep tracing
# in Istio (see
# https://istio.io/latest/docs/tasks/observability/distributed-tracing/lightstep/)
# Note: this should probably be changed to use B3 or W3C TRACE_CONTEXT.
# Lightstep recommends using B3 or TRACE_CONTEXT and most application
# libraries from lightstep do not support x-ot-span-context.
'x-ot-span-context',
# Datadog tracing header. Propagate these headers if you use Datadog
# tracing.
'x-datadog-trace-id',
'x-datadog-parent-id',
'x-datadog-sampling-priority',
# W3C Trace Context. Compatible with OpenCensusAgent and Stackdriver Istio
# configurations.
'traceparent',
'tracestate',
# Cloud trace context. Compatible with OpenCensusAgent and Stackdriver Istio
# configurations.
'x-cloud-trace-context',
# Grpc binary trace context. Compatible with OpenCensusAgent nad
# Stackdriver Istio configurations.
'grpc-trace-bin',
# b3 trace headers. Compatible with Zipkin, OpenCensusAgent, and
# Stackdriver Istio configurations.
'x-b3-traceid',
'x-b3-spanid',
'x-b3-parentspanid',
'x-b3-sampled',
'x-b3-flags',
# Application-specific headers to forward.
'end-user',
'user-agent',
]
request.each do |header, value|
if incoming_headers.include? header then
headers[header] = value
end
end
return headers
end
server.start