Web Service Deployment
Introducation
We have talked about Web services many times, and we have learned how to access to them. Today, we will learn how to implement and deploy Web services.
Almost every modern programming language has some frameworks to support the server side implementation for Web services. In Python, Django is a full-powered web-framework with supports of database access, models and views. However, to simplify the steps in this tutorial, we will use a micro framework Bottle to carry out the practice. If you are interested, there are several other choices of micro framework, including Flask and CheeryPy.
You can find all information about Bottle here: http://bottlepy.org/docs/dev/
Bottle is a fast, simple and lightweight WSGI micro web-framework for Python. It is distributed as a single file module and has no dependencies other than the Python Standard Library. Therefore, there is no need for any installation.
Download and copy file bottle.py to the same folder in which all your source files in this tutorial are located.
Let’s test the framework with a basic “Hello World” Example. Create “server.py” in the same folder with the following content:
from bottle import route, run
@route('/hello') def hello(): return "Hello World!"
run(host='localhost', port=8080, debug=True) |
![]() |
Run this script, visit http://localhost:8080/hello and you will see “Hello World!” in your browser. Try to visit other URLs, such as http://localhost:8080 and http://localhost:8080/test
Here is how it works:
The route() decorator matches a URL to a Python function. In this case, we link the /hello path to the hello() function. This is called a route (hence the decorator name) and is the most important concept of this framework. You can define as many routes as you want. Whenever a browser requests a URL, the associated function is called and the return value is sent back to the browser.
The run() call in the last line starts a built-in development server. It runs on localhost port 8080 and serves requests until you hit Control-c.
The Debug Mode is very helpful during early development, but should be switched off for public applications.
Use “Control-c” to terminate the server.
The route() decorator links an URL path to a callback function.
Routes that contain wildcards are called dynamic routes (as opposed to static routes) and match more than one URL at the same time.
@route('/hello') def hello(): return "Hello World!"
@route('/hello/ def greet(name='Stranger'): return "Hello " + name + ", how are you?" |
A simple wildcard consists of a name enclosed in angle brackets (e.g.
/hello/bob, but not for /hello, /hello/ or /hello/mr/smith.
Each wildcard passes the covered part of the URL as a keyword argument to the request callback. You can use them right away and implement RESTful, nice-looking and meaningful URLs with ease. Here are some other examples along with the URLs they’d match:
# matches /wiki/Learning_Python @route('/wiki/ def show_wiki_page(pagename): ...
# matches /follow/defnull @route('/ ... |
Cookies, HTTP header, HTML <form> fields and other request data is available through the global request object.
All HTTP headers sent by the client are accessible through the request.headers attribute.
from bottle import route, request @route('/is_ajax') def is_ajax(): if request.headers.get('X-Requested-With') == 'XMLHttpRequest': return 'This is an AJAX request' else: return 'This is a normal request' |
![]() |
The query string (as in /forum?id=1&page=5) is commonly used to transmit a small number of key/value pairs to the server. You can use
the request.query attribute to access these values and
the request.query_string attribute to get the whole string.
from bottle import route, request @route('/forum') def display_forum(): forum_id = request.query.id page = request.query.page or '1' return 'Forum ID: ' + forum_id + ' page ' + page |
![]() |
-
_Handling">HTML <FORM> Handling
In HTML, a typical <form> looks something like this:
<form action="/login" method="post"> Username: <input name="username" type="text" /> Password: <input name="password" type="password" /> <input value="Login" type="submit" /> </form> |
The action attribute specifies the URL that will receive the form data. method defines the HTTP method to use (GET or POST).
With method="get" the form values are appended to the URL and available through request.query as described above. This is considered insecure and has other limitations, so we use method="post" here. If in doubt, use POST forms.
Form fields transmitted via POST are stored in request.forms.
from bottle import route, request
@route('/login') def login(): return ''' <form action="/login" method="post"> Username: <input name="username" type="text" /> Password: <input name="password" type="password" /> <input value="Login" type="submit" /> </form> '''
@route('/login', method='POST') def do_login(): username = request.forms.get('username') password = request.forms.get('password') if check_login(username, password): return " Your login information was correct. else: return " Login failed. |
Your login information was correct. " else: return "Login failed. " " src="file:///C:\\Users\\PC\\AppData\\Local\\Temp\\msohtmlclip1\\01\\clip_image013.gif" style="height:440px; width:543px" /> |
Based on the introduction to Bottle framework, try to implement the following two RESTful Web services:
-
- Accept the following route: /books
- Accept a booksXML document into your web service
- parse it and separate the author into first name, middle name and last name. Add these elements as we did in a previous tutorial, and
- store the adjusted XML document as an XML file in your root directory.
- Create an AJAX GET web query: /books?booksXML=[bookstore xml document] to send the books web service you created.
- Accept the following route: /books
-
- Accept the following route: /getbook/
- Accept the booktitle and look for and extract that title in your stored Booklist XML file
- return appropriate book document as an XML document
- Create a AJAX GET web query: /getbook/[book title] to retrieve the book title you are looking for
- extract and display the book title and author name on the web page.
- Accept the following route: /getbook/
HINTS:
- Base your new html page on your RESTful AJAX from previous tutorial.
- in the html file and inside your JavaScript [removed] create a variable to hold your XML document as a string (take out all the attributes – makes it easier)
- include this variable in your AJAX Get web query
as part of your python Web Service route() function you will require the following before your return statement:
response.headers['Access-Control-Allow-Origin'] = '*' response.headers['Content-type'] = 'application/xml' return [your return data] |
![]() |
- http://bottlepy.org/docs/dev/tutorial.htm
- http://isbullsh.it/2011/11/Python-micro-frameworks/