[racket] HTTP POST: curl vs racket net library

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Mon Nov 3 19:19:11 EST 2014

It did not work because

(authcode "sk_test_BQokikJOvBiI2HlWgH4olfQ2:")

is

#"c2tfdGVzdF9CUW9raWtKT3ZCaUkySGxXZ0g0b2xmUTI6\r\n"

which contains "\r\n" which are illegal characters in an HTTP header,
so your HTTP request was messed up. Specifically, it ended in
"\r\n\r\n\r\n". The first "\r\n" ended the last header. The second
"\r\n" ended the HTTP header segment. And the third "\r\n" was
correctly parsed as POST data on the server side.

You really want something like this:

(define (subbytes* b st en)
  (subbytes b st (+ (bytes-length b) en)))
(subbytes* (authcode "sk_test_BQokikJOvBiI2HlWgH4olfQ2:") 0 -2)

As far as a less verbose way to do it, the Racket code has exactly one
expression for each argument to CURL. I think the only thing I would
do differently is turn this into a function that I call with various
arguments for each of the stripe API URLs.

Jay

On Mon, Nov 3, 2014 at 12:31 PM, pior neer <pior.neer at gmail.com> wrote:
> Here is an example (which worked once) I am trying to replicate in Racket.
>
> curl https://api.stripe.com/v1/customers \
>    -u sk_test_BQokikJOvBiI2HlWgH4olfQ2: \
>    -d "description=Customer for test at example.com" \
>    -d card=tok_14unJi2eZvKYlo2C804uRph5
>
> Here is my Racket code that does a "similar" thing.
>
> #lang racket
>
> (require net/http-client)
> (require net/url)
> (require net/uri-codec)
> (require net/base64)
> (require json)
>
> (define (authcode key)
>   (base64-encode (string->bytes/utf-8 key)))
>
> (define (make-customer #:email email #:token token)
>
>   (define-values (status-code header inport)
>     (http-sendrecv
>      "api.stripe.com"
>      "/v1/customers"
>      #:ssl? #t
>      #:method "POST"
>      #:data (alist->form-urlencoded
>              (list (cons 'card "token")))
>      #:headers (list (format "Authorization: Basic ~a"
>                              (authcode
> "sk_test_BQokikJOvBiI2HlWgH4olfQ2:")))))
>   (read-json inport))
>
> (make-customer #:email "jondo at example.com"
>                #:token "tok_14unJi2eZvKYlo2C804uRph5" )
>
> The above results in
>
> '#hasheq((error
>           .
>           #hasheq((param . "\r\ncard")
>                   (message
>                    .
>                    "Received unknown parameter: \r\ncard")
>                   (type . "invalid_request_error"))))
>
> Questions:
>
> 1) Why does the server parses \r\nkey instead of just key when using Racket?
>
> 2) Is there a less verbose way to express the same thing?
>
>
>
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
>



-- 
Jay McCarthy
http://jeapostrophe.github.io

           "Wherefore, be not weary in well-doing,
      for ye are laying the foundation of a great work.
And out of small things proceedeth that which is great."
                          - D&C 64:33

Posted on the users mailing list.