Skip to content

Commit 15b7f38

Browse files
committed
Add the implementation to request in REST-XML format (ex. S3).
1 parent db376e9 commit 15b7f38

File tree

6 files changed

+91
-39
lines changed

6 files changed

+91
-39
lines changed

api.lisp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@
4848
:method (request-method req)
4949
:host (request-host req region)
5050
:path (quri:uri-path uri)
51-
:params (quri:uri-query-params uri)
51+
:params (mapcar (lambda (kv)
52+
(if (null (cdr kv))
53+
(cons (car kv) "")
54+
kv))
55+
(quri:uri-query-params uri))
5256
:headers headers
5357
:payload (or payload "")))
5458
(multiple-value-list

generator/operation.lisp

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -75,31 +75,36 @@
7575
:status status
7676
:body body-str)))
7777

78-
(defun parse-response (response body-type wrapper-name error-map)
78+
(defun parse-response (response body-type wrapper-name error-map &optional default-content-type)
7979
(destructuring-bind (body status headers &rest ignore-args)
8080
response
81+
;; TODO: Parse also from headers
8182
(declare (ignore ignore-args))
82-
(let ((content-type (gethash "content-type" headers)))
83+
(let ((content-type (or (gethash "content-type" headers)
84+
default-content-type)))
8385
(if (<= 400 status 599)
8486
(parse-response-error body status content-type error-map)
85-
(if (equal body-type "blob")
86-
body
87-
(let ((body-str (ensure-string (or body ""))))
88-
(cond
89-
((or (string-prefix-p "text/xml" content-type)
90-
(string-prefix-p "application/xml" content-type))
91-
(let* ((output (xmls-to-alist (xmls:parse-to-list body-str)))
92-
(output ;; Unwrap the root element
93-
(cdr (first output))))
94-
(if wrapper-name
95-
(values (aget output wrapper-name)
96-
(aget output "ResponseMetadata"))
97-
output)))
98-
((member content-type '("application/json" "application/x-amz-json-1.1" "application/x-amz-json-1.0")
99-
:test #'string=)
100-
(yason:parse body-str :object-as :alist))
101-
(t
102-
body-str))))))))
87+
(values
88+
(if (equal body-type "blob")
89+
body
90+
(let ((body-str (ensure-string (or body ""))))
91+
(cond
92+
((or (string-prefix-p "text/xml" content-type)
93+
(string-prefix-p "application/xml" content-type))
94+
(let* ((output (xmls-to-alist (xmls:parse-to-list body-str)))
95+
(output ;; Unwrap the root element
96+
(cdr (first output))))
97+
(if wrapper-name
98+
(values (aget output wrapper-name)
99+
(aget output "ResponseMetadata"))
100+
output)))
101+
((member content-type '("application/json" "application/x-amz-json-1.1" "application/x-amz-json-1.0")
102+
:test #'string=)
103+
(yason:parse body-str :object-as :alist))
104+
(t
105+
body-str))))
106+
status
107+
headers)))))
103108

104109
(defun compile-path-pattern (path-pattern)
105110
(when path-pattern
@@ -121,7 +126,7 @@
121126
,@slots))
122127
path-pattern))))
123128

124-
(defun compile-operation (service name options params body-type error-map)
129+
(defun compile-operation (service name options params body-type error-map protocol)
125130
(let* ((output (gethash "output" options))
126131
(method (gethash "method" (gethash "http" options)))
127132
(request-uri (gethash "requestUri" (gethash "http" options))))
@@ -141,7 +146,10 @@
141146
,body-type
142147
,(and output
143148
(gethash "resultWrapper" output))
144-
,error-map)))
149+
,error-map
150+
,(case protocol
151+
((:json :rest-json) "application/json")
152+
(:rest-xml "application/xml")))))
145153
(export ',(lispify name))))
146154
`(progn
147155
(defun ,(lispify name) ()

generator/service.lisp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@
108108
(find-output-type
109109
(gethash+ `("shapes" ,(gethash "shape" shape)) hash))))))
110110
(find-output-type payload-shape))))
111-
(intern (string :*error-map*)))))
111+
(intern (string :*error-map*))
112+
protocol)))
112113
(force-output stream)))))
113114

114115
(defun dump-service-base-file-to-stream (service service-dir &optional (stream *standard-output*))

generator/shape.lisp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
(:method (input) input))
4040
(defgeneric input-headers (input))
4141
(defgeneric input-payload (input))
42+
(defgeneric input-payload-properties (input)
43+
(:method (input) (declare (ignore input)) nil))
4244

4345
(defun add-query-with-input (uri input)
4446
(quri:make-uri :defaults uri
@@ -55,15 +57,16 @@
5557
(defun make-request-with-input (request-class input method path-conversion action)
5658
(make-instance request-class
5759
:method method
58-
:path (quri:uri-path (add-query-with-input
59-
(etypecase path-conversion
60-
(string path-conversion)
61-
(function (funcall path-conversion input))
62-
(null "/"))
63-
input))
60+
:path (quri:render-uri (add-query-with-input
61+
(etypecase path-conversion
62+
(string path-conversion)
63+
(function (funcall path-conversion input))
64+
(null "/"))
65+
input))
6466
:params (input-params input)
6567
:headers (input-headers input)
6668
:payload (input-payload input)
69+
:payload-properties (input-payload-properties input)
6770
:operation action))
6871

6972
(defun filter-member (key value members)
@@ -127,7 +130,17 @@
127130
(defmethod input-payload ((input ,shape-name))
128131
,(if payload
129132
`(slot-value input ',(lispify payload))
130-
'nil)))))
133+
'nil))
134+
,@(when (and payload
135+
(gethash payload members))
136+
(let ((props (gethash payload members)))
137+
`((defmethod input-payload-properties ((input ,shape-name))
138+
(declare (ignore input))
139+
(list ,@(and (gethash "locationName" props)
140+
`(:location-name ,(gethash "locationName" props)))
141+
,@(and (gethash "xmlNamespace" props)
142+
(gethash "uri" (gethash "xmlNamespace" props))
143+
`(:xml-namespace ,(gethash "uri" (gethash "xmlNamespace" props))))))))))))
131144

132145
(defun compile-exception-shape (name &key members exception)
133146
(let ((condition-name (lispify* name)))

request.lisp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@
6262
(payload :initarg :payload
6363
:initform nil
6464
:accessor request-payload)
65+
(payload-properties :initarg :payload-properties
66+
:initform nil
67+
:accessor request-payload-properties)
6568
(session :initarg :session
6669
:initform *session*
6770
:reader request-session)))

rest-xml-request.lisp

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,44 @@
33
(:import-from #:aws-sdk/request
44
#:request
55
#:request-headers
6-
#:request-path)
6+
#:request-path
7+
#:request-payload)
78
(:import-from #:aws-sdk/session
89
#:*session*)
10+
(:import-from #:xml-emitter)
911
(:export #:rest-xml-request))
1012
(in-package #:aws-sdk/rest-xml-request)
1113

1214
(defclass rest-xml-request (request)
1315
())
1416

17+
(defun object-to-xml (object location-name &optional xml-namespace)
18+
(assert location-name)
19+
(typecase object
20+
(null)
21+
;; XXX: Should see if it's flattened or not.
22+
(cons (map nil (lambda (obj) (object-to-xml obj location-name))
23+
object))
24+
(standard-object
25+
(xml-emitter:with-simple-tag (location-name nil xml-namespace)
26+
(loop for slot in (c2mop:class-direct-slots (class-of object))
27+
for value = (slot-value object (c2mop:slot-definition-name slot))
28+
for tag-name = (or (aws-sdk/generator/shape::member-slot-location-name slot)
29+
(aws-sdk/generator/shape::member-slot-shape slot))
30+
when value
31+
do (if tag-name
32+
(object-to-xml value tag-name)
33+
(xml-emitter:xml-out value)))))
34+
(otherwise
35+
(xml-emitter:simple-tag location-name object nil xml-namespace))))
1536

16-
(defmethod initialize-instance :after ((req rest-xml-request) &rest args &key params path &allow-other-keys)
37+
(defmethod initialize-instance :after ((req rest-xml-request) &rest args &key path payload payload-properties &allow-other-keys)
1738
(declare (ignore args))
18-
(let ((uri (quri:uri path)))
19-
(setf (request-path req)
20-
(quri:render-uri
21-
(quri:make-uri :path (quri:uri-path uri)
22-
:query (quri:url-encode-params (append (quri:uri-query-params uri)
23-
params)))))))
39+
(when (typep payload 'standard-object)
40+
(destructuring-bind (&key location-name xml-namespace)
41+
payload-properties
42+
(setf (request-payload req)
43+
(with-output-to-string (s)
44+
(xml-emitter:with-xml-output (s :encoding "UTF-8")
45+
(object-to-xml payload location-name xml-namespace))))))
46+
(setf (request-path req) path))

0 commit comments

Comments
 (0)