HTTP redirection without updating document.location - http

We have a service located at a url like services.example.com/123456/*. We'd like to provide that same service at a url like www.example.com. The original service is provided by a PaaS provider which doesn't work with custom domains.
We want a request to go something like this: browser requests www.example.com/path, we tell it to go to services.example.com/123456/path, and it gets the data from there, but treats the response as if it came from www.example.com/path - so doesn't update document.location or the url at the top, and treats links as relative to the original path.
Is this possible, or would we have to have a own proxy-like website?

You need a proxy that do url rewriting.

Related

How to mask url from siteA.com to retreive data from siteB.com/page1.aspx?id=1234 - ( IIS - URLrewrite - ARR)

Let say the situation is
User type "http://siteA.com" without pagename or querystring in the browser's address bar then click "Go"
IIS receives the request and redirect it to "https://siteB.com/page1.aspx?id=1234"
IIS receives the response from "https://siteB.com/page1.aspx?id=1234"
IIS rewrites the url to "http://siteA.com/home" so users will see this url in their address bars.
At this state, any links on "http://siteA.com/home" must have http://siteA.com as domain name in URLs. Users should see the links like below links
http://siteA.com/page2.aspx
http://siteA.com/page3.aspx
page1.aspx, page2.aspx, and page3.aspx are actually hosted on https://siteB.com
How many rewrite rules do I need? How to write those? How to set up ARR? Any working examples would be helpful.
You asked a lot of questions at once, but in summary, you don’t know much about URL rewriting. So I suggest you take a look at the Microsoft documentation: URL Rewrite Module

When to add http(s):// to website address

I'm trying to create a web browser using Cocoa and Swift. I have an NSTextField where the user can enter the website he wants to open and a WebView where the page requested is displayed. So far, to improve the user experience, I'm checking if the website entered by the user starts with http:// and add it if it doesn't. Well, it works for most of the cases but not every time, for example when the user wants to open a local web page or something like about:blank. How can I check if adding http:// is necessary and if I should rather add https:// instead of http://?
You need to be more precise in your categorization of what the user typed in.
Here are some examples and expected reactions:
www.google.com: should be translated into http://www.google.com
ftp://www.foo.com: Should not be modified. Same goes to file:// (local)
Barrack Obama: Should probably run a search engine
about:settings: Should open an internal page
So after you figure out these rules with all their exceptions, you can use a regex to find out what should be done.
As for HTTP vs. HTTPS - if the site supports HTTPS, you'll get a redirect response (307 Internal Redirect, 301 Moved Permanently etc) if you go to the HTTP link. So for example, if you try to navigate to http://www.facebook.com, you'll receive a 307 that will redirect you to https://www.facebook.com. In other words, it's up to the site to tell the browser that it has HTTPS (unless of course you navigated to HTTPS to begin with).
A simple and fairly accurate approach would simply be to look for the presence of a different schema. If the string starts with [SomeText]: before any slashes are encountered, it is likely intended to indicate a different schema such as about:, mailto:, file: or ftp:.
If you do not see a non-http schema, try resolving the URL as an HTTP URL by prepending http://.

Do any CDNs allow rewriting request URI's so that client-side routing plays nicely with browser refreshes?

I have an HTML5 app written in static html/js/css (it's actually written in Dart, but compiles down to javascript). I'm serving the application files via CDN, with the REST api hosted on a separate domain. The app uses client-side routing, so as the user goes about using the app, the url might change to be something like http://www.myapp.com/categories. The problem is, if the user refreshes the page, it results in a 404.
Are there any CDN's that would allow me to create a rule that, if the user requests a page that is a valid client-side route, it would just return the (in my case) client.html page?
More detailed explanation/example
The static files for my web app are stored on S3 and served via Amazon's CloudFront CDN. There is a single HTML file that bootstraps the application, client.html. This is the default file served when visiting the domain root, so if you go to www.mysite.com the browser is actually served www.mysite.com/client.html.
The web app uses client-side routing. Once the app loads and the user starts navigating, the URL is updated. These urls don't actually exist on the CDN. For example, if the user wanted to browse widgets, she would click a button, client-side routing would display the "widgets" view, and the browser's url would update to www.mysite.com/widgets/browse. On the CDN, /widgets/browse doesn't actually exist, so if the user hits the refresh button on the browser, they get a 404.
My question is whether or not any CDNs support looking at the request URI and rewriting it. So, I could see a request for /widgets/browse and rewrite it to /client.html. That way, the application would be served instead of returning a 404.
I realize there are other solutions to this problem, namely placing a server in front of the CDN, but it's less ideal.
I do this using CloudFront, but I use my own server running Apache to accomplish this. I realize you're using a server with Amazon, but since you didn't specify that you're restricted to that, I figured I'd answer with how to accomplish what you're looking to do anyway.
It's pretty simple. Any time you query something that isn't already in the cache on CloudFront, or exists in the Cache but is expired, CloudFront goes back to your web server asking it to serve up the content. At this point, you have total control over the request. I use the mod_rewrite in Apache to capture the request, then determine what content I'm going to serve depending on the request. In fact, there isn't a single file (spare one php script) on my server, yet cloudfront believes there are thousands. Pretty sure url rewriting is standard on most web servers, I can only confirm on lighttp and apache from my own experience though.
More Info
All you're doing here is just telling your server to rewrite incoming requests in order to satisfy them. This would not be considered a proxy or anything of the sort.
The flow of content between your app and your server, with cloudfront in between is like this:
appRequest->cloudFront
if cloudFront has file, return data to user without asking your server
for the file.
If cloudFront DOESN'T have the file (or it has expired), go back to
the origin server and ask it for a new copy to cache.
So basically, what is happening in your situation is this:
A)app->ask cloudfront for url cloud front doesn't have
B)cloudfront
then asks your source server for the file
C)file doesn't exist there,
so the server tells cloudFront to go fly a kite
D)cloudFront comes back empty handed and makes your app 404
E)app crashes and
burns, users run away and use something else.
So, all you're doing with mod_rewrite is telling your server how it can re-interpret certain formatted requests and act accordingly. You could point all .jpg requests to point to singleImage.jpg, then have your app ask for:
www.mydomain.com/image3.jpg
www.mydomain.com/naughtystuff.jpg
Neither of those images even have to exist on your server. Apache would just honor the request by sending back singleImage.jpg. But as far as cloudfront or your app is concerned, those are two different files residing at two different unique places on the server.
Hope this clears it up.
http://httpd.apache.org/docs/current/mod/mod_rewrite.html
I think you are using the URL structure in a wrong way. the path which is defined by forward slashes is supposed to bring you to a specific resource, in your example client.html. However, for routing beyond that point (within that resource) you should make use of the # - as is done in many javascript frameworks. This should tell your router what the state of the resource (your html page or app) is. if there are other resources referenced, e.g. images, then you should provide different paths for them which would go through the CDN.

AngularJS routing hides 404 responses for nonexistent routes

I have noticed that GET requests for nonexistent paths don't return a 404 response. Instead, the client gets a "200 Ok", AngularJS renders the main view, and rewrites the path to /. A request for a nonsense URI is logged as successful in the server logs. If I understand correctly, the problem is that since AngularJS handles routing, the server has to accept a GET request for any URI and always respond by serving the client side of the app ("200 Ok" or "304 Not Modified").
For example, using the project scaffolded by the angular-fullstack Yeoman generator, requesting a nonexistent /unicorn goes like this:
GET /unicorn 200 31ms - 3.29kb
GET /partials/main 304 36ms
GET /api/awesomeThings 304 5ms
The Express route that handles the request looks like this:
// server, last route:
app.get('*', controllers.index);
// controllers:
exports.index = function(req, res) {
res.render('index');
};
and index.jade is the root of the whole client side of the app.
After a quick look at the server side code of other AngularJS / Express projects on Github (AngularJS Express seed, AngularJS login), I see that this is a common pattern. I am wondering if there is a better way to handle requests for nonexistent paths, so that the client gets a real HTTP 404 response?
The angular documentation has a section about the routing. Also, this question and this question have some information that pertains to IIS but could easily be adapted to express.
Html link rewriting
When you use HTML5 history API mode, you will need different links in different browsers, but all you have to do is specify regular URL links, such as: link
When a user clicks on this link,
In a legacy browser, the URL changes to /index.html#!/some?foo=bar
In a modern browser, the URL changes to /some?foo=bar
In cases like the following, links are not rewritten; instead, the browser will perform a full page reload to the original link.
Links that contain target element
Example: link
Absolute links that go to a different domain
Example: link
Links starting with '/' that lead to a different base path when base is defined
Example: link
When running Angular in the root of a domain, along side perhaps a normal application in the same directory, the "otherwise" route handler will try to handle all the URLs, including ones that map to static files.
To prevent this, you can set your base href for the app to <base href="."> and then prefix links to URLs that should be handled with .. Now, links to locations, which are not to be routed by Angular, are not prefixed with . and will not be intercepted by the otherwise rule in your $routeProvider.
Server side
Using this mode requires URL rewriting on server side, basically you have to rewrite all your links to entry point of your application (e.g. index.html)
You can use $route.otherwise() function
In order to decide what to do with undefined
Routes.
If you want to still show a 404 message,
You could simply set a /404.html route both in this Function and in express.
This is actually express handling routing--not angular. Remove the app.get('*', ... that you found to disable that.

Alternative to Response.Redirect to effect a subdomain

I have a site that is hosted in shared hosting environment. They use a wildcard subdomain setup and suggest using Response.Redirect to achieve the illusion of a subdomain.
Is there a way of doing this such that the "switch" takes place on the server rather than bouncing back down to the browser first?
Server.Transfer only works if I transfer to an actual resource. So redirecting from sub1.mydomain.com to www.mydomain.com/public/ does not work. I'd have to redirect to www.mydomain.com/public/mypage.aspx instead which i dont want to do.
To ensure that the "switch" takes place on the server, you could create a simple HTTP Module to intercept each request, inspect the requested URL and then forward them as needed . All your module has to do is handle the OnBeginRequest event, and then forward the request. In this way you could really have unlimited sub-domains.
Also might want add a blank host header, so that any requests for subdomains not listed get forwarded to the proper default website
If you aren't familiar with them, modules are very simple to create and work with.
Heres a link to a very similar implementation by Brendan Tompkins:
http://codebetter.com/blogs/brendan.tompkins/archive/2006/06/27/146875.aspx
You could also do some URL rewriting in the module should you need specific URL "look" behavior.

Resources