Rails streaming: "render stream: true" not working - ruby-on-rails

I recently discovered rails streaming, and having read the various documentation, I tried to add it to one of my controllers like so:
def index
render :stream => true
end
My template file currently looks like this:
<%10.times do%>
<p>
I should get streamed ERB...
<%sleep 0.5%>
</p>
<%end%>
But instead of displaying a message every 0.5 seconds, it waits 5 seconds and displays the whole page! I have checked this behavior in a browser and using curl.
I am using unicorn on OSX, and yes, I configured unicorn.rb for streaming:
listen 3000, :tcp_nodelay => true, :tcp_nopush => false
worker_processes 1
If you want to see my layout file, it looks like this:
<!DOCTYPE html>
<html>
<head>
<title>StreamingTest</title>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
I tried disabling all gems (except rails and postgres), and I pared my controller, layout, and template down to the bare minimum, without any success.
I even went so far as to download a complete streaming demo I found (https://github.com/slim-template/slim-streamingtest), and when I ran that, it didn't stream either! (Note to anybody trying to run that demo: I had to change the gemfile source to use https instead of http before I could "bundle install", and I had to "bundle update sprockets" before it would run)
I note that somebody else (using Puma) appears to have a similar problem, which has not been successfully resolved:
Rails Streaming not Streaming
It may be that whatever works for me will also work for them.
Streaming would really help our app, if I could just get it to work, but I can't even get demo streaming apps to run correctly! I suspect it might have something to do with my dev environment, but the problem remains when I deploy my app to Heroku, and I'm out of ideas. Any help would be greatly appreciated . . .
Thanks!

I tried the demo repo you mentioned and the behaviour is as expected. In the example you show it will stop streaming the template, then wait for it to be fully rendered after 5 sec and send the rest. If you use curl:
# curl -i http://localhost:3000
HTTP/1.1 200 OK
Date: Thu, 21 Apr 2016 17:29:00 GMT
Connection: close
Cache-Control: no-cache
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
X-UA-Compatible: IE=Edge
X-Runtime: 0.018132
<!DOCTYPE html>
<html>
<head>
<title>StreamingTest</title>
<link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
<script src="/javascripts/application.js" type="text/javascript"></script>
<meta content="authenticity_token" name="csrf-param" />
Then it waits for 5 seconds for the template to finish its rendering and then sends it.
...
<p>
I should get streamed...
</p>
</body></html>
That's what's supposed to happen. It will not send a part of the partial every 0,5 seconds.
The main goal of streaming with templates is for the browser to receive the headers before the rest of the content so that it makes it possible to save some time in loading assets. As stated in the docs.
Streaming inverts the rendering flow by rendering the layout first and streaming each part of the layout as they are processed. This allows the header of the HTML (which is usually in the layout) to be streamed back to client very quickly, allowing JavaScripts and stylesheets to be loaded earlier than usual.
It's not going to send the partial unless it's been fully rendered.
However, to show you how to get the kind of behaviour you're expecting you could change the body of application.html.slim layout like this:
body
= yield
= render 'application/other'
And create a partial named _other.html.erb with the following content
<% sleep 1 %>
<p>Me too!</p>
And now you'll see in curl that it renders the beginning of the layout, waits for the rendering to be finished on index.html.erb, sends it and shows up in curl and then waits for the _other.html.erb partial to be finished rendering to end the request body. Voilà.
You could also directly feed the request body, to send content every few milliseconds, you can do the following:
def index
headers['Cache-Control'] = 'no-cache'
self.response_body = Enumerator.new do |yielder|
10.times do
yielder << "I should be streamed...\n"
sleep 0.3
end
end
end
This is however not meant to send html, although you could by using render_to_string but then you'll have to modify quite a lot in your code.
Note that all this is Rails 3.x, for 4.x you'll have to use ActionController::Live. In the case of ActionController::Live, there are examples on how to listen to the server sent events in js to render client side such as this mini-chat.

Related

how to use iframe in vscode webview

in vscode-extension webview(catcoding), i want load external webpage(like google,..),
i tried
panel.webview.html ="<html>
<meta http-equiv="refresh" content="0; url=http://www.google.com/"></meta>
</html>"
You can try to use iframe inside the webview. Just include this into the <body> element of the catcoding example:
<iframe src="http://dlabacov.cz" width="100%" height="400px">
</iframe>
Now, not sure if it important for you to render exactly google.com website, because that particular website (and many others) refuses to render in an iframe. This is why I used a website of my local cinema, which does not have such restrictions and I use it for such tests. So if you want to display a website that is under your control, perhaps you can setup the policies to allow it to be rendered in an iframe.
Google has the X-Frame-Options: response header set to SAMEORIGIN (X-Frame-Options: SAMEORIGIN) which notifies browsers if they are allowed to render the requested page inside <frame>, <iframe>, <embed> or <object> HTML elements, that are not hosted on the same domain.
Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
But this can be bypassed/overridden by appending webhp?igu=1 to the end of the website URL. Like so, https://www.google.com/webhp?igu=1
Then you can use the iframe like this:
<iframe width="100%" height=650px" src="https://www.google.com/webhp?igu=1" title="Google">
</iframe>
The drawback will be that this may not work for every website, in that case you can check if the website you require works with iframes by checking for the header response on https://www.google.com & https://www.google.com/webhp?igu=1 with latter one not including any x-frame-options:

Adding new divs (blocks of content) inside OneNote page using the Microsoft Graph API

I am using the Microsoft Graph API to programmatically add content to a OneNote Page on my Office365 OneNote Notebook. For an example page like this:
OneNote snip consisting of Title & 2 separate divs/blocks, this is the generated HTML that I get by making a GET to the pages/{myPageID}/content?includeids=true endpoint
<html lang="en-US">
<head>
<title>Thursday, December 6, 2018</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="created" content="2018-12-06T19:55:00.0000000" />
</head>
<body data-absolute-enabled="true" style="font-family:Calibri;font-size:11pt">
<div id="div:{95790d05-168a-4f61-81a7-5c13e3124069}{4}" style="position:absolute;left:48px;top:115px;width:624px">
<p id="p:{95790d05-168a-4f61-81a7-5c13e3124069}{10}" style="margin-top:0pt;margin-bottom:0pt">It is a jolly good day</p>
</div>
<div id="div:{3a6b78e9-2af8-4a5b-abf8-09871fb6eec5}{20}" style="position:absolute;left:44px;top:180px;width:624px">
<p id="p:{3a6b78e9-2af8-4a5b-abf8-09871fb6eec5}{24}" style="margin-top:0pt;margin-bottom:0pt">Lets do this shall we</p>
</div>
</body>
</html>
I now try adding a new div/block by making the following PATCH using the requests library in Python. The myPageID and access_token are collected previously by making GET requests to the graph API:
patchPageURL='https://graph.microsoft.com/v1.0/users/'+userID+'/onenote/pages/'+myPageID+'/content?includeIDs=true'
patchPageHeaders={
'Content-Type':'application/json',
'Authorization':'Bearer '+access_token
}
patchPageBody=[{
'target':'div:{3a6b78e9-2af8-4a5b-abf8-09871fb6eec5}{20}',
'action':'insert',
'position':'after',
'content':'<div><p> And God said let there be new blocks </p></div>'
}]
patchResp = requests.patch(patchPageURL, headers=patchPageHeaders, json=patchPageBody)
However, I end up with a 400 error as a response to my PATCH request with the following code and message:
code: 20135
message: The entity type is not supported for this operation.
If I change the opening div tag for the content to something like <div data-id="new-div">, I still receive the same 400 error, code 20135.
I am following the instructions from this documentation here. What subtlety is being missed here? There are no authentication or other similar errors. The PATCH works fine if I change the target to body and the action to append but that doesn't make a new div/block and only adds the content as a child of the first div in the page.
Is there a straightforward way to add new blocks/divs as a sibling of existing blocks or even just something as simple as adding a new block at the end of the OneNote page?

Differentiate between IE compatibility view

If a user is on IE 7 and I read
<% = Request.Browser.Version %>
I get 7.0
if they have IE 9 and are on compatibility view, I get the same thing.
Is there anything in Request.Browser that can differentiate between a real IE7 user and a user that is using IE8 or IE9 but in compatibility mode?
It would be better to do this on the client side using JavaScript. You can use something like this:
http://code.google.com/p/ie6-upgrade-warning/
You can tweak it to whatever you want.
If your goal is simply to make sure the user is not in compatibility mode, then you can use either the meta tag or http header version of X-UA-COMPATIBLE:
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" >
</head>
<body>
<p>Content goes here.</p>
</body>
</html>

classic ASP with non-english languages special characters as boxes

I am currently working on Classic ASP for one of my project. For non English languages I am getting boxes instead of special characters. I am rendering using UTF-8 but sometimes the characters goes to boxes. It comes back normal when I click refresh sometimes.
I followed all the steps below but i still get this problem
XML:
<xml version="1.0" encoding="UTF-8">
HTML:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
content-type: text/html; charset=utf-8
Am I missing anything here? Thanks.
Add this to your page:
Response.CodePage = 65001
Response.CharSet = "utf-8"
It should display all correctly now.
Hope that helps
It's amazing BUT nobody gives a complete answer on what to do this PROPERLY... I hope this help somebody like me, because it was so hard to find the whole picture...
---------------- PREVIOUS CONSIDERATIONS --------------
FIRST, make sure IIS IS NOT replacing the Code Page... Go to IIS, click the Website, open ASP module, on Behavior it should be >> Code Page = 0
SECOND, The file itself should be checked, YES! the file... open your file explorer on windows (my computer), go to the folder where the files of your website are, take for example "default.asp", right click >> open with >> notepad THEN click on File >> Save As... IN THE DIALOG at the bottom says "Encoding", make sure it has UTF-8, otherwise you will have to add the
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> in every page (including server side includes), which is not correct.
---------------- CORRECT STRUCTURE OF THE PAGE --------------
<%#LANGUAGE="VBSCRIPT" CODEPAGE="65001"%><%
Response.AddHeader "Content-Type", "text/html;charset=utf-8"
%><!-- #include virtual="/conexion.asp" -->
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
</head>
<body>
áéíóú
</body>
</html>
It should work fine now with QueryStrings, Database and regular HTML... uffff

Strange extra characters in rendered html on IE 8

I have an ASP.Net MVC site that I want to render some custom HTML 5 canvasses in. I am getting a strange issue with the server serving up extra characters that are not in the source code.
In order to use an HTML 5 canvas in IE 8 you have to add the following tag in the html head:
<!--[if IE]><script src="../../Scripts/excanvas.js"></script><![endif]-->
For some reason this is served up as:
<!--[if IE]>IE]><script src="../../Scripts/excanvas.js"></scr<![endif]-->
Of course the duff markup causes the excanvas script to not be loaded by IE. I can't understand why the line gets garbled. I have the following doctype which is documented at http://www.w3schools.com/html5/tag_doctype.asp:
<!DOCTYPE html>
I'm not familiar with using HTML 5 or the new doctype so I'm suspicious of it. I'm also hosting on Apache with Mono so maybe that's what's garbling the line.
The page in question is at: http://openancestry.org/FamilyTree/Simpsons
Anyone seen this before or know why I cant use the "if IE" syntax?
UPDATE:
Well I'm pretty sure it's either Mono or Apache thats garbling the HTML so I've used the workaround below which adds a compatibility meta tag for IE8 and includes excanvas for any IE that predates IE9.
I'd still appreciate any answers on why the HTML gets garbled.
<% if (Request.Browser.Browser.Contains("IE") && float.Parse(Request.Browser.Version) < 9) { %>
<% if (float.Parse(Request.Browser.Version) > 7) { %>
<meta http-equiv="X-UA-Compatible" content="IE=7" />
<% } %>
<script type="text/javascript" src="../../Scripts/excanvas.js"></script>
<% } %>
Before I answer, I want to point out that you are missing type="text/javascript" in your example.
It is possible that the ASP.NET parser in Mono is mangling your comment. What version of Mono are you using (and what platform I suppose).
I just tried this on Mono 2.10 on Mac and did not have this problem.

Resources