summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Templates.class.php120
-rw-r--r--UrlGenerator.class.php10
-rw-r--r--db.php63
-rw-r--r--endpoint.php1
-rw-r--r--queue.php173
6 files changed, 319 insertions, 49 deletions
diff --git a/.gitignore b/.gitignore
index d040ffe..cf2ceb2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
.*.un~
+.*.swp
diff --git a/Templates.class.php b/Templates.class.php
new file mode 100644
index 0000000..9cfec4f
--- /dev/null
+++ b/Templates.class.php
@@ -0,0 +1,120 @@
+<?php
+
+include_once "db.php";
+
+function apply() {
+ $args = func_get_args();
+ $f = $args[0];
+ $args = array_slice($args, 1);
+ return function() use ($f, $args) {
+ return call_user_func_array($f, $args);
+ };
+}
+
+// Queue List
+
+function template_queue_list_text($url_generator, array $queues) {
+ $count = count($queues);
+?>
+Number of queues: <?=$count?>.
+
+<?php
+ foreach($queues as $q) {
+ echo($q->toPlainText($url_generator) . "\n");
+ }
+}
+
+function template_queue_list_html(UrlGenerator $url_generator, array $queues) {
+ html_default(apply("render_queues", $url_generator, $queues));
+}
+
+function render_queues($url_generator, $queues) {
+ $count = count($queues);
+?>
+<p>
+Number of queues: <?=$count?>.
+</p>
+
+<?php
+ foreach($queues as $q) {
+ echo($q->toHtml($url_generator, FALSE) . "\n");
+ }
+}
+
+
+// Queue
+
+function template_queue_html(UrlGenerator $url_generator, Queue $queue) {
+ html_default(apply("render_queue_html", $url_generator, $queue));
+}
+
+function render_queue_html(UrlGenerator $url_generator, Queue $queue) {
+ echo url_to_a($url_generator->queues(), "All queues");
+ echo $queue->toHtml($url_generator, TRUE);
+}
+
+function template_queue_text(UrlGenerator $url_generator, Queue $queue) {
+ echo($queue->toPlainText($url_generator));
+}
+
+// Item List
+
+function template_item_list_html(UrlGenerator $url_generator, $queue, array $items) {
+ html_default(apply("render_item_list_html", $url_generator, $queue, $items));
+}
+
+function render_item_list_html(UrlGenerator $url_generator, $queue, array $items) {
+ $queue_url = url_to_a($url_generator->queue($queue));
+ $html =
+ "<h1>Items in $queue</h1>" .
+ "<ul>" .
+ "<li>$queue_url</li>" .
+ "<li>Queue has " . count($items) . " items.</li>" .
+ "</ul>";
+ echo $html;
+
+ foreach($items as $item) {
+ echo($item->toHtml($url_generator));
+ }
+}
+
+function template_item_list_text(UrlGenerator $url_generator, $queue, array $items) {
+ echo("This queue has " . count($items) . " items.\n");
+ echo("\n");
+
+ foreach($items as $item) {
+ echo($item->toPlainText($url_generator));
+ echo("\n");
+ }
+}
+
+// Common
+
+function invoke($f) {
+ if(is_callable($f)) {
+ $f();
+ }
+ else {
+ echo($f);
+ }
+}
+
+function html_default($body, $head = NULL) {
+?>
+<html>
+<head>
+<?php
+if($head != NULL) {
+ $head();
+}
+?>
+</head>
+<body>
+<?php
+invoke($body);
+?>
+</body>
+</html>
+<?php
+}
+?>
diff --git a/UrlGenerator.class.php b/UrlGenerator.class.php
index 03c5b14..24aa75e 100644
--- a/UrlGenerator.class.php
+++ b/UrlGenerator.class.php
@@ -6,16 +6,24 @@ class UrlGenerator {
$this->baseurl = $baseurl;
}
+ function queues() {
+ return $this->baseurl . "/queue";
+ }
+
function queue($queue) {
return $this->baseurl . "/queue/" . $queue;
}
+ function queue_items($queue) {
+ return $this->baseurl . "/queue/" . $queue . "/items";
+ }
+
function enqueue($queue) {
return $this->baseurl . "/enqueue/" . $queue;
}
function item($queue, $item) {
- return $this->baseurl . "/item/" . $queue . "/" . $id;
+ return $this->baseurl . "/queue/" . $queue . "/items/" . $item;
}
function item_enclosure($queue, $id) {
diff --git a/db.php b/db.php
index 8cd8bc9..12743e8 100644
--- a/db.php
+++ b/db.php
@@ -1,13 +1,40 @@
<?php
+function url_to_a($url, $title = NULL) {
+ if(!isset($title)) {
+ $title = htmlspecialchars($url);
+ }
+ return "<a href='" . htmlspecialchars($url) . "'>$title</a>";
+}
+
class Queue {
public $name;
public $endpoint_url;
function toPlainText($url_generator) {
return "Name: " . $this->name . "\n" .
+ "Queue URL: " . $url_generator->queue($this->name) . "\n" .
"Endpoint URL: " . (isset($this->endpoint_url) ? $this->endpoint_url : "Not set") . "\n" .
- "Enqueue: " . $url_generator->enqueue($this->name) . "\n";
+ "Enqueue: " . $url_generator->enqueue($this->name) . "\n" .
+ "Items: " . $url_generator->queue_items($this->name) . "\n";
+ }
+
+ function toHtml($url_generator, $detail) {
+ $queue_url = url_to_a($url_generator->queue($this->name));
+ $endpoint = !isset($this->endpoint_url) ? "Not set" : htmlspecialchars($this->endpoint_url);
+ $enqueue_url = url_to_a($url_generator->enqueue($this->name));
+ $items_url = url_to_a($url_generator->queue_items($this->name));
+ $html =
+ "<h2>Queue: $this->name</h2>" .
+ "<table>" .
+ "<tr><td>Queue URL</td><td>$queue_url</td></tr>";
+ if($detail) $html .=
+ "<tr><td>Endpoint URL</td><td>$endpoint</td></tr>" .
+ "<tr><td>Enqueue</td><td>$enqueue_url</td></tr>" .
+ "<tr><td>Items</td><td>$items_url</td></tr>";
+ $html .=
+ "</table>";
+ return $html;
}
static function valid_name($str) {
@@ -39,6 +66,24 @@ class Item {
}
return "Headers:\n" . $headers;
}
+
+ function toHtml($url_generator) {
+ $item_url = url_to_a($url_generator->item($this->queue_name, $this->id));
+ $html =
+ "<h2>Item</h2>" .
+ "<h3>Meta</h3>" .
+ "<ul>" .
+ "<li>Id: $this->id</li>" .
+ "<li>Created: $this->created</li>" .
+ "<li>Link: $item_url</li>" .
+ "</ul>" .
+ "<h3>Headers</h3>" .
+ "<ul>\n";
+ foreach($this->headers as $k => $v) {
+ $html .= "<li>" . $k . ": " . $v . "</li>\n";
+ }
+ return $html . "</ul>\n";
+ }
}
class DB {
@@ -100,7 +145,15 @@ class DB {
$stmt->setFetchMode(PDO::FETCH_CLASS, "Queue");
$stmt->bindParam(":name", $queue);
$stmt->execute();
- return $stmt->fetch(PDO::FETCH_CLASS);
+ $x = $stmt->fetch(PDO::FETCH_CLASS);
+ return $x === FALSE ? NULL : $x;
+ }
+
+ function delete_item($queue_name, $id) {
+ $stmt = $this->db->prepare("DELETE FROM item WHERE queue_name = :queue_name AND id = :id");
+ $stmt->bindParam(":queue_name", $queue_name);
+ $stmt->bindParam(":id", $id);
+ $stmt->execute();
}
function select_item($queue_name, $id) {
@@ -108,7 +161,8 @@ class DB {
$stmt->bindParam(":queue_name", $queue_name);
$stmt->bindParam(":id", $id);
$stmt->execute();
- return $stmt->fetchAll(PDO::FETCH_FUNC, 'item_from_db');
+ $x = $stmt->fetchAll(PDO::FETCH_FUNC, 'item_from_db');
+ return count($x) > 0 ? $x[0] : NULL;
}
function select_items($queue_name, $limit = 10, $offset = 0) {
@@ -117,7 +171,8 @@ class DB {
$stmt->bindParam(":limit", $limit);
$stmt->bindParam(":offset", $offset);
$stmt->execute();
- return $stmt->fetchAll(PDO::FETCH_FUNC, 'item_from_db');
+ $x = $stmt->fetchAll(PDO::FETCH_FUNC, 'item_from_db');
+ return $x;
}
}
diff --git a/endpoint.php b/endpoint.php
index e133c90..b8f9f6c 100644
--- a/endpoint.php
+++ b/endpoint.php
@@ -29,6 +29,7 @@ if(isset($content_length)) {
fwrite($fd, "Content-Length: ". $content_length . "\n");
}
fwrite($fd, "\n");
+fwrite($fd, file_get_contents("php://input"));
fflush($fd);
fclose($fd);
diff --git a/queue.php b/queue.php
index 26d0f30..2c7396f 100644
--- a/queue.php
+++ b/queue.php
@@ -1,6 +1,7 @@
<?php
include_once "db.php";
include_once "UrlGenerator.class.php";
+include_once "Templates.class.php";
header("Content-Type: text/plain");
@@ -12,9 +13,10 @@ function data_file($id) {
return "/tmp/mq/data/$id";
}
-/*
-var_dump($_SERVER);
-*/
+function log_file($id) {
+ return "/tmp/mq/data/" . $id . ".log";
+}
+
$method = $_SERVER["REQUEST_METHOD"];
$content_type = isset($_SERVER["CONTENT_TYPE"]) ? $_SERVER["CONTENT_TYPE"] : NULL;
$db = new DB();
@@ -29,7 +31,7 @@ if(isset($content_type) && $content_type == "application/x-www-form-urlencoded")
list($key, $value) = split("=", $part);
$form[$key] = $value;
}
- var_dump($form);
+// var_dump($form);
}
$path_info = $_SERVER["PATH_INFO"];
@@ -41,7 +43,10 @@ else {
$path_info = preg_replace('/[\/]$/', '', $path_info);
$path_info = preg_replace('/^[\/]/', '', $path_info);
$segments = explode("/", $path_info);
- $baseurl = "http://" . $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["SCRIPT_NAME"];
+// var_dump($segments);
+ $port = $_SERVER["SERVER_PORT"];
+ $port = $port == "80" ? "" : ":" . $port;
+ $baseurl = "http://" . $_SERVER["SERVER_NAME"] . $port . $_SERVER["SCRIPT_NAME"];
$url_generator = new UrlGenerator($baseurl);
switch($segments[0]) {
case "enqueue":
@@ -51,20 +56,23 @@ else {
}
enqueue($url_generator, $segments[1]);
break;
- case "item":
- allow_methods("GET");
- if(count($segments) != 3) {
- not_found();
- }
- item($url_generator, $segments[1], $segments[2]);
- break;
case "queue":
switch(count($segments)) {
case 1:
- queue($url_generator);
+ queues($url_generator);
break;
case 2:
- queues($url_generator, $segments[1]);
+ queue($url_generator, $segments[1]);
+ break;
+ case 3:
+ if($segments[2] == "items") {
+ items($url_generator, $segments[1]);
+ }
+ break;
+ case 4:
+ if($segments[2] == "items") {
+ item($url_generator, $segments[1], $segments[3]);
+ }
break;
default:
not_found();
@@ -126,6 +134,17 @@ function bad_request($short = NULL, $long = NULL) {
exit(0);
}
+function conneg() {
+ $accept = isset($_SERVER["HTTP_ACCEPT"]) ? $_SERVER["HTTP_ACCEPT"] : NULL;
+ // First media type
+ $accept = preg_replace('/^([^,]*),.*/', '$1', $accept);
+// var_dump($accept);
+ // Remove parameters
+ $accept = preg_replace('/^([^;]*);.*/', '$1', $accept);
+// var_dump($accept);
+ return $accept;
+}
+
function cron() {
global $db;
@@ -152,6 +171,18 @@ function cron() {
function process_item($queue, $item) {
echo("Processing item " . $item->id . " from queue " . $queue->name . "\n");
+ $input_path = data_file($item->id);
+ $input_fd = fopen($input_path, "r");
+
+ $log_path = log_file($item->id);
+ $log_fd = fopen($log_path, "w");
+
+ if(!$input_fd || !$log_fd) {
+ echo("Error opening " . $path . "\n");
+ fclose($input_fd);
+ fclose($log_fd);
+ return;
+ }
$handle = curl_init();
// http://no2.php.net/manual/en/function.curl-setopt.php
@@ -170,26 +201,34 @@ function process_item($queue, $item) {
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, 1);
// Return the transfer as a string of the return value of curl_exec()
- curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
+// curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
// In seconds
curl_setopt($handle, CURLOPT_TIMEOUT, 30);
curl_setopt($handle, CURLOPT_URL, $queue->endpoint_url);
- var_dump($item->headers);
- curl_setopt($handle, CURLOPT_HEADER, $item->headers);
+ curl_setopt($handle, CURLOPT_HTTPHEADER, $item->headers);
+ curl_setopt($handle, CURLOPT_INFILE, $input_fd);
+
+ curl_setopt($handle, CURLOPT_WRITEHEADER, $log_fd);
+ curl_setopt($handle, CURLOPT_FILE, $log_fd);
+ curl_setopt($handle, CURLOPT_STDERR, $log_fd);
- curl_setopt($handle, CURLOPT_INFILE, data_file($item->id));
+ curl_setopt($handle, CURLOPT_CUSTOMREQUEST, "POST");
+ echo("Executing request...\n");
+ fwrite($log_fd, "POST " . $queue->endpoint_url . "\n");
$ret = curl_exec($handle);
+
if($ret === false) {
- echo("curl failed");
- echo("error: " . curl_error($handle));
+ echo("curl failed\n");
+ echo("error: " . curl_error($handle) . "\n");
}
else {
- echo("curl success");
- echo($ret);
+ echo("curl success\n");
}
+ fclose($input_fd);
+ fclose($log_fd);
curl_close($handle);
}
@@ -219,25 +258,62 @@ function enqueue($url_generator, $queue) {
$db->insert_item($id, $headers, array($queue));
header("HTTP/1.1 201 Created as " . $id);
- header("Location: " . $url_generator->item($id));
+ header("Location: " . $url_generator->item($queue, $id));
} catch (Exception $e) {
header("HTTP/1.1 500 Error");
echo("Caught exception: " . $e->getMessage() . "\n");
}
}
-function item($url_generator, $queue, $id) {
- global $db;
+function item($url_generator, $queue, $item) {
+ global $db, $method;
+
+ list($x, $queue, $id) = $segments;
$item = $db->select_item($queue, $id);
-// var_dump($item);
- $item = $item[0];
- header("Link: <" . $url_generator->item_enclosure($item->id) . ">;rel=enclosure");
- echo("Showing: " . $item->id . "\n");
- echo($item->toPlainText($url_generator));
+ if($item == NULL) {
+ not_found("No such item: " . $id);
+ }
+
+ switch($method) {
+ case "GET":
+ header("Link: <" . $url_generator->item_enclosure($item->id) . ">;rel=enclosure");
+ echo("Showing: " . $item->id . "\n");
+ echo($item->toPlainText($url_generator));
+ break;
+ case "DELETE":
+ $db->delete_item($queue, $id);
+ @unlink(data_file($id));
+ @unlink(log_file($id));
+ header("HTTP/1.1 204 Deleted item " . $id);
+ break;
+ default:
+ allow_methods("GET", "DELETE");
+ break;
+ }
+}
+
+function items($url_generator, $queue) {
+ global $db;
+
+ allow_methods("GET");
+
+ header("HTTP/1.1 200 Items in $queue");
+ $items = $db->select_items($queue);
+ switch(conneg()) {
+ default:
+ case "text/plain":
+ header("Content-Type: text/plain");
+ template_item_list_text($url_generator, $queue, $items);
+ break;
+ case "text/html":
+ header("Content-Type: text/html");
+ template_item_list_html($url_generator, $queue, $items);
+ break;
+ }
}
-function queue($url_generator) {
+function queues($url_generator) {
global $method, $content_type, $db;
switch($method) {
@@ -246,16 +322,16 @@ function queue($url_generator) {
$queues = $db->select_queues();
$count = count($queues);
- header("Content-Type: text/plain");
- if($count == 1) {
- echo("Have one queue");
- }
- else {
- echo("Have " . $count . " queues");
- }
- echo("\n\n");
- foreach($queues as $q) {
- echo($q->toPlainText($url_generator) . "\n");
+ switch(conneg()) {
+ default:
+ case "text/plain":
+ header("Content-Type: text/plain");
+ template_queue_list_text($url_generator, $queues);
+ break;
+ case "text/html":
+ header("Content-Type: text/html");
+ template_queue_list_html($url_generator, $queues);
+ break;
}
break;
case "POST":
@@ -278,7 +354,7 @@ function queue($url_generator) {
}
}
-function queues($url_generator, $queue) {
+function queue($url_generator, $queue) {
global $method, $content_type, $form, $db;
if(!Queue::valid_name($queue)) {
@@ -293,8 +369,17 @@ function queues($url_generator, $queue) {
not_found("No such queue: " . $queue);
}
- header("Content-Type: text/plain");
- echo($q->toPlainText($url_generator));
+ switch(conneg()) {
+ case "text/html";
+ header("Content-Type: text/html");
+ template_queue_html($url_generator, $q);
+ break;
+ default:
+ case "text/plain";
+ header("Content-Type: text/plain");
+ template_queue_text($url_generator, $q);
+ break;
+ }
break;
case "PUT":
$q = $db->select_queue($queue);