blob: 3fd79f8a7cb2ac58ffa6dc4658738360c5c17112 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
#!/usr/bin/env guile \
-e main -s
!#
;; Minimal web server can be started from command line. Current example routes:
;;
;; localhost:8080/
;;
(use-modules
(json)
(ice-9 match)
(ice-9 format)
(srfi srfi-1)
(srfi srfi-26)
(web http)
(web request)
(web response)
(web uri)
(fibers web server))
(define (get-version)
"2.0")
(define (base-url)
"https://genenetwork.org")
(define (prefix)
(string-append (base-url) "/api/" (get-version)))
(define (mk-url postfix)
(string-append (prefix) "/" postfix))
(define (meta url)
(string-append url "/meta"))
(define info `(
("name" . "GeneNetwork REST API")
("version" . ,(get-version))
("comment" . "This is the official REST API for the GeneNetwork service hosted at https://genenetwork.org/")
("license" . (("source code" . "AGPL")))
("note" . "work in progress (WIP)")
("see also". ,(meta (prefix)))
))
(define info-meta `(
("API" .
((,(mk-url "species")."Get a list of all species")
(,(mk-url "mouse")."Get information on mouse")
(,(mk-url "datasets")."Get a list of datasets")))))
(define (get-species)
'(("Mus_musculus" . (("id" . "mouse" )
("api" . "https://genenetwork.org/api/v2/mouse/")))
("Rattus_norvegicus" . (("id" . "rat")
("api" . "https://genenetwork.org/api/v2/rat/")))
))
(define (get-species-api-str)
(scm->json-string #("https://genenetwork.org/api/v2/mouse/"
"https://genenetwork.org/api/v2/rat/")))
;; ---- REST API web server handler
(define (not-found request)
(values (build-response #:code 404)
(string-append "Resource not found: "
(uri->string (request-uri request)))))
(define (render-json json)
(list '((content-type . (application/json)))
(lambda (port)
(scm->json json port))))
(define (controller request body)
(match-lambda
(('GET)
(render-json info))
(('GET "meta")
(render-json info-meta))
(('GET "version")
(render-json (get-version)))
(('GET "species")
(render-json (get-species)))
))
(define (request-path-components request)
(split-and-decode-uri-path (uri-path (request-uri request))))
(define (handler request body)
(format #t "~a ~a\n"
(request-method request)
(uri-path (request-uri request)))
(apply values
((controller request body)
(cons (request-method request)
(request-path-components request)))))
(define (start-web-server address port)
(format (current-error-port)
"GN REST API web server listening on http://~a:~a/~%"
address port)
;; Wrap handler in another function to support live hacking via the
;; REPL. If handler is passed as is and is then redefined via the
;; REPL, the web server will still be using the old handler. The
;; only way to update the handler reference held by the web server
;; would be to restart the web server.
(run-server (cut handler <> <>)
#:addr (inet-pton AF_INET address)
#:port port))
(define (main args)
(write (string-append "Starting Guile REST API " (get-version) " server!"))
(write args)
(newline)
(let ((listen (inexact->exact (string->number (car (cdr args))))))
(display `("listening on" ,listen))
;; (write listen)
;; (run-server hello-world-handler 'http `(#:port ,listen))))
(start-web-server "127.0.0.1" listen)))
|