api-utils.scm 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. (library (api-utils)
  2. (export define-api-route)
  3. (import (rnrs base)
  4. (only (guile)
  5. lambda* λ
  6. ;; macro stuff
  7. syntax-case
  8. syntax
  9. identifier?
  10. datum->syntax
  11. syntax->datum)
  12. (web client)
  13. (web uri)
  14. (json)
  15. (ice-9 iconv)
  16. (ice-9 exceptions)))
  17. (define-syntax http-method->http-call-procedure
  18. (λ (stx)
  19. (syntax-case stx (GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATH)
  20. [(_ GET) (syntax http-get)]
  21. [(_ HEAD) (syntax http-head)]
  22. [(_ POST) (syntax http-post)]
  23. [(_ PUT) (syntax http-put)]
  24. [(_ DELETE) (syntax http-delete)]
  25. [(_ TRACE) (syntax http-trace)]
  26. [(_ OPTIONS) (syntax http-options)]
  27. ;; error case
  28. [(_ other)
  29. (syntax
  30. (raise-exception
  31. (make-exception
  32. (make-non-continuable-error)
  33. (make-exception-with-message "unknown HTTP method used")
  34. (make-exception-with-irritants (list other))
  35. (make-exception-with-origin 'http-method->http-call-procedure))))])))
  36. (define-syntax variable-name->string
  37. (λ (stx)
  38. (syntax-case stx ()
  39. ((_ id)
  40. (identifier? #'id)
  41. (datum->syntax #'id (symbol->string (syntax->datum #'id)))))))
  42. (define-syntax define-api-route
  43. ;; https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
  44. ;; All HTTP methods are literals.
  45. (syntax-rules (GET HEAD POST PUT DELETE CONNECT OPTIONS TRACE PATH)
  46. ((define-api-route route http-method my-content-type)
  47. (define route
  48. (lambda* (docker-socket #:key (data #f))
  49. (call-with-values
  50. (λ ()
  51. ((http-method->http-call-procedure http-method)
  52. (variable-name->string route)
  53. #:port docker-socket
  54. #:version '(1 . 1)
  55. #:keep-alive? #f
  56. #:headers `((host . ("localhost" . #f))
  57. (content-type . (my-content-type (charset . "utf-8"))))
  58. #:body (scm->json-string data)
  59. #:decode-body? #t
  60. #:streaming? #f))
  61. (λ (response response-text)
  62. (let ([resp-text-as-string (bytevector->string response-text "utf-8")])
  63. (cons response resp-text-as-string)))))))))