node-sonos-http-api
node-sonos-http-api copied to clipboard
How to call sayall from own app and getting around invalid uri error?
I'm trying to figure out how to use the sayall function with a rails app using uri's open, for example
uri = URI.parse(URI.encode("#{HOST}:#{PORT}/sayall/#{speak_what}"))
response = open(uri).read
Here's an example request with a 302:
Request URL: http://localhost:3000/text_to_speech?utf8=%E2%9C%93&text_to_speak=go+to+sleep
Request Method: GET
Status Code: 302 Found
I'm assuming I have to URI.encode it otherwise I get
URI::InvalidURIError (bad URI(is not URI?): myhost:5005/sayall/go to sleep)
There are other methods:
Addressable::URI.parse
CGI::escape
HTMLEntities.new.decode
However since sayall
uses decodeURIComponent()
, I don't know what I need to do to get the request through in a raw format similar to what a browser will accept (with spaces), which seems to be necessary for sayall
, correct?
I may have to resort to javascript XMLHttpRequest
I had that working fine with a raw javascript app, having hard time mapping what that does to the 'railsy' way.
Any suggestions?
I think you are going about it wrong. Do note that you should only encode the actual phrase, because what you are actually doing is converting a string to be passed as an argument (or, as a path folder name), which means that if you send in a full url for encoding, it will try to escape everything in it to be able to send it as a query parameter. Here is the distinction, query strings can take +
as space, whereas a URL path can not (and this API uses a URL path).
I'm not familiar with Ruby, but a quick googling gives me that ERB::Util.url_encode
would work correctly, CGI::Util.escape won't work. HTML entities is something different, it's for escaping into markup.
You are correct, I should be encoding just the string. Fixed.
I am still confused. Lets take my code out of the picture first. When I simply use the node-sonos-http-api from the browser like /sayall/go%20to%20sleep
it returns 302 but does not actually say through the speakers. if use it like http://192.168.1.26:5005/sayall/go to sleep
it works (not sure what the browser is doing under the hood here). Am I correct in that we want the escape characters in the request (thus the point of using ERB::Util.url_encode
?
Here's my updated code for more context.
def speak
speak_what = params[:text_to_speak]
# speak_what = 'go to sleep'
puts "speak_what=#{speak_what}"
if !speak_what.present? then return end
speak_what_encoded = ERB::Util.url_encode(speak_what)
puts "speak_what_encoded=#{speak_what_encoded}"
uri = "#{HOST}:#{PORT}/sayall/#{speak_what_encoded}"
begin
puts "uri=#{uri}"
response = open(uri).read
rescue ActionController::UnknownFormat => e
if e.include? '204'
# do nothing
else
raise e
end
end
redirect_to :controller => 'presets', :action => 'display'
end
which results in
Started GET "/text_to_speech?utf8=%E2%9C%93&text_to_speak=go+to+sleep" for ::1 at 2019-05-27 16:51:04 -0500
Processing by TextToSpeechController#speak as HTML
Parameters: {"utf8"=>"✓", "text_to_speak"=>"go to sleep"}
speak_what=go to sleep
speak_what_encoded=go%20to%20sleep
uri=http://192.168.1.26:5005/sayall/go%20to%20sleep
Redirected to http://localhost:3000/
Now, some of that in the log above shows my controller being called, but my controller is making a get request to the uri
(that .26 is the node-sonos-http-api server)
I'll have to dig deeper and probably just use javascript XMLHttpRequest
for now but if you have any other suggestions/advice much appreciated
Yoy shouldn't get a 302 and definitely not be redirected to port 3000 on localhost. Something is off with the machine you are invoking it from... Does it have a proxy configured or something?
On Tue, 28 May 2019, 00:03 jzajac2, [email protected] wrote:
You are correct, I should be encoding just the string. Fixed. I am still confused. Lets take my code out of the picture first. When I simply use the node-sonos-http-api from the browser like /sayall/go%20to%20sleep it returns 302 but does not actually say through the speakers. if use it like http://192.168.1.26:5005/sayall/go to sleep it works (not sure what the browser is doing under the hood here). Am I correct in that we want the escape characters in the request (thus the point of using ERB::Util.url_encode ?
Here's my updated code for more context.
def speak
speak_what = params[:text_to_speak] # speak_what = 'go to sleep' puts "speak_what=#{speak_what}" if !speak_what.present? then return end speak_what_encoded = ERB::Util.url_encode(speak_what) puts "speak_what_encoded=#{speak_what_encoded}" uri = "#{HOST}:#{PORT}/sayall/#{speak_what_encoded}" begin puts "uri=#{uri}" response = open(uri).read rescue ActionController::UnknownFormat => e if e.include? '204' # do nothing else raise e end end redirect_to :controller => 'presets', :action => 'display'
end
which results in
Started GET "/text_to_speech?utf8=%E2%9C%93&text_to_speak=go+to+sleep" for ::1 at 2019-05-27 16:51:04 -0500
Processing by TextToSpeechController#speak as HTML
Parameters: {"utf8"=>"✓", "text_to_speak"=>"go to sleep"}
speak_what=go to sleep
speak_what_encoded=go%20to%20sleep
uri=http://192.168.1.26:5005/sayall/go%20to%20sleep
Redirected to http://localhost:3000/
Now, some of that in the log above shows my controller being called, but my controller is making a get request to the uri (that .26 is the node-sonos-http-api server)
I'll have to dig deeper and probably just use javascript XMLHttpRequest for now but if you have any other suggestions/advice much appreciated
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/jishi/node-sonos-http-api/issues/696?email_source=notifications&email_token=AAYE2IYIFXCHOKJ6VSKXSS3PXRLB5A5CNFSM4HPWZRK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODWKSARY#issuecomment-496312391, or mute the thread https://github.com/notifications/unsubscribe-auth/AAYE2I6EWLQ7JN4HCIPCBADPXRLB5ANCNFSM4HPWZRKQ .
the redirection is intentional (and temporary for now) and port 3000 as well (default for puma/webrick based servers I guess). Let me make sure I have all the latest code running first :)
Aha, now I understand what you mean. But either way, the url http://192.168.1.26:5005/sayall/go%20to%20sleep
looks correct, no? are you saying it doesn't work? Try using curl
or similar, if that works, you are doing something weird in ruby.
Well, I'm saying even when I put http://192.168.1.26:5005/sayall/go%20to%20sleep
in the browser, same result - I would get a 'success' but nothing coming out of the speakers, I'm really trying to keep my application out of it right now. I haven't updated / merged your updates to my fork in...quite a while, although I didn't see anything specific to sayall
I should.
Yes it's possible also something weird in ruby (rails) as fun and easy as it is to work with well, there's a cost to the magic.
Yep I'll try curl
curl http://192.168.1.26:5005/sayall/go%20to%20sleep
and I do not hear it through the speakers although I get success :(. :
jzajac$ curl http://192.168.1.26:5005/sayall/go%20to%20sleep
{"status":"success"}
I'll dig more though
after updating some npm modules per github's security request the same curl request now produces:
curl http://192.168.1.26:5005/sayall/go%20to%20sleep {"status":"error","error":"Buffer.alloc is not a function","stack":"TypeError: Buffer.alloc is not a function\n at FileTokenizer.AbstractTokenizer (/home/pi/code/node-sonos-http-api/node_modules/strtok3/lib/AbstractTokenizer.js:7:33)\n at new FileTokenizer (/home/pi/code/node-sonos-http-api/node_modules/strtok3/lib/FileTokenizer.js:23:28)\n at /home/pi/code/node-sonos-http-api/node_modules/strtok3/lib/index.js:38:24\n at invokeCallback (/home/pi/code/node-sonos-http-api/node_modules/es6-promise/dist/es6-promise.js:408:15)\n at publish (/home/pi/code/node-sonos-http-api/node_modules/es6-promise/dist/es6-promise.js:391:7)\n at flush (/home/pi/code/node-sonos-http-api/node_modules/es6-promise/dist/es6-promise.js:128:5)\n at doNTCallback0 (node.js:417:9)\n at process._tickDomainCallback (node.js:387:13)"}
Raise separate issue?