federicotdn / verb

Organize and send HTTP requests from Emacs
https://melpa.org/#/verb
GNU General Public License v3.0
545 stars 20 forks source link

Set a verb-var from the result of a request #59

Open astoff opened 1 year ago

astoff commented 1 year ago

This is similar but not quite the same as https://github.com/federicotdn/verb#storing-responses-by-key.

Suppose, for instance, that one would like to extract a login token and store it in a verb-var automatically after calling a login endpoint. It seems that a nice way to do this (and many other things) would be by specifying, as a request property, a hook that is run after the request completes:

* Do login
:PROPERTIES:
:Verb-Hook: (verb-set-var 'token (verb-json-get (oref verb-last body) "access_token"))
:END:
POST www.example.com/login

What do you think?

federicotdn commented 1 year ago

That is a good idea! In order to make it more consistent with Verb-Map-Request, I would instead make Verb-Hook receive a function that itself receives only one parameter, the response itself. For example:

(defun example (res)
  (verb-set-var 'token (verb-json-get (oref res body) "access_token")))

And then:

* Do login
:PROPERTIES:
:Verb-Hook: example
:END:
POST www.example.com/login

A lambda could also be specified there. I would also maybe call the property Verb-Response-Hook instead.

astoff commented 1 year ago

I think I would either define a Verb-Map-Response property that takes a response and returns an actual response to display, or a Verb-Response-Hook that takes no arguments and just performs some side-effects (relying on verb-last).

But in the end anything that allows setting a "token" variable would do the job for me :-).

bigodel commented 1 year ago

A bit late to the party, but Verb-Map-Response could be implemented on the user-side with:

(defun verb--apply-response-fn ()
  "Apply function in VERB-MAP-RESPONSE property to response object."
  (when-let ((res verb-last)
             (rs (oref res request))
             (form (thread-first
                     (format "%smap-response" verb--metadata-prefix)
                     (assoc-string (oref rs metadata) t)
                     cdr
                     verb--nonempty-string))
             (fn-form (verb--try-read-fn-form form))
             (fn (cond
                  ((functionp form) form)
                  ((listp form) (eval form)))))
    (with-current-buffer (other-buffer (current-buffer) 'visible-ok)
      (condition-case nil
          (funcall fn res)
        (error (message "Couldn't parse `%s' as a function." fn))))))

(add-hook 'verb-post-response-hook #'verb--apply-response-fn)

I have been using that particular piece of code for over a year now with no hiccups as far as I remember.

federicotdn commented 1 year ago

Nice! Would you mind opening a PR for it? Note that the thread-first bit can be replaced with the new function verb--request-spec-metadata-get. @bigodel

bigodel commented 1 year ago

Nice! Would you mind opening a PR for it?

Definitely could, but do we really need to add it to the code base? I would think that adding a section to the README would be enough for whoever wishes to have that behaviour to add that function to the response hook.

Note that the thread-first bit can be replaced with the new function verb--request-spec-metadata-get.

LOL I added that function and forgot to update my hook :P

federicotdn commented 1 year ago

Yes we could add it to the README, but I feel like this function specifically is useful enough to have it integrated in the package (for example, last week I also ran into a case where it would've been useful to have it). Since Verb as a package is relatively small I don't mind adding more stuff for the moment - and I also like it being "batteries included" when possible.

bigodel commented 1 year ago

Yes we could add it to the README, but I feel like this function specifically is useful enough to have it integrated in the package (for example, last week I also ran into a case where it would've been useful to have it). Since Verb as a package is relatively small I don't mind adding more stuff for the moment - and I also like it being "batteries included" when possible.

All right, I'll be creating the PR soon then.

-- João Pedro de A. Paula IT bachelors at Universidade Federal do Rio Grande do Norte (UFRN)

bigodel commented 1 year ago

I have created the PR to get some early reviews, but I still need to add tests for the new function that parses forms into function objects plus fixing the tests for the previous implementation of verb--try-read-fn-form.

federicotdn commented 1 year ago

Amazing! Thank you, let me know when I can review it

CedricCabessa commented 2 months ago

Hey, new to Verb, I come from restclient when one can easily do somethink like this

POST :base_url/auth/token
Content-Type: application/json
-> jq-set-var :bearer .access_token

and then use authorization: Bearer :bearer

I'm trying to emulate this behavior with Verb and stumble into this issue. Any update on merging the proposed PR?

Thank you for Verb, it looks great

federicotdn commented 2 months ago

Hi, the PR did not have more progress, but for your use case you can probably use the following: https://github.com/federicotdn/verb?tab=readme-ov-file#storing-responses-by-key (send the /auth/token request, store it in e.g. "auth", then retrieve the value inside the response via code inside code tags).