mihaiolteanu / vuiet

The music player and explorer for Emacs
https://mihaiolteanu.me/vuiet
GNU General Public License v3.0
278 stars 15 forks source link

Error signing in to vuiet #32

Closed eklebanow closed 3 years ago

eklebanow commented 3 years ago

After many months of successful use of vuiet I suddenly cannot access vuiet in emacs. When I try to play loved tracks I get the following error: Play random? (y or n) y [error] request--callback: peculiar error: 411 [error] request-default-error-callback: http://ws.audioscrobbler.com/2.0/ error

Can you help me figure out why I am getting this error?

I am using doom emacs which uses emacs 27.1

Not sure if this is related but I also am getting error message upon starting doom emacs that the cL library is deprecated. Apparently vuiet uses cl (which is to be replaced by cl-lib) see https://github.com/hlissner/doom-emacs/issues/3372

mihaiolteanu commented 3 years ago

I can reproduce that error, too,

[error] request--callback: peculiar error: 411
[error] request-default-error-callback: http://ws.audioscrobbler.com/2.0/ error

It is from the lastfm.el library. Digging a lit deeper, I think it has to do with the request.el library used to fetch the data from lastfm.

The response from lastfm is

"<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content=\"initial-scale=1, minimum-scale=1, width=device-width\">
  <title>Error 411 (Length Required)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
  </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>411.</b> <ins>That’s an error.</ins>
  <p>POST requests require a <code>Content-length</code> header.  <ins>That’s all we know.</ins>
"

which would indicate that Content-Length is missing from the request header, as seen here, for example, https://stackoverflow.com/a/58711342/2819719

There is not such symbol or string in the request.el libary, for example.

I do not have any more info at this moment. I will let you know as soon as I find something.

mihaiolteanu commented 3 years ago

This is the request to lastm that fails,

(request "http://ws.audioscrobbler.com/2.0/"
  :params '(("api_key" . "yourapikey") ("method" . "artist.getInfo") ("artist" . "anathema"))
  :parser #'buffer-string
  :type   "POST"
  :sync   t
  :complete (cl-function
             (lambda (&key data &allow-other-keys)
               data)))
[error] request--callback: peculiar error: 411
[error] request-default-error-callback: http://ws.audioscrobbler.com/2.0/ error
#s(request-response 411 nil "<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content=\"initial-scale=1, minimum-scale=1, width=device-width\">
  <title>Error 411 (Length Required)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
  </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>411.</b> <ins>That’s an error.</ins>
  <p>POST requests require a <code>Content-length</code> header.  <ins>That’s all we know.</ins>
" (error http 411) error "http://ws.audioscrobbler.com/2.0/?api_key=blabla&method=artist.getInfo&artist=anathema" t (:params (("api_key" . "cee0672413bfd44ad4904aaf3ee1330b") ("method" . "artist.getInfo") ("artist" . "anathema")) :parser buffer-string :type "POST" :sync t :complete (lambda (&rest --cl-rest--) "

(fn &key DATA &allow-other-keys)" (let* ... data)) :error #[128 "ÂÀÃÁ\"\"‡" [request-default-error-callback ... apply append] 6 "

(fn &rest ARGS2)"] ...) #<killed buffer> "HTTP/1.0 411 Length Required
Content-Type: text/html; charset=UTF-8
Referrer-Policy: no-referrer
Content-Length: 1564
Date: Sun, 15 Nov 2020 07:46:41 GMT
" nil ...)
mihaiolteanu commented 3 years ago

@eklebanow any clue? Did you find something?

aluaces commented 3 years ago

Hi, I have it working if I set request-curl-options to -d "" so curl sends the required length.

I know it is a hack, but something to have it working in the meantime.

mihaiolteanu commented 3 years ago

Hello Alberto,

Thanks for having a look on this. You are talking about this,

(defcustom request-curl-options nil
  "curl command options.

List of strings that will be passed to every curl invocation. You can pass
extra options here, like setting the proxy."
  :type '(repeat string))

right?

If that's the case, defcustom uses defvar underneath, so this is a special variable (i.e. it would be written as *request-curl-options*, in common lisp). This means you can bind it in a let form, for example, and it will be set to the new value just for the duration of this let form. You can can then call the request for last.fm inside this let.

If you've tested it and you want to merge it, I would gladly accept your PR.

Thanks, Mihai

aluaces commented 3 years ago

Hi, Mihai,

Yes and yes :-) Actually I was going to suggest that route to you, but since I'm not very experienced in elisp, I was not sure if it could be done. My first intention was to use a lexical scope variable, is it the same or something different? I always thought of them as a "private copy of a global variable for some scope".

Anyway I will try to craft the patch as you suggest and send the PR.

mihaiolteanu commented 3 years ago

They're quite different, and it helps us a lot here that request-curl-options is a dynamic variable.

With a lexical variable you wouldn't be able to say "ok, request call, I know you're using the request-curl-options somewhere in your body, and even though I can't see where, I would like you to use this value that I'm binding in this let form in all your future calls, as long as I'm calling you inside this let", which is what it actually happens with a dynamic variable.

We can simulate the same effect with a lexical variable, by first remembering its value in a new variable, then setting it's value to what we want, then evaluating the request form, and then remembering to set it back to it's original value.

I think the differences are quite subtle, though, and it has to do with the behavior of dynamic vs lexical environments. In our case, if request-curl-options were not dynamic, you would not be able to do,

(let ((request-curl-options "-d \"\""))
   (request "last.fm/etc..."))

and expect it to work. The request call would still use it's old request-curl-options, and what we could do in that case would be something like this (in case we wouldn't want to change the request-curl-options for everyone, but only for this call),

(let ((old-request-curl-options (copy-sequence request-curl-options))
       (setq request-curl-options "-d \"\""))
   (request "lastfm/etc...")
   (setq request-curl-options old-request-curl-options))