CSE 190M Web Programming

Lecture 20: Web Services

Reading: none

Except where otherwise noted, the contents of this document are Copyright 2012 Marty Stepp, Jessica Miller, Victoria Kirst and Roy McElmurry IV. All rights reserved. Any redistribution, reproduction, transmission, or storage of part or all of the contents in any form is prohibited without the author's expressed written permission.

Valid HTML5 Valid CSS

What is "Web 2.0"?

web 2.0

What is a web service?

web service: software functionality that can be invoked through the internet using common protocols

Setting content type with header

header("Content-type: type/subtype");
header("Content-type: text/plain");
print "This output will appear as plain text now!\n";

Recall: Content ("MIME") types

MIME type related file extension
application/json
text/plain.txt
text/html.html, .htm, ...
text/xml.xml
text/css.css
text/javascript.js
image/gif.gif

Example: Exponent web service

Using header to redirect between pages

header("Location: url");
if (!user_is_logged_in()) {
	header("Location: user-login.php");
}

Exercise: Baby name web service

  • Write a web service that accepts a name and gender and finds and outputs the line from text file rank.txt with information about that name
    Aaron m 147 193 187 199 250 237 230 178 52 34 34 41 55
    Lisa f 0 0 0 0 0 733 220 6 2 16 64 295 720
    ...
    
    For the following call:
    http://example.com/babynames.php?name=Lisa&gender=f
    
    The service should output the following line:
    Lisa f 0 0 0 0 0 733 220 6 2 16 64 295 720
    

What about errors?

Reporting errors

Using headers for HTTP error codes

header("HTTP/1.1  code  description");
if ($_GET["foo"] != "bar") {
	# I am not happy with the value of foo; this is an error
	header("HTTP/1.1 400 Invalid Request");
	die("An HTTP error 400 (invalid request) occurred.");
}
if (!file_exists($input_file_path)) {
	header("HTTP/1.1 404 File Not Found");
	die("HTTP error 404 occurred: File not found ($input_file_path)");
}

Checking for a mandatory query parameter

function get_query_param($name) {
	if (!isset($_GET[$name])) {
		header("HTTP/1.1 400 Invalid Request");
		die("HTTP/1.1 400 Invalid Request: missing required parameter '$name'");
	}
	if ($_GET[$name] == "") {
		header("HTTP/1.1 400 Invalid Request");
		die("HTTP/1.1 400 Invalid Request: parameter '$name' must be non-empty");
	}
	return $_GET[$name];
}

Exercise: Baby Names errors

  • Report a 400 Invalid Request error if the correct parameters are not passed
  • Report a 410 Gone error if the specified name and gender do not exist

The $_SERVER superglobal array

index description example
$_SERVER["SERVER_NAME"] name of this web server "webster.cs.washington.edu"
$_SERVER["SERVER_ADDR"] IP address of web server "128.208.179.154"
$_SERVER["REMOTE_HOST"] user's domain name "hsd1.wa.comcast.net"
$_SERVER["REMOTE_ADDR"] user's IP address "57.170.55.93"
$_SERVER["HTTP_USER_AGENT"] user's web browser "Mozilla/5.0 (Windows; ..."
$_SERVER["HTTP_REFERER"] where user was before this page "http://www.google.com/"
$_SERVER["REQUEST_METHOD"] HTTP method used to contact server "GET" or "POST"

GET or POST?

if ($_SERVER["REQUEST_METHOD"] == "GET") {
	# process a GET request
	...
} elseif ($_SERVER["REQUEST_METHOD"] == "POST") {
	# process a POST request
	...
}

Emitting partial-page HTML data

# suppose my web service accepts a "type" query parameter ...
<?php if ($_GET["type"] == "html") { ?>
	<ul>
		<?php foreach ($students as $kid) { ?>
			<li> <?= $kid ?> </li>
		<?php } ?>
	</ul>
<?php } ?>

Exercise: Baby Names HTML

  • Add a format parameter to the web service
  • If format is html output HTML instead of the line of text. The service should output HTML in the following format:
    <h1>Aaron: m</h1>
    <ul>
    	<li>1890: 147</li>
    	<li>1900: 193</li>
    	...
    </ul>
    

Emitting XML data manually

...
header("Content-type: text/xml");
print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
print "<books>\n";
foreach ($books as $book) {
	print "  <book title=\"{$book['title']}\" author=\"{$book['author']}\" />\n";
}
print "</books>\n";

PHP's XML DOM: DOMDocument

The PHP DOMDocument class represents an XML document. It has these methods:

createElement(tag) create a new element node to add to the document
createTextNode(text) create a new text node to add to the document
getElementById(id),
getElementsByTagName(tag)
search for elements in the document
load(filename),
loadXML(string)
read XML data from a file on disk or from a string
save(filename),
saveXML()
write XML data to a file on disk or returns it as a string
validate() return whether the current document consists of valid XML data

PHP's XML DOM: DOMElement

The PHP DOMElement class represents each DOM element. It has these fields/methods:

tagName, nodeValue node's name (tag) and value (text)
parentNode, childNodes,
firstChild, lastChild,
previousSibling, nextSibling
references to nearby nodes
appendChild(DOMNode),
insertBefore(newNode, oldNode),
removeChild(DOMNode)
manipulate this node's list of children
getElementsByTagName(tag) search for descendent elements within this element
getAttribute(name),
setAttribute(name, value),
removeAttribute(name)
get/set the value of an attribute on this tag

PHP XML DOM example

...
$xmldoc = new DOMDocument();                          # <?xml version="1.0"?>
$books_tag = $xmldoc->createElement("books");
$xmldoc->appendChild($books_tag);                     # <books>
foreach ($books as $book) {
	$book_tag = $xmldoc->createElement("book");         #   <book
	$book_tag->setAttribute("title", $book["title"]);   #    title="Harry Potter" />
	$book_tag->setAttribute("author", $book["author"]); #    author="J.K. Rowling" />
	$books_tag->appendChild($book_tag);
}                                                     # </books>
header("Content-type: text/xml");
print $xmldoc->saveXML();

Exercise: Baby Names XML

  • If format is xml output XML instead of the line of text. The service should output XML in the following format:
    <?xml version="1.0" encoding="UTF-8"?>
    <baby name="Morgan" gender="m">
    	<rank year="1890">375</rank>
    	<rank year="1900">410</rank>
    	...
    	<rank year="2010">518</rank>
    </baby>
    

Emitting JSON data manually

...
header("Content-type: application/json");
print "{\n";
print "  \"books\": [\n";
foreach ($books as $book) {
	print "  {\"title\": \"$title\"}\n";
}
print "\n";

PHP's JSON functions

PHP includes the following global functions for interacting with JSON data:

json_decode(string) parses the given JSON data string and returns an equivalent associative array object (like JSON.parse in JavaScript)
json_encode(object) returns JSON equivalent for the given object or array or value (like JSON.stringify in JavaScript)

PHP JSON example

<?php
$data = array(
	"library" => "Odegaard",
	"category" => "fantasy",
	"year" => 2012,
	"books" => array(
		array("title" => "Harry Potter", "author" => "J.K. Rowling"),
		array("title" => "The Hobbit", "author" => "J.R.R. Tolkien"),
		array("title" => "Game of Thrones", "author" => "George R. R. Martin"),
		array("title" => "Dragons of Krynn", "author" => "Margaret Weis"),
	)
);

header("Content-type: application/json");
print json_encode($data);
?>

PHP JSON example - output

{
	"library": "Odegaard",
	"category": "fantasy",
	"year": 2012,
	"books": [
		{"title": "Harry Potter", "author": "J.K. Rowling"},
		{"title": "The Hobbit", "author": "J.R.R. Tolkien"},
		{"title": "Game of Thrones", "author": "George R. R. Martin"},
		{"title": "Dragons of Krynn", "author": "Margaret Weis"},
	]
}

Exercise: Baby Names JSON

  • If format is json output JSON instead of the line of text. The service should output JSON in the following format:
    {
    	name: "Morgan",
    	gender: "m",
    	rankings: [375, 410, 392, 478, 579, 507,
    			636, 499, 446, 291, 278, 332, 518]
    }
    

Baby Names Formats

We built a web service that outputs several types of data formats: