# Google web services in Racket
A way to access 40+ Google APIs via
[Google API Discovery service](https://developers.google.com/discovery/).
The Google API Discovery service is a web service that tells you about
web services. Each web service is described using a JSON format
"discovery document", which describes such things as the resources,
methods, and parameters for the web service. It is possible to use
this document programatically to create Racket functions that will
make HTTP requests to the web service, as well as to make
documentation for the service. This is a great idea. And to be
appropriately meta, one of the services you can discover with the
discovery service, is the discovery service itself.
This library provides two approaches to using the discovery service
with Racket:
1. "Require" the discovery document like a source file. The wrapper
functions are created at compile time. The discovery documents are not
used at runtime and need not be shipped with your application;
essentially they are source code just like your `.rkt` files.
2. Dynamically load and parse the discovery docuemnt (from a local
file or from the Discovery web service) at runtime.
Unless you need runtime dynamism, the first approach is easier, more
efficient, and simpler for distributing your application.
The functions created by either approach are identical in terms of the
arguments they accept and the value they return. As a result you
should be able to change approaches without modifying much of your
code.
## Macros and .SCRBL generation
The simplest approach creates wrapper functions for the web service
at compile time. This reduces startup time for your
application. Furthermore, it means that you don't need to ship the
service documents---they are "source code" just like your `.rkt`
files. (Huge thanks to Eli Barzilay for pushing me through the
macro learning crucible to do this!)
```scheme
#lang racket
(require (planet gh/gapi/macro))
(require-gapi-doc urlshortener.v1.js)
(define orig-url "http://www.racket-lang.org/")
(define js-insert (urlshortener-url-insert #:longUrl orig-url))
(define short-url (dict-ref js-insert 'id))
(define js-get (urlshortener-url-get #:shortUrl short-url))
(define long-url (dict-ref js-get 'longUrl))
(printf "~s was shortened to ~s, which expanded back to ~s: ~a"
orig-url short-url long-url
(if (equal? orig-url long-url) "Yay!" "Boo!"))
=> "http://www.racket-lang.org/" was shortened
to "http://goo.gl/uAKH9", which expanded back to
"http://www.racket-lang.org/": Yay!
```
Static `.scrbl` files are generated, because there's really no need
to do these at compile time. Instead they are needed to create
`.html` files for PLaneT package preparation.
## Dynamic
Another way to use the API discovery service is to query it at
runtime, or to parse a locally-stored discovery file at runtime. This
may be desirable if you want to be able to discover newly-added
services, for instance.
```scheme
#lang racket
(require (planet gh/gapi/dynamic))
;; Create a `service?' object from the API discovery document:
(define goo.gl (online-discovery-document->service "urlshortener" "v1"))
;; Make procedures, each corresponding to a resource and method:
(define urlshortener-url-insert (method-proc goo.gl 'url 'insert))
(define urlshortener-url-get (method-proc goo.gl 'url 'get))
;; Use them:
(define orig-url "http://www.racket-lang.org/")
(define js-insert (urlshortener-url-insert #:longUrl orig-url))
(define short-url (dict-ref js-insert 'id))
(define js-get (urlshortener-url-get #:shortUrl short-url))
(define long-url (dict-ref js-get 'longUrl))
(printf "~s was shortened to ~s, which expanded back to ~s: ~a"
orig-url short-url long-url
(if (equal? orig-url long-url) "Yay!" "Boo!"))
=> "http://www.racket-lang.org/" was shortened
to "http://goo.gl/uAKH9", which expanded back to
"http://www.racket-lang.org/": Yay!
```
## Documentation
For full documentation, see
[PLaneT](http://planet.racket-lang.org/display.ss?package=gapi.plt&owner=gh).