Detect iframe request in a rails app - ruby-on-rails

I have a iFrame tool, which should get rendered in a other format than my page. So I want to detect requests from iFrame like I can detect them from a iPhone. Is this possible?
Is there a special hint in the request header, that I could use, or could I manually enter one?
Thanks
Markus

When you get a request from an iPhone there will be send a "User Agent"-String like Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 in the request.user_agent variable. Searching this string for iPhone can tell you that an iPhone is visiting your page.
An iframe is an HTML tag to include other pages within your page (eg. the Facebook like button uses this). This does not have to to anything with a specific browser, all modern browsers support this. You cannot tell on server side whether your page was called within an iframe or not. You can use some JavaScript in the client to find out if your current page is within an iframe and then send a notice to the server.
Best practice would be to add another paramter to your request like ?iframe=1 and use this param within your controller.

A good practice is to add a subdomain for your embeds. Then you can fire requests to the subdomain and evaluate request.host. This also allows for a separation of logic in controllers/views when using multiple subdomains.
Example:
iFrame
<iframe src="embed-subdomain.domain.com" /> instead of <iframe src="domain.com" />
Controller
iframe = request.host.include?("embed-subdomain.domain")
Disclaimer: This can get tricky if you utilize sessions and CNAMEs

Related

PathLocationStrategy vs HashLocationStrategy in web apps

What are the pros and cons of using:
PathLocationStrategy - the default "HTML 5 pushState" style.
HashLocationStrategy - the "hash URL" style.
for instance, using HashLocationStrategy will prevent the feature of scrolling to an element by its #ID, but some 3rd party plugins require the HashLocationStrategy or the Hashbang #! in order to work in ajax websites.
I would like to know which one offers more for a webapp.
For me the main difference is that the PathLocationStrategy requires a configuration on the server side to all the paths configured in #RouteConfig to be redirected to the main HTML page of your Angular2 application. Otherwise you will have some 404 errors when trying to reload your application in the browser or try to access it using a particular URL.
Here is a question that could give you some hints about this:
When I refresh my website I get a 404. This is with Angular2 and firebase.
Hope it helps you,
Thierry
# can only be processed on the client, the servers just ignore them. This can cause problems with search engines (SEO), redirects can cause redundant page reloads.
This page https://github.com/browserstate/history.js/wiki/Intelligent-State-Handling has some detailed explanation, while some of the arguments don't apply for Angular applications (for example - doesn't work with JS disabled).
The "disadvantage" of HTML5 pushstate is that is requires server support like explained by Thierry.
According to official docs:
When the router navigates to a new component view, it updates the browser's location and history with a URL for that view. This is a strictly local URL. The browser shouldn't send this URL to the server and should not reload the page.
PathLocationStrategy
Modern HTML5 browsers support history.pushState, a technique that changes a browser's location and history without triggering a server page request. The router can compose a "natural" URL that is indistinguishable from one that would otherwise require a page load.
Here's the HTML5 pushState style URL that routes to the xyz component: localhost:4200/xyz/
HashLocationStrategy
Older browsers send page requests to the server when the location URL changes unless the change occurs after a # (called the hash). Routers can take advantage of this exception by composing in-application route URLs with hashes.
Here's a hash style URL that routes to the xyz component: localhost:4200/src/#/xyz/
I would like to know which one offers more for a webapp.
Almost all Angular projects should use the default HTML5 style as:
It produces URLs that are easier for users to understand.
It preserves the option to do server-side rendering later.
Rendering critical pages on the server is a technique that can greatly improve perceived responsiveness when the app first loads. An app that would otherwise take ten or more seconds to start could be rendered on the server and delivered to the user's device in less than a second.
This option is only available if application URLs look like normal web URLs without hashes (#) in the middle.
Stick with the default unless you have a compelling reason to resort to hash routes.

Get iOS Device Default System User-Agent For HTTP Requests

I'm communicating with an API that requires I use a particular user-agent string. The format for this is basically User-Agent: IOS_USER_AGENT API_CUSTOM_AGENT
Upon investigation I discovered that people would use UIWebView and apply a javascript function to extract the system user agent string. Now that UIWebView is deprecated, its replacement WKWebView offers an asynchronous means of calculating the user agent (not ideal for my purposes).
Is there any way to extract some form of the iOS user agent string without needing to randomly create some off-screen web view. Especially with SFSafariViewController I don't think its entirely impossible that these web views become deprecated in future.
I know that Apps like WhatsApp and Facebook use the system User-Agent see here. The question is, what is the most reliable way of achieving this without involving web view trickery?

Is my web service being used by an application/bot?

I have a web application that makes file conversion. I've checked usage statistics today and I realized 20-30 files uploaded and converted every second from the same ip. I checked the browser's header info (I wrote every request's http header info to my database) and found this:
Mozilla/5.0 (iPad; CPU OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko)
I think someone is using my web service in an iOS application for converting files. How can I know which application is this or how can I stop this?
If it's your own form, you may use a captcha but this may create problems if you or any of your allowed customers want to use it by using a an application instead of using web view. (I'm not sure if you have such a case). My basic solution would be adding basic authentication to the page on web server level (IIS, etc...)...

Is The Request Coming From An iframe?

I have an asp.net mvc website that returns a JSON result to certain pages on the website. I would like to be able to also return results to iframes being hosted on other websites. However, if the request is coming from an iframe on another website (I mean from an iframe being hosted on another domain), I would like to be able to detect this in the action of the controller and adjust the results accordingly. Is it possible to know in the action that the request is coming from another domain (or from an iframe, either way)?
Many thanks in advance! I don't have much experience working across domains...
Is it possible to know in the action that the request is coming from another domain
From another domain yes => simply inspect the Request.Url property. From an iframe, no, you can't. There's nothing defined in the HTTP protocol which enforces requests coming from an iframe to be anyhow different than normal requests.
Request.UrlReferrer has browser specific issue, It will probably not work for IE versions less than 9. So might want to consider that as well.

Detect screen size and pixel density on the server-side?

I've been doing some research and I think I know the answer already, but I'm wondering if there's any means by which you can get a device's screen size and pixel density without the use of javascript or relying on CSS3 media queries.
Essentially, I'm looking into what it would take to get the screen resolution and pixel density so that the server could decide which image to server in a URI request.
So far I've not found anything that says this is even possible but I thought hey, why not ask?
I don't agree entirely with the above correct answer. Realistically this answer is correct in many cases...but theoretically it is not. Often requests made to a web server contain a User-Agent field which could, in theory, be used to discern information about device screen resolutions and properties.
Web requests do not pass through the client first. They pass to the server, which then serves a page to the client so the server gets the request first...Ruby on Rails, for example, receives a request through an action controller to a resource and then serves a page to the response.
Look at an example UA parser such as : https://github.com/visionmedia/user-agent
A sample user agent being sent by my computer is:
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.11 (KHTML, like enter code here`Gecko) Chrome/17.0.963.83 Safari/535.11
I think it is eminently possible to make a good guess what my screen resolution (DPI etc) is given that information via a server. You would, of course, need a table of device information to reference.
For mobile devices it gets even easier. If the User-Agent is a mobile safari for iPad:
Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B314 Safari/531.21.10
You can know with strong certainty what the screen resolution is on the server. You can even know the height and width of the browser with that info. I suspect the same is true with many mobile devices such as Android or Win Mo.
So in summation, I agree its impractical to do this but I also disagree.
I believe Facebook has undertaken a major project cataloging devices and screen resolutions and made it open source because they faced similar issues when creating the facebook mobile app e.g. they had to catalog all the discrepancies between all mobile browser renderers so they could tailor the client app to every individual case. Perhaps that project might have the necessary information to do this...in theory.
Ruby runs on the server side--without getting info from the client, it has no way of knowing any client capabilities.
For something that's impossible it looks like Mobvious does a decent job:
Mobvious detects whether your app / website is being accessed by a
phone, or by a tablet, or by a personal computer. You can then use
this information throughout your app. (E.g. fork your front-end code
with regard to device type. There is a plugin for Ruby on Rails that
helps you with this.)
https://github.com/jistr/mobvious
I had the same problem and solved it using a getter and a setter route for the window height. If the $height variabale is 0 the get_heigt.erb is served, otherwise the index.erb
This is a one user app, so I use a global variable, with different users you would have to keep that info in cookies.
Here the code that matters.
Controller:
get "/" do
if $height == 0
erb :get_height
else
erb :index
end
end
get "/get_height" do
erb :get_height
end
get "/set_height" do
$height = params[:height]
redirect "/"
end
get_height.erb
<script type="text/javascript">
function send_message(message) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
document.location.reload(true);
}
xhttp.open("GET", "http://localhost:4567/" + message + "?height=" + window.innerHeight, true);
xhttp.send();
}
send_message('set_height');
</script>
You could use Ahoy. The current_visit method contains the following information.
When someone visits your website, Ahoy creates a visit with lots of
useful information.
traffic source - referrer, referring domain, landing page, search
keyword location - country, region, and city technology - browser, OS,
and device type
utm parameters - source, medium, term, content,
campaign
Not sure how realistic would be to build but you could build a database which maps specific device types you can get from user agent in server-side into know screen sizes. It still would not allow things like window size.

Resources