How does the 'u' flag in curl convert to clj-http?

How do I convert this cURL call into cli-http?

I realize this is probably a stupid question, but I have tried every possible variation:

I’ll change the key for security.

This works fine:

curl https://api.stripe.com/v1/charges -u sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:\n

I am trying to figure out how the “-u” translates to clj-http. I tried (using both POST and GET):

========> (client/post “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G” “”]})
(client/post “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G” “”]})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 400

========> (client/post “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G” “:”]})
(client/post “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G” “:”]})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 400

========> (client/post “https://api.stripe.com/v1/charges” {:headers {“u” “sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G”}})
(client/post “https://api.stripe.com/v1/charges” {:headers {“u” “sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G”}})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

========> (client/post “https://api.stripe.com/v1/charges” {:headers {“u” “sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:”}})
(client/post “https://api.stripe.com/v1/charges” {:headers {“u” “sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:”}})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

========> (client/post “https://api.stripe.com/v1/charges” {:body {“u” “sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:”}})
(client/post “https://api.stripe.com/v1/charges” {:body {“u” “sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:”}})
Execution error (ClassCastException) at clj-http.core/request (core.clj:609).
class clojure.lang.PersistentArrayMap cannot be cast to class [B (clojure.lang.PersistentArrayMap is in unnamed module of loader ‘app’; [B is in module java.base of loader ‘bootstrap’)

========> (client/post “https://api.stripe.com/v1/charges” {:body “{"u" : "sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:"}”})
(client/post “https://api.stripe.com/v1/charges” {:body “{"u" : "sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:"}”})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

========> (client/post “https://api.stripe.com/v1/charges” {:body “{"user" : "sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:"}”})
(client/post “https://api.stripe.com/v1/charges” {:body “{"user" : "sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:"}”})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

========> (client/post “https://api.stripe.com/v1/charges” {:form-params {:u “sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:”}})
(client/post “https://api.stripe.com/v1/charges” {:form-params {:u “sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:”}})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

========> (client/post “https://api.stripe.com/v1/charges” {:form-params {:u “sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G”}})
(client/post “https://api.stripe.com/v1/charges” {:form-params {:u “sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G”}})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

========> (client/post “https://api.stripe.com/v1/charges” {:form-params {“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G” “”}})
(client/post “https://api.stripe.com/v1/charges” {:form-params {“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G” “”}})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

========> (client/post “https://api.stripe.com/v1/charges” {:form-params {“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:” “”}})
(client/post “https://api.stripe.com/v1/charges” {:form-params {“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:” “”}})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

========> (client/post “https://api.stripe.com/v1/charges” {:form-params {“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G :” “”}})
(client/post “https://api.stripe.com/v1/charges” {:form-params {“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G :” “”}})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

========> (client/post “https://api.stripe.com/v1/charges” {:body “{"sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G : "}”})
(client/post “https://api.stripe.com/v1/charges” {:body “{"sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G : "}”})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

========> (client/post “https://api.stripe.com/v1/charges” {:body “{"sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:"}”})
(client/post “https://api.stripe.com/v1/charges” {:body “{"sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FS1234567890123456790aXts1FjjPsfV5f821nt6G:"}”})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

curl -u probably uses the basic authentication, you can confirm that by executing the command with -vvv and looking at the request details.

If so, you have to create the right value for the Authorization header.

Thank you p-himik. I tried that but:

  `curl -vvv -X GET "https://api.stripe.com/v1/charges" --user "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:"`

Works fine and shows me:

  • Server auth using Basic with user ‘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:’
  • Using Stream ID: 1 (easy handle 0x14d00d000)

GET /v1/charges HTTP/2
Host: api.stripe.com
authorization: Basic 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:

But I am not sure how to translate that into cli-http:

=============> (client/get “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfCHDhk0BMWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G:”] })
(client/get “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfCHNtETWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G:”] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

=============> (client/post “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfCHhk0BMWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G:”] })
(client/post “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniETqDhk0BMWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G:”] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

=============> (client/post “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfDhk0BMWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G:” “”] })
(client/post “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfCHNtETqDasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G:” “”] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

=============> (client/post “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHultefCHNtETqDhk0BMWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G” “:”] })
(client/post “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHultehHNtETqDhk0BMWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G” “:”] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

=============> (client/get “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHultfCHNtETqDhk0BMWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G” “:”] })
(client/get “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfqDhk0BMWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G” “:”] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

=============> (client/get “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulHNtETqDhk0BMWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G” “:”] })

All fail.

All 401.

I also tried these use POST.

Are you sure the last line is indeed that and not something you’ve replaced for this post because it looked like the original user:pass?

Here’s what I see, with some elision of unnecessary detail:

$ curl -vvv -u the_user:the_pass example.com
[...]
* Server auth using Basic with user 'the_user'
> GET / HTTP/1.1
> Host: example.com
> Authorization: Basic dGhlX3VzZXI6dGhlX3Bhc3M=
> User-Agent: curl/8.5.0
> Accept: */*
> 
< HTTP/1.1 200 OK
[...]

Notice how the header Authorization: Basic dGhlX3VzZXI6dGhlX3Bhc3M= doesn’t resemble the original the_user:the_pass at all.

2 Likes

I appreciate your help, but I don’t understand the question. Stripe’s official documentation for the API suggests using a “:” to skip the password. This works well in the cURL example. But I cannot figure out how it should be translated into cli-http.

If I use -vvv I see this output in the Terminal.

What difference do you see?

I’ve uploaded a screenshot so you can see what I am seeing.

Stripe’s official documentation for the API suggests using a “:” to skip the password.

It means that the password is empty, that’s it. And the username is probably some token.

I’ve uploaded a screenshot so you can see what I am seeing.

Well, yeah, that’s what I meant - the line that starts with authorization: Basic has some encoded content that’s derived from the combination of username and password (which in your case is empty). Basic auth is well documented, you just gotta follow what is described there and it should work.

Ah, after checking the README of clj-http I now see that you have actually tried :basic-auth and it didn’t work. And you’ve tried multiple combinations of things.
However, you have missed one combination - GET with the username being that long string and the password being an empty string:

 (client/get "https://api.stripe.com/v1/charges"
             {:basic-auth ["sk_live_51HheTgHulteheniUfCHDhk0BMWSasdfghjklmnbvcxzasdf1FjjPsfV5f821nt6G" ""] })

Alternatively, provide a string that ends with : but don’t wrap it in [...].

1 Like

I appreciate your help.

I am sad to say that I’ve run out of ideas.

I’ve never had so much trouble translating a working cURL command to cli-http. Do you have any thoughts about an HTTP library in Clojure that might be more transparent?

I tried all of these:


===============>            (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G" ""] })
  (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G" ""] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

===============>            (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G" " "] })
  (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G" " "] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

===============>            (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G:" " "] })
  (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G:" " "] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

===============>            (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G:" ":"] })
  (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G:" ":"] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

===============>            (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G" ":"] })
  (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G" ":"] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

===============>            (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G"] })
  (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G"] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

===============>            (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G:"] })
  (client/get "https://api.stripe.com/v1/charges" {:basic-auth ["sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G:"] })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

===============>            (client/get "https://api.stripe.com/v1/charges" {:basic-auth "sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G:" })
  (client/get "https://api.stripe.com/v1/charges" {:basic-auth "sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G:" })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

===============>            (client/get "https://api.stripe.com/v1/charges" {:basic-auth "sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G" })
  (client/get "https://api.stripe.com/v1/charges" {:basic-auth "sk_live_51HheTgHulteheniUfCHNtETqDhk0asdfghjklZXCVBNqwertyu0aXts1FjjPsfV5f821nt6G" })
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

Simply setting the header, directly, should work, but I cannot get it to work:

===============> (client/get “https://api.stripe.com/v1/charges” {:headers {“Authorization” “Basic sk_live_51HheTgHulteheniUfCHNtasdfghjkloi1234567890mSDFHWRTts1FjjPsfV5f821ntcqclzhd6c000GzlCzt6G”}})
(client/get “https://api.stripe.com/v1/charges” {:headers {“Authorization” “Basic sk_live_51HheTgHulteheniUfCHNtasdfghjkloi1234567890mSDFHWRTts1FjjPsfV5f821ntcqclzhd6c000GzlCzt6G”}})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401
===============> (client/post “https://api.stripe.com/v1/charges” {:headers {“Authorization” “Basic sk_live_51HheTgHulteheniUfCHNtasdfghjkloi1234567890mSDFHWRTts1FjjPsfV5f821ntcqclzhd6c000GzlCzt6G”}})
(client/post “https://api.stripe.com/v1/charges” {:headers {“Authorization” “Basic sk_live_51HheTgHulteheniUfCHNtasdfghjkloi1234567890mSDFHWRTts1FjjPsfV5f821ntcqclzhd6c000GzlCzt6G”}})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401
===============> (client/post “https://api.stripe.com/v1/charges” {:headers {“Authorization” “Basic sk_live_51HheTgHulteheniUfCHNtasdfghjkloi1234567890mSDFHWRTts1FjjPsfV5f821ntcqclzhd6c000GzlCzt6G:”}})
(client/post “https://api.stripe.com/v1/charges” {:headers {“Authorization” “Basic sk_live_51HheTgHulteheniUfCHNtasdfghjkloi1234567890mSDFHWRTts1FjjPsfV5f821ntcqclzhd6c000GzlCzt6G:”}})
Execution error (ExceptionInfo) at slingshot.support/stack-trace (support.clj:201).
clj-http: status 401

If you set the header directly, you also have to properly encode the value. You can’t just put the username/token there.

As for why my suggestion didn’t work - no clue, sorry. At this point, I’d try confirming that it doesn’t work with some other library and then I’d try tracing the request to see what’s getting sent over the wire.

Thank you for the help.

This worked:

(client/get “https://api.stripe.com/v1/charges” {:basic-auth [“sk_live_51HheTgHulteheniUfCHNtETqDhk0BMWSLhGT4FSK5LtRStBbGnFasdfghjlk09234GFVO93JKUY1asdlfkgj” “”]})

I’m surprised that in the 50 or 60 variations that I tried, I never tried that before.