Gauche:AWS

Gauche:AWS

Gauche:AWS

最初の実装

Amazon Web ServiceのAPIを叩くためのライブラリモジュール。 使うにはAWSのAccessKeyIdが必要なので、各自取得してね。

マニュアルはないです。
最後にいくつかexampleを載っけてるのでAWSのAPIをある程度知ってれば叩けるかと。 低レベルのAPIを使えば何でも可だけど、多少上位レイヤと思えるAPIを追加してます。 薄いラッパーだけど…。

注意点としては1秒ルールはここでは対応してません。 アプリレベルでやるか、それともここにオプショナルにつっこめるなら ハックしてフィードバックよろしく。cut-sea:2007/04/10 18:18:03 PDT

マルチオペレーション

調べたらマルチオペレーションなるものもあった。
最初の実装でも複数のオペレーションをサポートしたつもりだったが、 あれはバッチリクエストというものだったらしい。 というわけで、マルチオペレーションを追加した。 同時にバッチリクエストを吸収。
ただし、カート系との組み合わせはやってない。 ルールが結構難しくなりそうなのと、 今のところそのような記述を必要としてないってのとで逃げ〜。

ちなみにマルチオペレーションではこんな感じ。

(aws:multi-operation :Operation "BrowseNodeLookup"
                     :BrowseNodeId 466298
                     :Operation "ItemSearch"
                     :SearchIndex "Books" :BrowseNode 466298
                     :ResponseGroup "Small"
                     :SearchIndex "Music" :Artist "大塚愛"
                     :ResponseGroup "Large")

みたいに書くと

(aws:send-rest :Operation "BrowseNodeLookup,ItemSearch"
               :BrowseNodeLookup.1.BrowseNodeId 466298
               :ItemSearch.1.SearchIndex "Books"
               :ItemSearch.1.BrowseNode 466298
               :ItemSearch.1.ResponseGroup "Small"
               :ItemSearch.2.SearchIndex "Music"
               :ItemSearch.2.Artist "大塚愛"
               :ItemSearch.2.ResponseGroup "Large")

としてくれて、それがRESTなHTTP requestになる。 問題はCart系がここまで単純じゃないんで、 必要になったところでちょっと集中して実装するかなーってことで。cut-sea:2007/04/14 10:29:21 PDT


ソース

;;;
;;; AWS - Amazon Web Service
;;;  
;;;   Copyright (c) 2007  Katsutoshi Itoh  <cut-sea@master.email.ne.jp>
;;;   
;;;   Redistribution and use in source and binary forms, with or without
;;;   modification, are permitted provided that the following conditions
;;;   are met:
;;;   
;;;   1. Redistributions of source code must retain the above copyright
;;;      notice, this list of conditions and the following disclaimer.
;;;  
;;;   2. Redistributions in binary form must reproduce the above copyright
;;;      notice, this list of conditions and the following disclaimer in the
;;;      documentation and/or other materials provided with the distribution.
;;;  
;;;   3. Neither the name of the authors nor the names of its contributors
;;;      may be used to endorse or promote products derived from this
;;;      software without specific prior written permission.
;;;  
;;;   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
;;;   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
;;;   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
;;;   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
;;;   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
;;;   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
;;;   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
;;;   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
;;;   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
;;;   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
;;;   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;;;  
;;;  $Id$
;;;

(define-module aws
  (use gauche.charconv)
  (use gauche.parameter)
  (use rfc.http)
  (use rfc.uri)
  (use sxml.ssax)
  (use sxml.sxpath)
  (use util.list)
  (use util.match)

  (export
   ;; it's important export
   parameterize

   ;; Class, slot-accessor
   <aws> <cart> <response>
   AccessKeyId-of AssociateTag-of UserAgent-of BaseDomain-of Version-of
   CartId-of HMAC-of Cart-of Error-of
   ResultCode-of Header-of Body-of

   ;; Low Level API and Utility
   aws:namespace-prefix
   aws:pass?
   aws:request
   aws:send-rest
   aws:send-rest-lite
   current-aws
   with-aws

   ;; Middle Level API
   aws:multi-operation
   aws:item-search
   aws:item-lookup

   aws:sellerlisting-search
   aws:sellerlisting-lookup

   aws:list-search
   aws:list-lookup

   aws:seller-lookup
   aws:customercontent-lookup
   aws:similarity-lookup
   aws:browsenode-lookup
   aws:customercontent-search
   aws:transaction-lookup
   aws:help

   aws:cart-create
   aws:cart-get
   aws:cart-clear!
   aws:cart-add!
   aws:cart-modify!

   ;; High Level API
   aws:blended-search
   aws:books-search
   aws:classical-search
   aws:dvd-search
   aws:electronics-search
   aws:foreignbooks-search
   aws:healthpersonalcare-search
   aws:hobbies-search
   aws:kitchen-search
   aws:music-search
   aws:musictracks-search
   aws:software-search
   aws:sportinggoods-search
   aws:toys-search
   aws:vhs-search
   aws:video-search
   aws:videogames-search
   aws:watches-search

   aws:asin-lookup
   aws:dpci-lookup
   aws:ean-lookup
   aws:isbn-lookup
   aws:sku-lookup
   aws:upc-lookup
   
   aws:asin-sellerlisting-lookup
   aws:exchange-sellerlisting-lookup
   aws:listing-sellerlisting-lookup
   aws:sku-sellerlisting-lookup

   aws:babyregistry-search
   aws:weddingregistry-search
   aws:wishlist-search

   aws:listmania-lookup
   aws:weddingregistry-lookup
   aws:wishlist-lookup

   aws:help-operation
   aws:help-response
   )
  )
(select-module aws)

(define-class <aws> ()
  ((AccessKeyId  :accessor AccessKeyId-of :init-keyword :AccessKeyId)
   (AssociateTag :accessor AssociateTag-of :init-keyword :AssociateTag
                 :init-value "webservices-20")
   (UserAgent    :accessor UserAgent-of :init-keyword :UserAgent
                 :init-value "ECS-Agent/0.1")
   (BaseDomain   :accessor BaseDomain-of :init-keyword :BaseDomain
                 :init-value "webservices.amazon.co.jp")
   (Version      :accessor Version-of :init-keyword :Version
                 :init-value "2007-02-22")
   ))

(define-class <cart> ()
  ((CartId :accessor CartId-of :init-keyword :CartId
           :init-value #f)
   (HMAC   :accessor HMAC-of :init-keyword :HMAC
           :init-value #f)
   (Cart   :accessor Cart-of :init-keyword :Cart
           :init-value #f)
   (Error  :accessor Error-of :init-keyword :Error
           :init-value '())))

(define-class <response> ()
  ((ResultCode :accessor ResultCode-of :init-keyword :ResultCode
               :init-value "200")
   (Header     :accessor Header-of :init-keyword :Header
               :init-value '())
   (Body       :accessor Body-of :init-keyword :Body
               :init-value '())))

;
; TODO: confirm this namespace is right?
;
(define-method aws:namespace-prefix ((aws <aws>))
  #`"http://webservices.amazon.com/AWSECommerceService/,(Version-of aws)")

(define-method aws:pass? ((res <response>))
  (and (string=? "200" (ResultCode-of res))
       (not ((if-sxpath '(// AWS:Errors)) (Body-of res)))))

(define current-aws (make-parameter (make <aws>)))

(define-macro (with-aws aws . body)
  `(parameterize ((current-aws ,aws)) ,@body))

;
; generate request string
;
(define-method aws:request ((aws <aws>) . args)
  (define (generate-key&val key-vals)
    (define (encode-key key)
      (cond ((and (boolean? key) key) "True")
            ((boolean? key) "False")
            (else
             (uri-encode-string
              (ces-convert (x->string key) "*jp" "utf8")))))
    (define (p->q p)
      #`",(keyword->string (car p))=,(encode-key (cadr p))")
    (fold-right (lambda (item seed)
                  (cons (p->q item) seed))
                '() (slices args 2 #t "")))
  (string-join (apply list
                      "/onca/xml?Service=AWSECommerceService"
                      #`"AWSAccessKeyId=,(AccessKeyId-of aws)"
                      #`"AssociateTag=,(AssociateTag-of aws)"
                      #`"Version=,(Version-of aws)"
                      (generate-key&val args))
               "&"))

(define-method aws:request args
  (apply aws:request (current-aws) args))

;;
;; http-get on AWS REST
;;
;; Low Level API
;;
(define-method aws:send-rest ((aws <aws>) . args)
  (receive (result header body)
      (http-get (BaseDomain-of aws) (apply aws:request aws args))
    ; for debug print
    ;(format #t "~a~%" (apply aws:request aws args))
    (values result
            header
            (call-with-input-string
                (ces-convert body "*jp" (gauche-character-encoding))
              (lambda (in)
                (ssax:xml->sxml
                 in (list (cons 'AWS (aws:namespace-prefix aws)))))))))

(define-method aws:send-rest args
  (apply aws:send-rest (current-aws) args))

(define-method aws:send-rest-lite ((aws <aws>) . args)
  (receive (result header body)
      (apply aws:send-rest aws args)
    (make <response> :ResultCode result :Header header :Body body)))

(define-method aws:send-rest-lite args
  (apply aws:send-rest-lite (current-aws) args))

;;
;; Middle Level API - AWS Operation
;;
#|
;; ex.1 This expression translated to ...
(aws:multi-operation :Operation "BrowseNodeLookup"
                     :BrowseNodeId 466298
                     :Operation "ItemSearch"
                     :SearchIndex "Books" :BrowseNode 466298
                     :ResponseGroup "Small"
                     :SearchIndex "Music" :Artist "大塚愛"
                     :ResponseGroup "Large")

;; this express.
(aws:send-rest :Operation "BrowseNodeLookup,ItemSearch"
               :BrowseNodeLookup.1.BrowseNodeId 466298
               :ItemSearch.1.SearchIndex "Books"
               :ItemSearch.1.BrowseNode 466298
               :ItemSearch.1.ResponseGroup "Small"
               :ItemSearch.2.SearchIndex "Music"
               :ItemSearch.2.Artist "大塚愛"
               :ItemSearch.2.ResponseGroup "Large")

|#

;; This support Multi Operation compile into REST format.
;; But, Couldn't support automatically append :Quantity for Cart* operation.
;; So, it's TODO task. It means import the function of %trans.
;; If you use this, then you add `:Quantity 1' into args list.
;;
;; ops: Operations : list
;; op: current operation
;; sub: current sub operation
;; seq: current sequence
;; src: rest of analysis keyword and value list
;; dst: analysed code
(define (compile src)
  (define (%compile ops op sub seq src dst)
    (define x->key make-keyword)
    (match src
      (() (cons :Operation (cons (string-join (reverse ops) "," ) (reverse dst))))
      ((:Operation o (? keyword? k) s . args)
       (%compile (cons o ops) o k 0 (cons k (cons s args)) dst))
      (((? keyword? k) v . args)
       (cond ((equal? k sub)
              (%compile ops op k (+ seq 1) args (cons v (cons (x->key #`",|op|.,(+ seq 1).,|k|") dst))))
             (else
              (%compile ops op sub seq args (cons v (cons (x->key #`",|op|.,|seq|.,|k|") dst))))))
      (else (error "illegal format."))))
  (%compile '() #f #f 0 src '()))

#|
;; TODO: check specification of AWS and add CartId and HMAC parameters.
;;
(define (compile src)
  (define (%compile ops op sub seq src dst)
    (define x->key make-keyword)
    (define (cart-operator? op)
      (member op '("CartCreate" "CartAdd" "CartModify")))
    (define (cart-subop? key)
      (member key '(:ASIN :OfferListingId :CartItemId)))
    (define (cart-subsubop? key)
      (member key '(:Quantity :Action)))
    (match src
      (() (cons :Operation (cons (string-join (reverse ops) "," ) (reverse dst))))
      ;; for cart operations
      ((:Operation (? cart-operator? o) (? cart-subop? k) s (? cart-subsubop? q) n . args)
       (%compile (cons o ops) o k 0 (cons k (cons s (cons q (cons n args))))))
      ((:Operation (? cart-operator? o) (? cart-subop? k) s :Q n . args)
       (%compile ops op sub seq (apply list :Operation o k s :Quantity n args) dst))
      ((:Operation (? cart-operator? o) (? cart-subop? k) s . args)
       (%compile ops op sub seq (apply list :Operation o k s :Quantity 1 args) dst))
      ;; for other operations
      ((:Operation o (? keyword? k) s . args)
       (%compile (cons o ops) o k 0 (cons k (cons s args)) dst))
      (((? keyword? k) v . args)
       (cond ((equal? k sub)
              (%compile ops op k (+ seq 1) args (cons v (cons (x->key #`",|op|.,(+ seq 1).,|k|") dst))))
             (else
              (%compile ops op sub seq args (cons v (cons (x->key #`",|op|.,|seq|.,|k|") dst))))))
      (else (error "illegal format."))))
  (%compile '() #f #f 0 src '()))
|#

(define-method aws:multi-operation ((aws <aws>) . args)
  (apply aws:send-rest-lite aws (compile args)))

(define-method aws:multi-operation args
  (apply aws:multi-operation (current-aws) args))

; ItemSearch
;
;(define-method aws:item-search ((aws <aws>) . args)
;  (apply aws:send-rest-lite aws
;        :Operation "ItemSearch"
;        (delete-keyword :Operation args)))

(define-method aws:item-search ((aws <aws>) . args)
  (apply aws:send-rest-lite aws
         (compile (apply list :Operation "ItemSearch"
                         (delete-keyword :Operation args)))))

(define-method aws:item-search args
  (apply aws:item-search (current-aws) args))

; ItemLookup
;
(define-method aws:item-lookup ((aws <aws>) . args)
  (apply aws:send-rest-lite aws
         :Operation "ItemLookup"
         (delete-keyword :Operation args)))

(define-method aws:item-lookup args
  (apply aws:item-lookup (current-aws) args))

; SellerListingSearch
;
(define-method aws:sellerlisting-search ((aws <aws>) id . args)
  (apply aws:send-rest-lite aws
         :Operation "SellerListingSearch"
         :SellerId id
         (delete-keyword :Operation args)))

(define-method aws:sellerlisting-search (id . args)
  (apply aws:sellerlisting-search (current-aws) id args))

; SellerListingLookup
;
(define-method aws:sellerlisting-lookup ((aws <aws>) . args)
  (apply aws:send-rest-lite aws
         :Operation "SellerListingLookup"
         (delete-keyword :Operation args)))

(define-method aws:sellerlisting-lookup args
  (apply aws:sellerlisting-lookup (current-aws) args))

; ListSearch
;
(define-method aws:list-search ((aws <aws>) . args)
  (apply aws:send-rest-lite aws
         :Operation "ListSearch"
         (delete-keyword :Operation args)))

(define-method aws:list-search args
  (apply aws:list-search (current-aws) args))

; ListLookup
;
(define-method aws:list-lookup ((aws <aws>) . args)
  (apply aws:send-rest-lite aws
         :Operation "ListLookup"
         (delete-keyword :Operation args)))

(define-method aws:list-lookup args
  (apply aws:list-lookup (current-aws) args))

; SellerLookup
;
(define-method aws:seller-lookup ((aws <aws>) id . args)
  (apply aws:send-rest-lite aws
         :Operation "SellerLookup"
         :SellerId id
         (delete-keyword :Operation args)))

(define-method aws:seller-lookup (id . args)
  (apply aws:seller-lookup (current-aws) id args))

; CustomerContentLookup
;
(define-method aws:customercontent-lookup ((aws <aws>) id . args)
  (apply aws:send-rest-lite aws
         :Operation "CustomerContentLookup"
         :CustomerId id
         (delete-keyword :Operation args)))

(define-method aws:customercontent-lookup (id . args)
  (apply aws:customercontent-lookup (current-aws) id args))

; SimilarityLookup
;
(define-method aws:similarity-lookup ((aws <aws>) id . args)
  (apply aws:send-rest-lite aws
         :Operation "SimilarityLookup"
         :ItemId id
         (delete-keyword :Operation args)))

(define-method aws:similarity-lookup (id . args)
  (apply aws:similarity-lookup (current-aws) id args))

; BrowseNodeLookup
;
(define-method aws:browsenode-lookup ((aws <aws>) id . args)
  (apply aws:send-rest-lite aws
         :Operation "BrowseNodeLookup"
         :BrowseNodeId id
         (delete-keyword :Operation args)))

(define-method aws:browsenode-lookup (id . args)
  (apply aws:browsenode-lookup (current-aws) id args))

; CustomerContentSearch
;
(define-method aws:customercontent-search ((aws <aws>) . args)
  (apply aws:send-rest-lite aws
         :Operation "CustomerContentSearch"
         (delete-keyword :Operation args)))

(define-method aws:customercontent-search args
  (apply aws:customercontent-search (current-aws) args))

; TransactionLookup
;
(define-method aws:transaction-lookup ((aws <aws>) id . args)
  (apply aws:send-rest-lite aws
         :Operation "TransactionLookup"
         :TransactionId id
         (delete-keyword :Operation args)))

(define-method aws:transaction-lookup (id . args)
  (apply aws:transaction-lookup (current-aws) args))

; Help
;
(define-method aws:help ((aws <aws>) . args)
  (apply aws:send-rest-lite aws
         :Operation "Help"
         (delete-keyword :Operation args)))

(define-method aws:help args
  (apply aws:help (current-aws) args))

; Local Utility Functions for Cart Operation after here.
;
(define (%trans seq src dst)
  (match src
    (() dst)
    ((:ASIN i :Q n . args)
     (%trans (+ seq 1) args
             (apply list
                    (make-keyword #`"Item.,|seq|.ASIN") i
                    (make-keyword #`"Item.,|seq|.Quantity") n
                    dst)))
    ((:OfferListingId i :Q n . args)
     (%trans (+ seq 1) args
             (apply list
                    (make-keyword #`"Item.,|seq|.OfferListingId") i
                    (make-keyword #`"Item.,|seq|.Quantity") n
                    dst)))
    ;; :CartItemId is for cart-modify
    ((:CartItemId i :Q n . args)
     (%trans (+ seq 1) args
             (apply list
                    (make-keyword #`"Item.,|seq|.CartItemId") i
                    (make-keyword #`"Item.,|seq|.Quantity") n
                    dst)))
    ((:CartItemId i :Action a . args)
     (%trans (+ seq 1) args
             (apply list
                    (make-keyword #`"Item.,|seq|.CartItemId") i
                    (make-keyword #`"Item.,|seq|.Action") a
                    dst)))
    ;; AWS Not Supported?
    ((:ListItemId i :Q n . args)
     (%trans (+ seq 1) args
             (apply list
                    (make-keyword #`"Item.,|seq|.ListId") i
                    (make-keyword #`"Item.,|seq|.Quantity") n
                    dst)))
    ((key i . args)
     (case key
       ((:ASIN :OfferListingId :CartItemId :ListItemId)
        (%trans seq (apply list key i :Q 1 args) dst))
       (else (%trans seq args (apply list key i dst)))))))

(define (result-to-cart-set! res cart)
  (if (aws:pass? res)
      (let1 body (Body-of res)
        (set! (CartId-of cart)
              ((if-car-sxpath '(// AWS:CartId *text*)) body))
        (set! (HMAC-of cart)
              ((if-car-sxpath '(// AWS:HMAC *text*)) body))
        (set! (Cart-of cart) body)
        (set! (Error-of cart) '()))
      (set! (Error-of cart) (Body-of res))))


; CartCreate
;
(define-method aws:cart-create ((aws <aws>) . args)
  (let* ((res (apply aws:send-rest-lite aws
                     :Operation "CartCreate"
                     (%trans 1 (delete-keyword :Operation args) '())))
         (body (Body-of res)))
    (cond ((aws:pass? res)
           (make <cart>
             :CartId ((if-car-sxpath '(// AWS:CartId *text*)) body)
             :HMAC ((if-car-sxpath '(// AWS:HMAC *text*)) body)
             :Cart body
             :Error '()))
          (else (make <cart> :CartId #f :HMAC #f :Cart '() :Error body)))))

(define-method aws:cart-create args
  (apply aws:cart-create (current-aws) args))

; CartGet
;
(define-method aws:cart-get ((aws <aws>) (cart <cart>) . args)
  (let* ((res (apply aws:send-rest-lite aws
                     :Operation "CartGet"
                     :CartId (CartId-of cart)
                     :HMAC (HMAC-of cart)
                     (delete-keyword :Operation args)))
         (body (Body-of res)))
    (result-to-cart-set! res cart)
    cart))

(define-method aws:cart-get ((cart <cart>) . args)
  (apply aws:cart-get (current-aws) cart args))

;; This API don't need?
(define-method aws:cart-get ((aws <aws>) . args)
  (let* ((res (apply aws:send-rest-lite aws
                     :Operation "CartGet"
                     (delete-keyword :Operation args)))
         (body (Body-of res)))
    (if (aws:pass? res)
        (make <cart>
          :CartId ((if-car-sxpath '(// AWS:CartId *text*)) body)
          :HMAC ((if-car-sxpath '(// AWS:HMAC *text*)) body)
          :Cart body
          :Error '())
        (make <cart> :CartId #f :HMAC #f :Cart '() :Error body))))

(define-method aws:cart-get args
  (apply aws:cart-get (current-aws) args))


; CartClear
;
(define-method aws:cart-clear! ((aws <aws>) (cart <cart>))
  (let* ((res (aws:send-rest-lite aws
                                  :Operation "CartClear"
                                  :CartId (CartId-of cart)
                                  :HMAC (HMAC-of cart)))
         (body (Body-of res)))
    (result-to-cart-set! res cart)
    cart))

(define-method aws:cart-clear! ((cart <cart>) . args)
  (apply aws:cart-clear! (current-aws) cart args))

;; This API don't need?
(define-method aws:cart-clear! ((aws <aws>) . args)
  (let* ((res (apply aws:send-rest-lite aws
                     :Operation "CartClear"
                     (delete-keyword :Operation args)))
         (body (Body-of res)))
    (if (aws:pass? res)
        (make <cart>
          :CartId ((if-car-sxpath '(// AWS:CartId *text*)) body)
          :HMAC ((if-car-sxpath '(// AWS:HMAC *text*)) body)
          :Cart body
          :Error '())
        (else (make <cart> :CartId #f :HMAC #f :Cart '() :Error body)))))

(define-method aws:cart-clear! args
  (apply aws:cart-clear! (current-aws) args))

; CartAdd
;
(define-method aws:cart-add! ((aws <aws>) (cart <cart>) . args)
  (define (item-count cart)
    (length ((sxpath '(// AWS:CartItem)) (Cart-of cart))))
  ;; refresh(It's illegal action of 1sec wait rule.)
  ;;(aws:cart-get aws cart)
  (let* ((res (apply aws:send-rest-lite aws
                     :Operation "CartAdd"
                     :CartId (CartId-of cart)
                     :HMAC (HMAC-of cart)
                     (%trans (+ 1 (item-count cart))
                             (delete-keyword :Operation args) '())))
         (body (Body-of res)))
    (result-to-cart-set! res cart)
    cart))

(define-method aws:cart-add! ((cart <cart>) . args)
  (apply aws:cart-add! (current-aws) cart args))

; CartModify
;
(define-method aws:cart-modify! ((aws <aws>) (cart <cart>) . args)
  (define (item-count cart)
    (length ((sxpath '(// AWS:CartItem)) (Cart-of cart))))
  ;; refresh(It's illegal action of 1sec wait rule.)
  ;;(aws:cart-get aws cart)
  (let* ((res (apply aws:send-rest-lite aws
                     :Operation "CartModify"
                     :CartId (CartId-of cart)
                     :HMAC (HMAC-of cart)
                     (%trans 1 (delete-keyword :Operation args) '())))
         (body (Body-of res)))
    (result-to-cart-set! res cart)
    cart))

(define-method aws:cart-modify! ((cart <cart>) . args)
  (apply aws:cart-modify! (current-aws) cart args))

;;
;; High Level API - AWS Utility
;;

;;
;; ItemSearch
;;
(define-method aws:blended-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Blended" args))

(define-method aws:blended-search args
  (apply aws:blended-search (current-aws) args))

(define-method aws:books-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Books" args))

(define-method aws:books-search args
  (apply aws:books-search (current-aws) args))

(define-method aws:classical-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Classical" args))

(define-method aws:classical-search args
  (apply aws:classical-search (current-aws) args))

(define-method aws:dvd-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "DVD" args))

(define-method aws:dvd-search args
  (apply aws:dvd-search (current-aws) args))

(define-method aws:electronics-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Electronics" args))

(define-method aws:electronics-search args
  (apply aws:electronics-search (current-aws) args))

(define-method aws:foreignbooks-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "ForeignBooks" args))

(define-method aws:foreignbooks-search args
  (apply aws:foreignbooks-search (current-aws) args))

(define-method aws:healthpersonalcare-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "HealthPersonalCare" args))

(define-method aws:healthpersonalcare-search args
  (apply aws:healthpersonalcare-search (current-aws) args))

(define-method aws:hobbies-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Hobbies" args))

(define-method aws:hobbies-search args
  (apply aws:hobbies-search (current-aws) args))

(define-method aws:kitchen-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Kitchen" args))

(define-method aws:kitchen-search args
  (apply aws:kitchen-search (current-aws) args))

(define-method aws:music-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Music" args))

(define-method aws:music-search args
  (apply aws:music-search (current-aws) args))

(define-method aws:musictracks-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "MusicTracks" args))

(define-method aws:musictracks-search args
  (apply aws:musictracks-search (current-aws) args))

(define-method aws:software-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Software" args))

(define-method aws:software-search args
  (apply aws:software-search (current-aws) args))

(define-method aws:sportinggoods-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "SportingGoods" args))

(define-method aws:sportinggoods-search args
  (apply aws:sportinggoods-search (current-aws) args))

(define-method aws:toys-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Toys" args))

(define-method aws:toys-search args
  (apply aws:toys-search (current-aws) args))

(define-method aws:vhs-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "VHS" args))

(define-method aws:vhs-search args
  (apply aws:vhs-search (current-aws) args))

(define-method aws:video-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Video" args))

(define-method aws:video-search args
  (apply aws:video-search (current-aws) args))

(define-method aws:videogames-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "VideoGames" args))

(define-method aws:videogames-search args
  (apply aws:videogames-search (current-aws) args))

(define-method aws:watches-search ((aws <aws>) . args)
  (apply aws:item-search aws :SearchIndex "Watches" args))

(define-method aws:watches-search args
  (apply aws:watches-search (current-aws) args))

;;
;; ItemLookup
;;
(define-method aws:asin-lookup ((aws <aws>) item-id . args)
  (apply aws:item-lookup aws :IdType "ASIN" :ItemId item-id args))

(define-method aws:asin-lookup (item-id . args)
  (apply aws:asin-lookup (current-aws) item-id args))

(define-method aws:dpci-lookup ((aws <aws>) item-id . args)
  (apply aws:item-lookup aws :IdType "DPCI" :ItemId item-id args))

(define-method aws:dpci-lookup (item-id . args)
  (apply aws:dpci-lookup (current-aws) item-id args))

(define-method aws:ean-lookup ((aws <aws>) item-id . args)
  (apply aws:item-lookup aws :IdType "EAN" :ItemId item-id args))

(define-method aws:ean-lookup (item-id . args)
  (apply aws:ean-lookup (current-aws) item-id args))

(define-method aws:isbn-lookup ((aws <aws>) item-id . args)
  (apply aws:item-lookup aws :IdType "ISBN" :ItemId item-id args))

(define-method aws:isbn-lookup (item-id . args)
  (apply aws:isbn-lookup (current-aws) item-id args))

(define-method aws:sku-lookup ((aws <aws>) item-id . args)
  (apply aws:item-lookup aws :IdType "SKU" :ItemId item-id args))

(define-method aws:sku-lookup (item-id . args)
  (apply aws:sku-lookup (current-aws) item-id args))

(define-method aws:upc-lookup ((aws <aws>) item-id . args)
  (apply aws:item-lookup aws :IdType "UPC" :ItemId item-id args))

(define-method aws:upc-lookup (item-id . args)
  (apply aws:upc-lookup (current-aws) item-id args))

;;
;; SellerListingLookup
;;
(define-method aws:asin-sellerlisting-lookup ((aws <aws>) id . args)
  (apply aws:sellerlisting-lookup aws :IdType "ASIN" :Id id args))

(define-method aws:asin-sellerlisting-lookup (id . args)
  (apply aws:asin-sellerlisting-lookup (current-aws) id args))

(define-method aws:exchange-sellerlisting-lookup ((aws <aws>) id . args)
  (apply aws:sellerlisting-lookup aws :IdType "Exchange" :Id id args))

(define-method aws:exchange-sellerlisting-lookup (id . args)
  (apply aws:exchange-sellerlisting-lookup (current-aws) id args))

(define-method aws:listing-sellerlisting-lookup ((aws <aws>) id . args)
  (apply aws:sellerlisting-lookup aws :IdType "Listing" :Id id args))

(define-method aws:listing-sellerlisting-lookup (id . args)
  (apply aws:listing-sellerlisting-lookup (current-aws) id args))

(define-method aws:sku-sellerlisting-lookup ((aws <aws>) id . args)
  (apply aws:sellerlisting-lookup aws :IdType "SKU" :Id id args))

(define-method aws:sku-sellerlisting-lookup (id . args)
  (apply aws:sku-sellerlisting-lookup (current-aws) id args))

;;
;; ListSearch
;;
(define-method aws:babyregistry-search ((aws <aws>) . args)
  (apply aws:list-search aws :ListType "BabyRegistry" args))

(define-method aws:babyregistry-search args
  (apply aws:babyregistry-search (current-aws) args))

(define-method aws:weddingregistry-search ((aws <aws>) . args)
  (apply aws:list-search aws :ListType "WeddingRegistry" args))

(define-method aws:weddingregistry-search args
  (apply aws:weddingregistry-search (current-aws) args))

(define-method aws:wishlist-search ((aws <aws>) . args)
  (apply aws:list-search aws :ListType "WishList" args))

(define-method aws:wishlist-search args
  (apply aws:wishlist-search (current-aws) args))

;;
;; ListLookup
;;
(define-method aws:listmania-lookup ((aws <aws>) id . args)
  (apply aws:list-lookup aws :ListType "Listmania" :ListId id args))

(define-method aws:listmania-lookup (id . args)
  (apply aws:listmania-lookup (current-aws) id args))

(define-method aws:weddingregistry-lookup ((aws <aws>) id . args)
  (apply aws:list-lookup aws :ListType "WeddingRegistry" :ListId id args))

(define-method aws:weddingregistry-lookup (id . args)
  (apply aws:weddingregistry-lookup (current-aws) id args))

(define-method aws:wishlist-lookup ((aws <aws>) id . args)
  (apply aws:list-lookup aws :ListType "WishList" :ListId id args))

(define-method aws:wishlist-lookup (id . args)
  (apply aws:wishlist-lookup (current-aws) id args))

;;
;; Help
;;
(define-method aws:help-operation ((aws <aws>) about)
  (let* ((res (aws:help aws :HelpType "Operation" :About about))
         (qry `(// ,(if (aws:pass? res)
                        'AWS:OperationInformation
                        'AWS:Errors))))
    ((sxpath qry) (Body-of res))))

(define-method aws:help-operation (about)
  (aws:help-operation (current-aws) about))


(define-method aws:help-response ((aws <aws>) about)
  (let* ((res (aws:help aws :HelpType "ResponseGroup" :About about))
         (qry `(// ,(if (aws:pass? res)
                        'AWS:ResponseGroupInformation
                        'AWS:Errors))))
    ((sxpath qry) (Body-of res))))

(define-method aws:help-response (about)
  (aws:help-response (current-aws) about))


#|

;; example

(use aws)
(use sxml.sxpath)

(current-aws (make <aws> :AccessKeyId "03F2P9TKR6DSAZ5RSG82"))

;; get help manual

;; if you have your own access kye, replace :AccessKeyId value by yours.

(with-aws (make <aws> :AccessKeyId "03F2P9TKR6DSAZ5RSG82")
          (aws:help-operation "ListLookup"))

(with-aws (make <aws> :AccessKeyId "03F2P9TKR6DSAZ5RSG82")
          (aws:help-operation "TransactionLookup"))

;; get information
(Body-of (aws:similarity-lookup 4756146759))

(with-aws (make <aws> :AccessKeyId "03F2P9TKR6DSAZ5RSG82")
          ((sxpath '(// AWS:Item))
           (Body-of (aws:similarity-lookup 4756146759))))

;; get sellerlisting information by dojiajiba's sellerid.
(with-aws (make <aws> :AccessKeyId "03F2P9TKR6DSAZ5RSG82")
          (Body-of (aws:sellerlisting-search "A3C6SEUOT1L8H")))

;; get similarity information.
;; note that id can be symbol, string, number are all permitted form.
(with-aws (make <aws> :AccessKeyId "03F2P9TKR6DSAZ5RSG82")
          (Body-of (aws:similarity-lookup  'A3C6SEUOT1L8H)))

;; get comic's browsenodes.
(with-aws (make <aws> :AccessKeyId "03F2P9TKR6DSAZ5RSG82")
          (Body-of (aws:browsenode-lookup 466280)))

;; get comic's browsenodes from co.jp and archaeology from com.
;; warnning! this access is not illegal. because it's not 1 sec wait access.
(with-aws (make <aws> :AccessKeyId "03F2P9TKR6DSAZ5RSG82")
          (list (Body-of (aws:browsenode-lookup 466280))
                (Body-of (aws:browsenode-lookup
                          (make <aws>
                            :AccessKeyId "03F2P9TKR6DSAZ5RSG82"
                            :BaseDomain "webservices.amazon.com")
                          11242))))

;; the most low level access
;; it's all round api.
(aws:send-rest (make <aws> :AccessKeyId "03F2P9TKR6DSAZ5RSG82")
               :Operation "ItemSearch"
               :SearchIndex "Music"
               :Artist "大塚愛")

(define mycart (aws:cart-create :ASIN 4274066371 :Q 2))

(use rfc.uri)
(CartId-of mycart)
(HMAC-of mycart)
(Cart-of mycart)
(uri-decode-string
 ((car-sxpath '(// AWS:URLEncodedHMAC *text*)) (Cart-of mycart)))

|#


(provide "aws")

Last modified : 2012/02/07 08:52:09 UTC