I finally had the time to walk through a complete test using the production
code I will utilize to actually consume the real time pusub updates and it
works flawlessly. It will enable me to get content updates in real time, and
only the updates, hence no need to repeatedly download whole feeds in order
to look for updates.

Currently AFAIK only Google's FeedBurner has implemented the service but
that makes up for more than 70% of the content I subscribe to so it's far
from trivial despite the novelty. Not all content providers will ping FB
when they publish something though, hence breaking the real time process.
But it's still better than having to parse the feeds myself, instead I let
FB do the heavy lifting and just send me the new stuff.

Thanks for the help on this one!

The feed url (see hub.topic below) comes url encoded which was the final
snag I had to solve. I couldn't find a global function so I made my own:

(dm urlDecode> (Str)
         (in (list 'echo Str)
            (while (char)
               (let Char @
                  (ifn (= Char "%")
                     (unless (= "^J" Char) (link Char))
                     (link (char (hex (pack (char) (char))))))))))))

(in (list 'echo Str)) is a trick I got from Armadillo (originally as a way
to use (xml) with strings), however it seems like it's attaching a newline
before end of input so maybe not the best solution here (when using (xml)
it's a non issue).

Are there any suggestions on how the above could have been done in a better
way? Apart from that final newline I like the idea of being able to stream a
string internally to be able to utilize the input channel functions, in this
case (char).

My current (go):

(de go ()
   (task (port 4000)
      (let? Sock (accept @)
         (unless (fork)
            (in Sock
               (off *Xml *ContLen *Get)
               (use (L @X @Y @U)
                  (while (setq L (line))
                        ((match '("G" "E" "T" " " @U " " "H" "T" "T" "P" "/"
"1" "." @Y) L)
                           (setq *Get T))
                        ((match '(@Y "a" "t" "o" "m" @X) L)
                           (setq *Xml T))
                        ((match '(~(chop "conte...@ength: ") . @X) L)
                           (setq *ContLen (format (pack @X))))))
                     ((and *Xml *ContLen)
                        (setq *Xml (ht:Read *ContLen)))
                        (setq L (split @U "?"))
                        (for KeyVal (split (cadr L) "&")
                           (let Res (split KeyVal "=")
                              (push '*Get (cons (pack (car Res)) (pack (cadr
               (out Sock
                        (httpHead "text/plain; charset=utf-8")
                           (= "hoobaloo" (cdr (assoc "hub.verify_token"
                           (= "subscribe" (cdr (assoc "hub.mode" *Get)))
                           (db 'xmlUrl '+Feed (urlDecode> '+Gh (cdr (assoc
"hub.topic" *Get))))
                           (prin (cdr (assoc "hub.challenge" *Get)))))
                        (hubSubImport> '+Rss *Xml)
                        (httpStat 204 "No Content"))
                     (T (http404)))))
      (close Sock)))
   (server *UsePort "@start"))

The above is respecting the current version of the protocol:

On Sun, Dec 20, 2009 at 4:06 PM, Alexander Burger <a...@software-lab.de>wrote:

> On Sun, Dec 20, 2009 at 01:59:59PM +0100, Henrik Sarvell wrote:
> > Apparently it was a GET request but I managed to parse it.
> > ...
> >                   (while (setq L (line))
> >                      (cond
> >                         ((match '("G" "E" "T" " " @U " " "H" "T" "T"
> > "P" "/" "1" "." @Y) L)
> >                            (setq *Get T))
> >                         ((match '(@Y "a" "t" "o" "m" @X) L)
> > ...
> I wouldn't match for the GET in the header loop. GET must be the very
> first line, otherwise I would abort the transaction (like I wrote in my
> previous example in case of POST). Also, no need for the global '*Get'
> then.
> So this looks like an if/else condition. If GET is the first line, you
> accept the variables from the URL, else if it is POST and "atom" is
> matched, you read the XML.
> > The problem now is that it seems like the prints are on the wrong
> > channel, before when I was using the normal http etc in the @pubsub
> > function I didn't get headers printed to my terminal for instance
> > which I'm getting now. If I only can get the output to the right place
> > I think I'm done.
> What's missing here is a call to 'out'. Currently, the socket 'Sock' is
> only used in 'in'.
>   (out Sock
>      (httpHead "text/plain; charset=3Dutf-8")
>      ...
> If the output channel is not set to 'Sock', it will write to whatever
> channel is currently open (initially standard output).
> BTW: I would not call '_htSet' here:
> >                                        (ifn (cdr (setq L (split L
> "=3D")))
> >                                           (cons (htArg (car L)))
> >                                           (_htSet (car L) (htArg (cadr
> L)))
> As you see from the naming conventions, the underscore in the name
> indicates a "local" function. And indeed, '_htSet' may call
>   (throw "http")
> which will crash your system if called in the wrong context. And it does
> some permission checks on the variables which may not be suitable here.
> '_htSet' does basically only a simple assignment, and follows some rules
> of the application server which are not needed here, so I would
> recommend to use something simpler, and more to the point.
> Cheers,
> - Alex
> --
> UNSUBSCRIBE: mailto:picol...@software-lab.de?subject=unsubscribe

Reply via email to