-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfetch-core.el
88 lines (73 loc) · 3.18 KB
/
fetch-core.el
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
;;; fetch-core.el --- Core logic -*- lexical-binding: t; -*-
;; Copyright (C) 2019 Erik Anderson
;; Author: Erik Anderson <erik@ebpa.link>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'fetch-utils)
(cl-defstruct (fetch-request (:constructor fetch-request-create)
:named)
resource
(method 'get)
headers
body)
(cl-defstruct fetch-response
status-code
headers
body
request
raw)
(cl-defmethod fetch ((request fetch-request) &key callback promise)
"Core function to make HTTP requests."
(declare (indent 1))
(fetch--do-setup)
(cl-assert (not (and callback promise)) nil ":callback and :promise arguments are exclusive (may not be used simultaneously).")
(let ((handler (-partial #'fetch--response-handler request))
(url (fetch-request-resource request))
(url-request-data (fetch-request-body request))
(url-request-extra-headers (fetch-request-headers request))
(url-request-method (upcase (symbol-name (fetch-request-method request))))
(url-show-status nil))
(cond
(callback
(url-retrieve url (-compose callback handler)))
(promise
(if (not (require 'promise nil t))
(message "In order to use the fetch promise API, promise.el must be on the load-path.")
(promise-chain
(promise-new (lambda (resolve reject)
(condition-case err
(url-retrieve url (lambda (status)
(funcall resolve (list (current-buffer) status))))
(t
(funcall reject err)))))
(then (-lambda ((response-buffer status))
(with-current-buffer response-buffer
(funcall handler status)))))))
(t
(with-current-buffer
(url-retrieve-synchronously url)
(funcall handler (car url-callback-arguments)))))))
(cl-defun fetch--response-handler (request status)
"Internal function to build a `fetch-response' object from the response by the url library."
(set-buffer-multibyte t)
(make-fetch-response
:status-code url-http-response-status
:headers (fetch--parse-response-headers (buffer-substring-no-properties (point-min) url-http-end-of-headers))
:body (when (not (eq url-http-end-of-headers (point-max)))
(decode-coding-string (buffer-substring-no-properties url-http-end-of-headers (point-max)) 'utf-8))
:request request
:raw (current-buffer)))
(provide 'fetch-core)
;;; fetch-core.el ends here