Duncan Bayne
Duncan Bayne

Reputation: 3959

Failing to pass function parameters parsed from command line arguments

I have a function which uses Drakma to GET a web page:

(defun scrape ()
  (let ((cookie-jar (make-instance 'drakma:cookie-jar)))
    (drakma:http-request "http://www.example.com/account/login"
             :method :post
             :parameters '(("username" . "myusername")
                       ("password" . "mypassword"))
             :cookie-jar cookie-jar)
    (setq body (drakma:http-request "http://www.example.com/"
                    :cookie-jar cookie-jar))
    (format t body)))

This works just as I expect. However, if I parameterise the username and password like so:

(defun scrape (username password)
  (let ((cookie-jar (make-instance 'drakma:cookie-jar)))
    (drakma:http-request "http://www.example.com/account/login"
             :method :post
             :parameters '(("username" . username)
                       ("password" . password))
             :cookie-jar cookie-jar)
    (setq body (drakma:http-request "http://www.example.com/"
                    :cookie-jar cookie-jar))
    (format t body)))

... and invoke it like so:

(scrape "my_username" "my_password")

... then I get the following error:

*** - Don't know what to do with name/value pair ("username" . USERNAME) in multipart/form-data body.

I'm new to Lisp, so I'm 100% certain that I'm missing something very straightforward to do with parameters here. E.g. if I add a call to format to the scrape function I can see that the username is being passed through correctly.

Upvotes: 3

Views: 320

Answers (2)

Nietzche-jou
Nietzche-jou

Reputation: 14730

When you use quotation to create a literal list, the quotation extends down to inhibit evaluation of all the members of the list. You can see how username got upcased by the time it got printed out, which is the default for reading symbols.

You have to build up the list structure using LIST and CONS forms as necessary, or use the backquote which allows you to selectively evaluate pieces, i.e.

(list (cons "username" username)
      (cons "password" password))

or

`(("username" . ,username)
  ("password" . ,password))

Upvotes: 2

Xach
Xach

Reputation: 11839

The parameters argument to drakma:http-request is quoted, so it's not getting the strings you passed in the alist, it's getting the symbols USERNAME and PASSWORD. You need to construct the list in such a way that it includes the argument variables in a context where they're evaluated, e.g. (list (cons "username" username) (cons "password" password)).

Upvotes: 1

Related Questions