I want to make a single page website, that uses history.pushstate to change the url.
I can make my site have only one html file, the 404 page. so that no matter what url people enter, they get to that page.
My question is: Is there a drawback to abusing 404 pages in that way?
Does google care?
Are there browser quirks?
A better solution is to just have all URLs other than / answer with a permanent redirect to /. You should in any case never actually return the 404 status code because at least some versions of IE will display its own error page instead of whatever HTML you send back.
Related
I have recently moved from localhost to my live website. I have a simple PHP login page. After the users details are checked with my mysql table and if the username exist and they provide a valid password for that username they are redirected to the home page. I was using the header function built in to PHP but this seems to be no longer working now that I am on my live website.
After further research it seems that I cannot use header tags after the page loads. So I am not echo'ing out script tags to window.location redirect to my homepage. The problem with this is that when the new location is being redirected to it appears to look like an additional web pages is loading in before my actual webpage that I'm wanting to go to loads in (This is probably due to the fact that I have extra error handling code that is running after the fact). Does anyone else experience this when using this method? Is there a better way to handle this?
This is what I'm using currently just in case there is any confusion
echo '<script>window.location.href = "home.php";</script>';
I was using the header function built in to PHP but this seems to be
no longer working now that I am on my live website.
Headers must be the very first thing that your script outputs or they won't work. PHP has a convenience feature called output buffering which temporarily holds back the output until the script is done. This allows you to put calls to header() anywhere in your code, and then PHP will automatically take care of moving headers to the front of the output for you. Thus, if you have output buffering enabled, you can put headers anywhere and it will still work. If you do not have output buffering enabled, you must put headers at the very start.
I will wager that you are generating output before the headers, and your local PHP install has output buffering enabled, while your remote host does not. You can fix this in one of two ways:
Update your code to ensure that nothing is output before calls to header().
Enable output buffering on your host by setting output_buffering = 1 in your php.ini.
I recently learnt you can do this with a meta tag:
<meta http-equiv="refresh" content="2;url=http://example.com/" />
In real trouble here. Our old website featured a gallery slider that used URL #fragments to position a jQuery slider on the right project.
For instance, /work/interactive#777 brought you to the /work/interactive page--which shows one project at a time in a slider--and then animates the slider to project with the ID of 777
We are about ready to launch a new website with the same projects, but the projects are now fully qualified and independent pages, so the previous project on the new website is at /work/777
The big issue is we need to serve 301 redirects for the following:
From: /work/interactive To: /our-work
AND if there is a hash, somehow capture it before its lost, so after the redirect we can use Javascript to act on the #ID of the project.
I seem to only be able to do one or the other: 301 redirect the root page w/o the #fragments (which prevents me from then checking the #fragment), OR use a global javascript to check the URL and #fragment and use window.location to redirect to the individual project page on the new site (which prevents me from any 301 redirects).
Any ideas on how to preserve the #fragment? Is there a way to conditionally perform a 301 if and only if the request URL does NOT have a #fragment?
This is not possible since the browser does not pass the fragment part to the server meanwhile only the server can do 301 redirects.
I'd suggest you to keep the current website URL for this specific case if you need to keep old hyperlinks working.
This is possible (now). However there may still be some older browsers that do not follow the specification: https://www.rfc-editor.org/rfc/rfc7231#section-7.1.2
The solution:
First, set up a server 301 redirect so that all requests to /work/interactive will be sent to /our-work.
Second, put the following JavaScript code at the top of the HTML page at /our-work. The code will look at the fragment by using window.location.hash, and if not empty, will redirect to /our-work/xxx based upon the fragment found. I'm using the replace function instead of assign so that the browser history does not remember the initial request with a fragment. And since window.location.hash will start with #, I use substring(1) to remove the first character.
<script>
if (window.location.hash !== "") {
window.location.replace(window.location.pathname + "/" + window.location.hash.substring(1));
}
</script>
This should work even if /our-work is a valid page (e.g. a listing page for all products). Anyone requesting the product listing page without a fragment would not be redirected. A product listing page would also allow search engines to quickly find and re-index the content in its new location.
Expected behaviour:
A request for /work/interactive#777 should initially be redirected by the server (e.g. 301), and a compliant browser would initially request /our-work#777. The server would reply with the HTML/JS code block (and preferably also other fallback HTML content). Depending on performance, the user may briefly see some of the other HTML content before the JavaScript is executed. Then the browser will be redirected to /our-work/777 and the intended HTML page loaded.
Alternatively, a request for /work/interactive (i.e. no fragment) should be redirected by the server, and the browser would then request /our-work. The server would reply with the HTML/JS code block and preferably also other fallback HTML content. Since there is no fragment, the HTML/JS code block should do nothing. The user would only see the fallback HTML content (e.g. a product listing page).
Assumptions:
Every possible fragment has a valid page at /our-work/xxxx. For the code example above, we redirect regardless of what the fragment contains. If you'd prefer to redirect only some fragments, you could use a more specific test, e.g.: if (/^[#]([0-9]{3}$)/.test(window.location.hash)) { ... }. This would only redirect for strictly 3-digit numeric fragments. Or adjust the regular expression to your circumstances.
Your new page doesn't have content that warrants its own fragments. If your new page should handle its own fragments (e.g. /our-work#intro, /our-work#portfolio, etc.), then you'll need to use a more specific test to only selectively redirect (see previous assumption).
The fragments don't encode additional information. You could do further processing before redirecting if the fragments contain more complex data. For example, you could parse requests like: /work/interactive#777-description, or /work/interactive#777-author, and then redirect to /our-work/777#description or /our-work/777#author.
Further explanation:
If a client (e.g. browser) wishes to load http://www.example.com/old.html#fragment, it would typically first make a request for /old.html from the server at www.example.com. If that resource is available at that location, then once received, the client would look for the fragment and adjust (e.g. scroll viewport) if the fragment is found.
However, when the server indicates that the resource has moved by sending a HTTP response of 301, 302, etc. and a new Location (e.g. /new.html), then the client should first make a new request to /new.html, and then once received, should still process the fragment and adjust. This implies that after redirecting, the browser address bar should show http://www.example.com/new.html#fragment.
Historically, not all browsers have correctly kept the fragment after redirection.
Also note that according to the specification, a browser should give precedence to any fragment specified in the HTTP response Location (e.g. Location: /new.html#newfragment). And if no fragment is specified in the Location, then it should retain any fragment originally requested.
I just removed # tag from my url of angular single page app.
I did like.
$locationProvider.html5Mode(true);
And It worked fine.
My problem is when I directly enter any url to the browser it showing a 404 error. And its working fine when I traverse throughout the app through links.
Eg: www.example.com/search
www.example.com/search_result
www.example.com/project_detail?pid=19
All these url's are working fine. But when I directly enter any of the above url's into my browser it showing a 404 error.
Please any thoughts on it.
Thanks in advance.
Well i had a similar problem. The server side implementation included Spring in my case.
Routing on client side ensures that all the url changes are resolved on the client side. However, When you directly enter any such url in the browser, the browser actually goes to the server for retrieving a web page corresponding to the url.
Now in your case, since these are VIRTUAL urls, that are meaningful on the client side, the server throws 404.
You can capture page not found exception at your server side
implementation, and redirect to the default page [route] in your app.
In Spring, we do have handlers for page not found exceptions, so i
guess they'll be available for your server side implementation too.
When using the History API you are saying:
"Here is a new URL. The other JavaScript I have just run has transformed the page into the page you would have got by visiting that URL."
This requires that you write server side code that will build the page in that state for the other URLs. This isn't a trivial thing to do and will usually require a significant amount of work.
However, in exchange for that work you get robustness and performance. When one of those URLs is visited it will:
work even if the JS fails for any reason (such as a dropped network connection or a client (such as a search engine) that doesn't support JS)
load faster than loading the homepage and then transforming it with JS
You need to use rewrite rules. Angular is an single page app, so all your request should go to the same file(index.html). You could do this by creating an .htaccess.
Assuming your main page is index.html.
Something like this (not tested):
RewriteRule ^(.)*$ / [L,QSA]
L flag means that if the rule matches, don't execute the next RewriteRule.
QSA means that the URL query parameters are also passed with the rewrited url.
More info about htaccess: http://httpd.apache.org/docs/2.2/howto/htaccess.html
Instead of using hash URLs for my SinglePageApplication I would like to use the HTML5 Browser History API. This works fine so far (I'm using emberjs).
The pro of the hash URL is, I can refresh the page without worrying about the result. When I try to reload with the browser history API I'll get a 404 (since my server don't have a route for this).
So: Is there a common workaround to avoid this behaviour?
I could tell my server to redirect to the index page but this wouldn't show me the correct content.
Example:
GET host/#images
... shows the "images" page (even when it is the index.html)
GET host/images
... redirect to host/
... shows me the content of the index template
Is https://stackoverflow.com/a/17288940/1423583 an answer to your question? Basically it says that you have to change the server to always serve the index.html page.
A small website I was creating (more like fiddling) uses AJAX to load each page. Previously I was changing the hash of the url, this worked great but was ugly, and the user could refresh the page, and it would stay on the same page.
Now I have switched to using pushState in the JS History API, which looks much better, and the back and forward work, but refreshing does not. For example:
Going to: http://example.com/page2 goes to a 404 as there is no real page called page 2. But if I click on the button which uses the pushState method to change the url, it works as it should.
How can allow refreshes, and permalinks with the new History API?
(And how do search engines treat this, seeing as Google had to create a way of indexing hash urls, by making the developer switch to #!, is it possible they will do something similar for the history api in the future?)
You shouldn't use pushState to push invalid URLs at all. It's meant to be used in cases where the site works both with and without AJAX - i.e. you push the URL which would result in the same output without AJAX when creating this output with AJAX.
If you want only virtual URLs (like in the pre-pushState era), keep using the hash tag.
This is a somewhat old question, but it was one of the top google results. In the pursuit of being helpful, here is my solution.
You can use Apache's Mod_Rewrite to rewrite the url to a central location.
For example:
example.com/p2 gets its page content from example.com/index.php?page=p2
You can keep your current implementation of the History API and AJAX to get the content and include the following in your .htaccess
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^([^/\.]+)/?$ index.php?page=$1&full=1 [L]
</ifModule>
In your index.php:
<?php
if(isset($_GET['full']) {
//Generate the full page here
}else{
//Generate just the content for AJAX
}
?>
This Page is a good primer on using mod_rewrite to redirect an entire website. (Comments 11 & 13 have useful additions as well)
I had to redirect 404 errors to the sites homepage (the one that loads the AJAX requests), and then get the last component of the URL, and run the javascript function that loads the page using an AJAX request. Not a great solution but it seems to work well.