Design, implement, and test a network application that maintains an on-line phon
ID: 3918681 • Letter: D
Question
Design, implement, and test a network application that maintains an on-line phone book. The data model for the phone book is saved in a file on the server’s computer. Clients should be able to look up a person’s phone number or add a name and number to the phone book. The server should handle multiple clients without delays. Unlike the doctor program (Case Study), there should be just one phone book that all clients share. The server creates this object at start-up and passes it to the client handlers.
Enclosed are python code that you might need to perform this project.
Deliverables: Must submit your python code for Client, server , multi-handler and phone-book code.
Explanation / Answer
SOLUTION:
According to the given data the following code is shown:
from argparse import ArgumentParser
from collections import namedtuple
from contextlib import closing
from io import BytesIO
from json import dumps as json_encode
import os
import sys
if sys.version_info >= (3, 0):
from http.server import BaseHTTPRequestHandler, HTTPServer
from socketserver import ThreadingMixIn
from urllib.parse import parse_qs
else:
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from SocketServer import ThreadingMixIn
from urlparse import parse_qs
from boto3 import Session
from botocore.exceptions import BotoCoreError, ClientError
ResponseStatus = namedtuple("HTTPStatus",
["code", "message"])
ResponseData = namedtuple("ResponseData",
["status", "content_type", "data_stream"])
AUDIO_FORMATS = {"ogg_vorbis": "audio/ogg",
"mp3": "audio/mpeg",
"pcm": "audio/wave; codecs=1"}
CHUNK_SIZE = 1024
HTTP_STATUS = {"OK": ResponseStatus(code=200, message="OK"),
"BAD_REQUEST": ResponseStatus(code=400, message="Bad request"),
"NOT_FOUND": ResponseStatus(code=404, message="Not found"),
"INTERNAL_SERVER_ERROR": ResponseStatus(code=500, message="Internal server error")}
PROTOCOL = "http"
ROUTE_INDEX = "/index.html"
ROUTE_VOICES = "/voices"
ROUTE_READ = "/read"
session = Session(profile_name="adminuser")
polly = session.client("polly")
class HTTPStatusError(Exception):
"""Exception wrapping a value from http.server.HTTPStatus"""
def __init__(self, status, description=None):
"""
Constructs an error instance from a tuple of
(code, message, description), see http.server.HTTPStatus
"""
super(HTTPStatusError, self).__init__()
self.code = status.code
self.message = status.message
self.explain = description
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""An HTTP Server that handle each request in a new thread"""
daemon_threads = True
class ChunkedHTTPRequestHandler(BaseHTTPRequestHandler):
""""HTTP 1.1 Chunked encoding request handler"""
protocol_version = "HTTP/1.1"
def query_get(self, queryData, key, default=""):
"""Helper for getting values from a pre-parsed query string"""
return queryData.get(key, [default])[0]
def do_GET(self):
"""Handles GET requests"""
path, _, query_string = self.path.partition('?')
query = parse_qs(query_string)
response = None
print(u"[START]: Received GET for %s with query: %s" % (path, query))
try:
# Handle the possible request paths
if path == ROUTE_INDEX:
response = self.route_index(path, query)
elif path == ROUTE_VOICES:
response = self.route_voices(path, query)
elif path == ROUTE_READ:
response = self.route_read(path, query)
else:
response = self.route_not_found(path, query)
self.send_headers(response.status, response.content_type)
self.stream_data(response.data_stream)
except HTTPStatusError as err:
if sys.version_info >= (3, 0):
self.send_error(err.code, err.message, err.explain)
else:
self.send_error(err.code, err.message)
self.log_error(u"%s %s %s - [%d] %s", self.client_address[0],
self.command, self.path, err.code, err.explain)
print("[END]")
def route_not_found(self, path, query):
"""Handles routing for unexpected paths"""
raise HTTPStatusError(HTTP_STATUS["NOT_FOUND"], "Page not found")
def route_index(self, path, query):
"""Handles routing for the application's entry point'"""
try:
return ResponseData(status=HTTP_STATUS["OK"], content_type="text_html",
data_stream=open(os.path.join(sys.path[0],
path[1:]), "rb"))
except IOError as err:
raise HTTPStatusError(HTTP_STATUS["INTERNAL_SERVER_ERROR"],
str(err))
def route_voices(self, path, query):
"""Handles routing for listing available voices"""
params = {}
voices = []
while True:
try:
response = polly.describe_voices(**params)
except (BotoCoreError, ClientError) as err:
# The service returned an error
raise HTTPStatusError(HTTP_STATUS["INTERNAL_SERVER_ERROR"],
str(err))
voices.extend(response.get("Voices", []))
if "NextToken" in response:
params = {"NextToken": response["NextToken"]}
else:
break
json_data = json_encode(voices)
bytes_data = bytes(json_data, "utf-8") if sys.version_info >= (3, 0)
else bytes(json_data)
return ResponseData(status=HTTP_STATUS["OK"],
content_type="application/json",
data_stream=BytesIO(bytes_data))
def route_read(self, path, query):
"""Handles routing for reading text (speech synthesis)"""
text = self.query_get(query, "text")
voiceId = self.query_get(query, "voiceId")
outputFormat = self.query_get(query, "outputFormat")
if len(text) == 0 or len(voiceId) == 0 or
outputFormat not in AUDIO_FORMATS:
raise HTTPStatusError(HTTP_STATUS["BAD_REQUEST"],
"Wrong parameters")
else:
try:
response = polly.synthesize_speech(Text=text,
VoiceId=voiceId,
OutputFormat=outputFormat)
except (BotoCoreError, ClientError) as err:
raise HTTPStatusError(HTTP_STATUS["INTERNAL_SERVER_ERROR"],
str(err))
return ResponseData(status=HTTP_STATUS["OK"],
content_type=AUDIO_FORMATS[outputFormat],
data_stream=response.get("AudioStream"))
def send_headers(self, status, content_type):
"""Send out the group of headers for a successful request"""
self.send_response(status.code, status.message)
self.send_header('Content-type', content_type)
self.send_header('Transfer-Encoding', 'chunked')
self.send_header('Connection', 'close')
self.end_headers()
def stream_data(self, stream):
"""Consumes a stream in chunks to produce the response's output'"""
print("Streaming started...")
if stream:
with closing(stream) as managed_stream:
while True:
data = managed_stream.read(CHUNK_SIZE)
self.wfile.write(b"%X %s " % (len(data), data))
if not data:
break
self.wfile.flush()
print("Streaming completed.")
else:
self.wfile.write(b"0 ")
print("Nothing to stream.")
cli = ArgumentParser(description='Example Python Application')
cli.add_argument(
"-p", "--port", type=int, metavar="PORT", dest="port", default=8000)
cli.add_argument(
"--host", type=str, metavar="HOST", dest="host", default="localhost")
arguments = cli.parse_args()
# If the module is invoked directly, initialize the application
if __name__ == '__main__':
server = ThreadedHTTPServer((arguments.host, arguments.port),
ChunkedHTTPRequestHandler)
print("Starting server, use <Ctrl-C> to stop...")
print(u"Open {0}://{1}:{2}{3} in a web browser.".format(PROTOCOL,
arguments.host,
arguments.port,
ROUTE_INDEX))
try:
server.serve_forever()
except KeyboardInterrupt:
print(" Shutting down...")
server.socket.close()
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.