Skip to content

Commit 4412faa

Browse files
committed
Add pretty print to XML output. Simplified POST method to add a subscription.
1 parent 5c3cb65 commit 4412faa

File tree

3 files changed

+43
-21
lines changed

3 files changed

+43
-21
lines changed

README.txt

+20-6
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,39 @@ Configuring scala-push:
1919
scala-push runs a simple REST admin interface which does not yet have a GUI.
2020

2121
To add a subscription, do a POST:
22-
curl -v -X POST -H 'Content-type: text/xml' -d '<feed feedURL=[your feed URL]"/>' http://[host]:[port]/admin/
22+
curl -d "feedURL=[your feed URL]" http://[host]:[port]/admin/
23+
Example: curl -d "feedURL=http://www.google.com/reader/public/atom/user%2F05268996354213702508%2Fstate%2Fcom.google%2Fbroadcast" http://localhost:8080/admin/
2324

2425
To list the subscriptions, do a GET:
2526
curl http://[host]:[port]/admin/
27+
Example: curl http://localhost:8080/admin/
2628

2729
Example output:
2830
<feeds>
29-
<feed feedURL="http://www.google.com/reader/public/atom/user%2F05268996354213702508%2Fstate%2Fcom.google%2Fbroadcast" topicURL="http://www.google.com/reader/public/atom/user%2F05268996354213702508%2Fstate%2Fcom.google%2Fbroadcast" hubURL="http://pubsubhubbub.appspot.com/" id="429658526">
30-
</feed>
31+
<feed>
32+
<id>-702581410</id>
33+
<feedURL>http://www.google.com/reader/public/atom/user/05268996354213702508/state/com.google/broadcast</feedURL>
34+
<topicURL>http://www.google.com/reader/public/atom/user/05268996354213702508/state/com.google/broadcast</topicURL>
35+
<hubURL>http://pubsubhubbub.appspot.com/</hubURL>
36+
</feed>
3137
</feeds>
38+
3239
Make a note of the field called id.
3340

34-
To delete a subscription, do a DELETE to url curl -x DELETE http://[host]:[port]/admin/[id] where id is the feed id.
41+
To delete a subscription, do a DELETE: curl -X DELETE http://[host]:[port]/admin/[id] where id is the feed id.
42+
Example: curl -X DELETE http://localhost:8080/admin/-702581410
3543

3644
As content is pushed to the subscriber, it will be displayed on the console.
45+
Here is an example below:
46+
47+
Fri Nov 27 15:51:43 GMT 2009 --- Update from: Guillaume's shared items in Google Reader
48+
Topic URL: http://www.google.com/reader/public/atom/user%2F05268996354213702508%2Fstate%2Fcom.google%2Fbroadcast
49+
50+
10 NoSQL Systems Reviewed (published Mon Nov 09 16:04:02 GMT 2009)
51+
http://feedproxy.google.com/~r/HighScalability/~3/8arewmYgZ7k/10-nosql-systems-reviewed.html
3752

3853
Feeds to subscribe to:
3954
----------------------
4055
The following feeds are PuSH enabled and good candidates for testing:
4156
-Google Alert feeds
42-
-Shared Google Reader items
43-
57+
-Shared Google Reader items: the subscriber receives a notification as soon as you share an item.

src/main/scala/org/kafecho/push/Push.scala

+5-6
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ object Constants{
4141
class Subscription(val feedURL : String, val topicURL : String, val hubURL : String){
4242
val id : Int = feedURL.hashCode
4343
override def toString = "Feed URL: " + feedURL + ", topic URL: " + topicURL + ", Hub URL: " + hubURL +"."
44-
def toXML = <feed id={id.toString} feedURL={feedURL} topicURL={topicURL} hubURL={hubURL} />
44+
def toXML = <feed><id>{id.toString}</id><feedURL>{feedURL}</feedURL><topicURL>{topicURL}</topicURL><hubURL>{hubURL}</hubURL></feed>
4545
}
4646

4747
/*
@@ -54,10 +54,9 @@ class Subscriber(val hostname:String, val port : Int) extends Logging{
5454
val pushRoute = "push"
5555
val adminRoute = "admin"
5656
val callbackURL = "http://" + hostname + ":" + port + "/" + pushRoute
57-
val pushRestlet = new PuSHRestlet(this)
58-
val adminRestlet = new AdminRestlet(this)
59-
val configFile = "feeds.xml"
60-
57+
val pushRestlet = new PuSHRestlet(this)
58+
val adminRestlet = new AdminRestlet(this)
59+
val configFile = "feeds.xml"
6160
var pendingSubscriptions : Set[Subscription] = Set()
6261
var activeSubscriptions : Set[Subscription] = Set()
6362

@@ -77,7 +76,7 @@ class Subscriber(val hostname:String, val port : Int) extends Logging{
7776
def loadConfig{
7877
try{
7978
val config = XML.loadFile(configFile)
80-
(config\"feed").foreach{t => subUnsub( ( t \"@feedURL").text,true) }
79+
(config\"feed").foreach{t => subUnsub( t \ "feedURL" text ,true) }
8180
}catch{
8281
case ex: FileNotFoundException =>
8382
}

src/main/scala/org/kafecho/push/Restlets.scala

+18-9
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import org.restlet.{Client,Component,Restlet};
1111
import org.restlet.data._
1212
import java.text.SimpleDateFormat
1313

14-
import scala.xml.XML
14+
import scala.xml.{XML,PrettyPrinter}
1515
import scala.xml.Elem
1616

1717
/*
@@ -25,20 +25,28 @@ object RFC3339 extends SimpleDateFormat("yyyy-MM-dd'T'h:m:ss")
2525
* This restlet mixes in the traits corresponding to the HTTP methods it supports and the dispatch logic is handled by each of the trait.
2626
*/
2727
class AdminRestlet (val subscriber : Subscriber ) extends Default with Logging with POST with GET with DELETE{
28+
val xmlPrinter = new PrettyPrinter(100,2)
29+
2830
def doPOST(request : Request, response : Response){
2931
val id = request.getAttributes.get("ID")
3032
if (id != null){
3133
response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED)
3234
return
3335
}
34-
if (request.getEntity.getMediaType != MediaType.TEXT_XML){
35-
response.setStatus(Status.CLIENT_ERROR_NOT_ACCEPTABLE,"Please provide some XML.")
36+
37+
if (request.getEntity.getMediaType != MediaType.APPLICATION_WWW_FORM){
38+
log.error("Invalid MIME type: " + request.getEntity.getMediaType)
39+
response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED)
3640
return
3741
}
38-
39-
val xml = XML.loadString(request.getEntity.getText)
40-
subscriber.subUnsub(xml \ "@feedURL" text , true)
41-
}
42+
val form = request.getEntityAsForm
43+
val feedURL = form.getFirstValue("feedURL")
44+
if (feedURL != null){
45+
subscriber.subUnsub(feedURL , true)
46+
response.setEntity("Creating subscription for feed: " + feedURL,MediaType.TEXT_PLAIN)
47+
response.setStatus(Status.SUCCESS_ACCEPTED)
48+
}
49+
}
4250

4351
def doDELETE(request : Request, response : Response){
4452
val id = request.getAttributes.get("ID")
@@ -48,7 +56,8 @@ class AdminRestlet (val subscriber : Subscriber ) extends Default with Logging w
4856
found match{
4957
case Some(subscription) =>
5058
subscriber.subUnsub(subscription.feedURL,subscription.topicURL,subscription.hubURL,false)
51-
response.setStatus(Status.SUCCESS_OK,"Created a new subscription for feed: " + subscription.feedURL)
59+
response.setEntity("Removing subscription for feed: " + subscription.feedURL, MediaType.TEXT_PLAIN)
60+
response.setStatus(Status.SUCCESS_ACCEPTED)
5261
case None => response.setStatus(Status.CLIENT_ERROR_NOT_FOUND)
5362
}
5463
}
@@ -58,7 +67,7 @@ class AdminRestlet (val subscriber : Subscriber ) extends Default with Logging w
5867
if (id != null){
5968
val found = subscriber.activeSubscriptions.find( _.id.toString == id)
6069
found match{
61-
case Some(subscription) => response.setEntity(subscription.toXML.toString, MediaType.TEXT_XML)
70+
case Some(subscription) => response.setEntity(xmlPrinter.format(subscription.toXML), MediaType.TEXT_XML)
6271
case None => response.setStatus(Status.CLIENT_ERROR_NOT_FOUND)
6372
}
6473
}

0 commit comments

Comments
 (0)