Hi all, I''m working on a Backbone.js single page app with Rails 3.1, and in an attempt to save on HTTP requests, I want to embed initial data set in a HTML document that is sent back to the browser after successful login. I was thinking I can simply convert my ruby object to JSON, then HTML escape resulting string of JSON, and then use that as a value for JavaScript variable. Something like this: <% tags = [{name:"tag1", color:"green"}, {name:"</script><b>I can do something bad here</b>", color:"red"}] %> <script type="text/javascript" charset="utf-8"> //<![CDATA[ var tags_list = <%= tags.to_json %>; // ]]> </script> However, this escapes all the double quotes in that string, which triggers a "SyntaxError: Unexpected token &" in Chrome: var tags_list [{"name":"tag1","color":"green"}, {"name":"</script><b>I can do something bad here</b>","color":"red"}]; If I remove the Rails'' default HTML escaping with <%=raw tags.to_json %>, then it returns this: var tags_list = [{"name":"tag1","color":"green"},{"name":"</ script><b>I can do something bad here</b>","color":"red"}]; which, of course, breaks the HTML document with "</script>". I guess what I really want is to tell to_json() method to HTML escape keys and values inside JSON object(s), instead of it returning the JSON string unescaped, and then having Rails escape that whole string. I guess what I need is something like this: var tags_list = [{"name":"tag1","color":"green"},{"name":"</ script><b>I can do something bad here</ b>","color":"red"}]; I thought about storing JSON string in a <script type="application/ json" id="json_string"> tag, and then doing something like $.parseJSON($("#json_string").html()) but that also has the same problem of escaping, like in the above example. Is there any easy (Rails) way to do that? Or am I doing it wrong to begin with? Cheers! -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Hi Alex, What is it that you''re actually trying to do? I don''t think its such a good idea to put a JSON string on the client side as it can be manipulated to no end. Why not just call the JSON object directly from the controller instead? David @davidchua On Fri, Aug 26, 2011 at 1:27 AM, Alex Duck <alex2duck-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Hi all, > > I''m working on a Backbone.js single page app with Rails 3.1, and in an > attempt to save on HTTP requests, I want to embed initial data set in > a HTML document that is sent back to the browser after successful > login. > > I was thinking I can simply convert my ruby object to JSON, then HTML > escape resulting string of JSON, and then use that as a value for > JavaScript variable. Something like this: > > > <% tags = [{name:"tag1", color:"green"}, {name:"</script><b>I can do > something bad here</b>", color:"red"}] %> > > <script type="text/javascript" charset="utf-8"> > //<![CDATA[ > var tags_list = <%= tags.to_json %>; > // ]]> > </script> > > > However, this escapes all the double quotes in that string, which > triggers a "SyntaxError: Unexpected token &" in Chrome: > > var tags_list > [{"name":"tag1","color":"green"}, > {"name":"</script><b>I can do something bad > here</b>","color":"red"}]; > > > If I remove the Rails'' default HTML escaping with <%=raw tags.to_json > %>, then it returns this: > var tags_list = [{"name":"tag1","color":"green"},{"name":"</ > script><b>I can do something bad here</b>","color":"red"}]; > > which, of course, breaks the HTML document with "</script>". > > I guess what I really want is to tell to_json() method to HTML escape > keys and values inside JSON object(s), instead of it returning the > JSON string unescaped, and then having Rails escape that whole string. > I guess what I need is something like this: > > var tags_list = [{"name":"tag1","color":"green"},{"name":"</ > script><b>I can do something bad here</ > b>","color":"red"}]; > > I thought about storing JSON string in a <script type="application/ > json" id="json_string"> tag, and then doing something like > > $.parseJSON($("#json_string").html()) > > but that also has the same problem of escaping, like in the above > example. > > > Is there any easy (Rails) way to do that? Or am I doing it wrong to > begin with? > > Cheers! > > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to > rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > For more options, visit this group at > http://groups.google.com/group/rubyonrails-talk?hl=en. > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
David, I want to embed it in HTML so that I can just send that one HTML page to user after log in, and no other HTTP requests are needed before the user can start using the app. This is because it would take several small, but slow, HTTP requests to gather all the data that is needed to show the page. I guess I could whip up a special API method that would return all the data in a single HTTP roundtrip, but if I can pull off this JSOPN embedding, then I can skip even that one extra HTTP requests for initial load. After initial load, app will rarely be needing data from the server, and when it does, it will be using regular API to get that data. This is all just a performance optimization, since most of our users are on a high latency network (mobiles), so those HTTP requests really take a while, and this is an attempt to just skip them altogether. Is there no easy way to embed HTML safe JSON in an HTML document, and have it parsed by JavaScript engine at the same time? Thanks, Alex On Fri, Aug 26, 2011 at 2:19 AM, David Chua <zhchua-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Hi Alex, > > What is it that you''re actually trying to do? I don''t think its such a good > idea to put a JSON string on the client side as it can be manipulated to no > end. > > Why not just call the JSON object directly from the controller instead? > > David > @davidchua > > On Fri, Aug 26, 2011 at 1:27 AM, Alex Duck <alex2duck-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > >> Hi all, >> >> I''m working on a Backbone.js single page app with Rails 3.1, and in an >> attempt to save on HTTP requests, I want to embed initial data set in >> a HTML document that is sent back to the browser after successful >> login. >> >> I was thinking I can simply convert my ruby object to JSON, then HTML >> escape resulting string of JSON, and then use that as a value for >> JavaScript variable. Something like this: >> >> >> <% tags = [{name:"tag1", color:"green"}, {name:"</script><b>I can do >> something bad here</b>", color:"red"}] %> >> >> <script type="text/javascript" charset="utf-8"> >> //<![CDATA[ >> var tags_list = <%= tags.to_json %>; >> // ]]> >> </script> >> >> >> However, this escapes all the double quotes in that string, which >> triggers a "SyntaxError: Unexpected token &" in Chrome: >> >> var tags_list >> [{"name":"tag1","color":"green"}, >> {"name":"</script><b>I can do something bad >> here</b>","color":"red"}]; >> >> >> If I remove the Rails'' default HTML escaping with <%=raw tags.to_json >> %>, then it returns this: >> var tags_list = [{"name":"tag1","color":"green"},{"name":"</ >> script><b>I can do something bad here</b>","color":"red"}]; >> >> which, of course, breaks the HTML document with "</script>". >> >> I guess what I really want is to tell to_json() method to HTML escape >> keys and values inside JSON object(s), instead of it returning the >> JSON string unescaped, and then having Rails escape that whole string. >> I guess what I need is something like this: >> >> var tags_list = [{"name":"tag1","color":"green"},{"name":"</ >> script><b>I can do something bad here</ >> b>","color":"red"}]; >> >> I thought about storing JSON string in a <script type="application/ >> json" id="json_string"> tag, and then doing something like >> >> $.parseJSON($("#json_string").html()) >> >> but that also has the same problem of escaping, like in the above >> example. >> >> >> Is there any easy (Rails) way to do that? Or am I doing it wrong to >> begin with? >> >> Cheers! >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Ruby on Rails: Talk" group. >> To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org >> To unsubscribe from this group, send email to >> rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org >> For more options, visit this group at >> http://groups.google.com/group/rubyonrails-talk?hl=en. >> >> > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to > rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > For more options, visit this group at > http://groups.google.com/group/rubyonrails-talk?hl=en. >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Alex Duck wrote in post #1018609:> Is there no easy way to embed HTML safe JSON in an HTML document, and > have > it parsed by JavaScript engine at the same time?You could Base64 encode the JSON and decode it on the client-side with JavaScript. I am ABSOLUTELY NOT recommending that you do this, but simply stating that it could work. Still a bad design idea IMHO. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
I have no idea why embedded json would be considered worse than the rest of the page that is sent down. I do it all the time, usually with small items though, so I haven''t have the problem you are describing. I was hoping that someone would have a suggestion of a built in method to call. I''ve had to do this in a helper that was constructing a complicated object, and I think this is similar to your problem: 1) enumerate through all the parts of your object that could contain dangerous data and call h() on them. 2) call raw(your_object.to_json) on the result. It''s definitely not an easy, generic solution, but it gets you past this problem. On Fri, Aug 26, 2011 at 8:22 AM, Robert Walker <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Alex Duck wrote in post #1018609: >> Is there no easy way to embed HTML safe JSON in an HTML document, and >> have >> it parsed by JavaScript engine at the same time? > > You could Base64 encode the JSON and decode it on the client-side with > JavaScript. > > I am ABSOLUTELY NOT recommending that you do this, but simply stating > that it could work. Still a bad design idea IMHO. >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Peter Hickman
2011-Aug-26 14:43 UTC
Re: Re: How to safely embed JSON object in HTML document
The purpose of JSON is to be able to interchange the data between various systems. As you are not going to do that then why use JSON at all? Honestly if you are going to process the JSON with Javascript what dont you write your data out as Javascript data structures (which it would be converted from JSON anyway) in the page and process that? What do you gain from embedding the JSON then having to convert it into Javascript data structures over just writing the native Javascript data structures? -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Paul, thanks for the suggestion. I was hoping there is something in Rails to do that for me. But I guess there isn''t. Other suggestion I got, off this list, is to have JSON embedded in a javascript string, and parsed by jQuery into an object. With proper javascript escaping (by j method), that gets the job done. And I like that approach better then calling h on attributes on server side, as this is more generic IMO, since it will work for any Ruby object. Here is the code that works: <% tags = [{name:"tag1", color:"green"}, {name:"</script><b>I can \n\ndo something bad here</b>", color:"red"}] %> <script type="text/javascript" charset="utf-8"> //<![CDATA[ var tags_list = $.parseJSON(''<%=j tags.to_json.html_safe %>''); // ]]> </script> And that results in: <script type="text/javascript" charset="utf-8"> //<![CDATA[ var tags_list $.parseJSON(''[{\"name\":\"tag1\",\"color\":\"green\"},{\"name\":\"<\/script><b>I can \\n\\ndo something bad here<\/b>\",\"color\":\"red\"}]''); // ]]> </script> Thanks all! On Fri, Aug 26, 2011 at 4:43 PM, Peter Hickman < peterhickman386-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote:> The purpose of JSON is to be able to interchange the data between > various systems. As you are not going to do that then why use JSON at > all? > > Honestly if you are going to process the JSON with Javascript what > dont you write your data out as Javascript data structures (which it > would be converted from JSON anyway) in the page and process that? > What do you gain from embedding the JSON then having to convert it > into Javascript data structures over just writing the native > Javascript data structures? > > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to > rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > For more options, visit this group at > http://groups.google.com/group/rubyonrails-talk?hl=en. > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
I''m surprised that Rails doesn''t have a built-in way of doing this! As Paul said, I can''t think of why embedded json would be worse than any other way of transmitting the data, especially for things like backbone apps. As I mentioned on http://stackoverflow.com/questions/7205902/how-to-safely-embed-json-in-html-document/ a workaround is: <script type="text/javascript" charset="utf-8"> //<![CDATA[ var tags_list = <%=raw @tags.to_json.gsub(''/'', ''\/'') %>; // ]]> </script> but that''s kind of ugly. Again, I''m surprised there isn''t a built-in way of passing JSON data to from controller to view like this. Am I missing some obvious reason why? -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.