I've already successfully changed most of the <a> urls to prettier ones (hiding all the millions of /w/index.php?title=foo&.... links into /wiki/Foo?...) through a combination of $wgActionPaths and client side javascript:
jQuery(function ($) {
$('[href*="title="]').attr('href', function (i, value) {
return value.replace(/\/w\/index.php\?title=(.+?)\&(.+?)/, "/wiki/$1?$2")
})
})
(I was too lazy to translate that into PHP)
The only links left are the target urls of
the search form
the history page 'compare selected versions' and 'browse history' forms
How would I make these target nicer cleaner URLs?
A combination of the following LocalSettings.php
$actions = [ 'watch', 'unwatch', 'delete', 'revert', 'rollback', 'protect',
'unprotect', 'markpatrolled', 'render', 'submit', 'purge' ];
foreach ($actions as $action)
$wgActionPaths[$action] = "/wiki/$1?action=$action";
which change the some of the html links
and MediaWiki:Common.js
$('#searchform').attr('action', '/wiki/Special:Search')
$('form').attr('action', function (i, value) {
return value.replace("/w/index.php", "/wiki/" + $('[name="title"]', this).attr('value'))
})
$("[name='title']",$('form')).remove()
to fix the search action, and the special pages forms
the following .htaccess rule can be used to redirect all /w/index.php?...&title=Article&... links to the /wiki/Article?... variant:
# force any /w/index.php urls back to the /wiki/ variant
RewriteCond %{QUERY_STRING} title=([^&]+)
RewriteRule ^/?w/index.php$ /wiki/%1 [QSA,NE,R=302]
unfortunately the myriad forms used at various points cause the query parameters to be percent-encoded in such a way that the .htaccess QSA flag fails and you end up at /wiki/Special%3ARecentChanges for example. This especially fails on subpages where the %2F's that get inserted cause everything to break.
EDIT: the above percent-encoding problem can be fixed by enabling the following RewriteMap in the server settings (doesn't work in .htaccess itself):
RewriteMap unescape int:unescape
and then replacing the %1 in the RewriteRule line with
RewriteRule ^/?w/index.php$ /wiki/${unescape:%1} [QSA,NE,R=302]
EDIT: and to further remove the remaining/repeated title= parameter from the final url, include the following rules (found here):
# remove title query parameter
RewriteCond %{QUERY_STRING} ^(.*)&?title=[^&]+&?(.*)$ [NC]
RewriteRule ^(/?wiki/.+)$ /$1?%1&%2 [NE,R]
Related
I'm using GulpJS and gulp-token-replace to replace variables within an HTML file, such as title and meta tags. It's working great, but I'm stuck with only one configuration file (config-title-meta.json). I want to have an individual configuration file for each folder, so that I might be able to edit "main" variables for all html pages, but customize others, without having to edit each individual page. Am I using the correct tool for this?
gulpfile.js:
var replace = require('gulp-token-replace');
gulp.task('compile-html', function() {
var config = require('./config-title-meta.json');
return gulp.src([
'./**/*.html',
'!header.html', // ignore
'!footer.html' // ignore
])
.pipe(fileinclude({
prefix: '##',
basepath: '#file'
}))
.pipe(replace({global:config}))
.pipe(gulp.dest(Paths.scripts.dest));
});
I am trying to remove the # in the following URL: (www.example.com/#section1). How could I do this using the htaccess file. I am sure this could be done using regular expression, but I am not sure how I would do this.
This is what I have written within the htaccess file RewriteRule ^[#].
Thanks for your help!
Hashes (#) are not send to the server, so you can't manipulate them on the server.
If you really need to remove them, you would have to use JavaScript on each page.
// Wait for the page to load, and call 'removeHash'.
document.addEventListener("DOMContentLoaded", removeHash);
document.addEventListener("Load", removeHash);
function removeHash() {
// If there is no hash, don't do anything.
if (!location.hash) return;
// http://<domain></pathname>?<search><#hash>
// Build an URL for the page, sans the domain and hash
var url = location.pathname;
if (location.search) {
// Include the query string, if any
url += '?' + location.search;
}
// Replace the loaded url with the built url, without reloading the page.
history.replaceState('', document.title, url);
}
I would like to remove the # hash from URLs using Angularjs' $locationProvider.html5Mode(true).
Example: The address bar displays http://localhost/shop instead of http://localhost/#/shop.
Everything works well untill I refresh a page. If i refresh, the following Laravel Route (defined in routes.php) is accesed
Route::resource('shop', 'ShoppingController')
not the AngularJS Route (defined in app.js)
$routeProvider.when('/shop', {
templateUrl: 'templates/shop.html',
controller: 'ShoppingController'
});
My Code:
routes.php (Laravel Routes)
Route::get('/', function() {
return View::make('index');
});
Route::resource('shop', 'ShoppingController');
app.js (AngularJS Routes)
var app = angular.module('shoppingApp',['ngRoute','SharedServices']);
app.config(function($routeProvider, $locationProvider) {
$routeProvider.when('/shop', {
templateUrl: 'templates/shop.html',
controller: 'ShoppingController'
});
$routeProvider.otherwise({ redirectTo: '/' });
$locationProvider.html5Mode(true);
});
My directory structure:
Project
/app
/...
/views
-index.php (single page application file)
-routes.php (Laravel routes)
/public
/...
/js
-angular.js
-app.js
-index.php (Laravel index file)
Tried Solutions:
Rewrite the htaccess file so that all requests are redirected to index.php (the single page application file, from where AngularJS would take over the routing). Problem: In this way the Laravel route (Route::resource('shop', 'ShoppingController'); - necessary for interaction with the database) becomes inaccessible to the AngularJS $http service:
app.js
app.controller("ShoppingController", function($scope, $http) {
$http.get('/shop', { cache: true}).
success(function(data, status) {
$scope.items = data
}).
error(function(data, status) {
console.log('Status: ' + status);
});
});
Question:
How can I solve the routing problem, so that the AngularJS route, not the Laravel Route gets accessed if I refresh localhost/shop?
From what I read, it seems like Laravel is reading the modified route when you refresh the page. In this case, you should make Laravel continue to make the original view even if it would otherwise be a 404 redirect.
Try adding the following somewhere on the Laravel side (Ex. routes.php)
App::missing(function($exception)
{
return View::make('index');
});
Note: You might want to have AngularJS's routing use .otherwise to handle pages that are not found.
A better solution is to redirect this way:
'Redirect::to('/#/' . Request::path())'
When you refresh or go to the URI directly:
'Request::path()': returns the requested URI i.e.
('/shop/categories/electronics');
AngularJS in 'html5Mode' still responds to the '#/' prefix;
If angular detects the prefix when in HTML5 mode it will remove the prefix for you.
Final solution:
App::missing(function($exception) {
return Redirect::to('/#/' . Request::path());
});
If you are using Laravel 5 then go to app/Exception/Handler.php and place the code below:
public function render($request, Exception $e)
{
if($e instanceof NotFoundHttpException)
{
return Redirect::to('/#/' . Request::path());
}
return parent::render($request, $e);
}
If you wana have more than one single page application running in html5mode or just have another use for App::missing inside a Laravel app you migh use a rewrite rule like this:
#Redirect base url of AngularJS app in html5mode
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/path/.+$
RewriteRule ^(path)/(.*) /path/#/$2 [R=301,L,NE]
I have another solution which I found quite useful. Rather than just making home page view, I pass in the URI to the home page, which will get checked by a controller and redirect accordingly (the Angular way). This means that if you are on myapp.com/about and you refresh, instead of taking you home, it takes you back to the page you were currently on.
routes.php: Notice that I have a URI wildcard that I pass in as an argument to the callback function, then as a variable to the view.
// Note that this must be on the bottom of your routes file because
// if you have any registered route with a similar pattern
// it will get caught by this route and never reach any registered routes you might have
Route::get('{slug}', function($slug){
return View::make('index', compact('slug'));
});
// These routes will never get hit, so move them above Route::get('{slug}')
Route::get('about', function(){...});
Route::get('contact', function(){...});
index.blade.php:
<html ng-app"myApp">
<head>
...
</head>
<body>
<!--Check if there is a variable named $slug that is set-->
<!--If it is, set hidden input with ng-model-->
#if(isset($slug))
<input type="hidden" value="{{slug}}" ng-model="slug" ng-controller="RedirectController">
#endif
<div ng-view></div>
</body>
</html>
app.js
angular.module('myApp', [])
.controller('RedirectController', ['$location', '$scope', function ($location, $scope) {
// If slug is set, redirect to that slug
if ($scope.slug) {
$location.path('/' + $scope.slug);
}
}]);
For Laravel 4.x or 5.x i use this simple and nice trick and there is no need to change .htaccess file. this trick is very simple and works for me. it doesn't redirect URL and user will stay on same URL when refresh page and page will refresh:
Route::get('dashboard/{all?}', function(){
return view('main.index');
});
here my dashboard app is my SPA. this way we can resolve 404 errors pages too.
My links are like "http://www.shinylook.ro/product.php?id=58" and I rewrite them like
"http://www.shinylook.ro/produs/58/saboti-dama/"
using this code:
RewriteRule ^produs/([0-9]+)/([a-zA-Z0-9_-]+)\/ product.php?id=$1 [L]
But I cannot manage to redirect the old links to the new ones. If someone will type the old, to be redirected to the new ones.
I tried this one:
RewriteRule ^product.php?id=$1 produs/([0-9]+)/([a-zA-Z0-9_-]+)\/ [L,R=301]
But it doesn't work.
How can I fix this problem?
EDIT:
I managed to write the PHP code... You can try it at www.shinylook.ro/redirect_old_links.php?id=44.
But I can`t manage to solve the htaccess rewrite code to redirect to that file...
I used RewriteRule ^product.php?id=([0-9]+) redirect_old_links.php?id=$1 [R=301,NC]
But it doesn't work.
EDIT 2:
I managed to solve the problem... the htaccess looks like
RewriteCond %{ENV:REDIRECT_STATUS} !=200
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteRule ^product.php$ /redirect_old_links.php/ [L]
RewriteRule ^produs/([0-9]+)/([a-zA-Z0-9_-]+)\/$ product.php?id=$1 [L]
And the PHP code looks like:
<?
include "_storescripts/connect_to_mysql.php";
error_reporting(E_ALL);
ini_set('display_errors', '1');
if (isset($_GET['id'])) {
$produs = $_GET['id'];
$sql = mysql_query("SELECT nume_produs FROM products WHERE id='$produs'"); // Chose the product
// ------- We check if it exists ---------
$existCount = mysql_num_rows($sql); // Count
if ($existCount == 1) {
while($row = mysql_fetch_array($sql)){
$nume_brut = $row["nume_produs"];
$nume = explode(" ", $nume_brut);
}
$nume_final = strtolower($nume[0]."-".$nume[1]);
$name = urlencode($nume_final);
header("location: http://www.shinylook.ro/produs/$produs/$name/", TRUE, 301);
}
else {
echo ("This product id does not exist!");
exit();
}
}
?>
If anyone see some mistakes (I'm new to this domain), I will be very glad to hear them and learn how to do this things better...
You probably want to redirect the old links to the new URL so that people use the new links when pasting them on blogs and such.
When using RewriteRules, Apache cannot guess the rest of the name in order to do the other part of the redirection.
It can remove it:
produs/58/saboti-dama/ -> product.php?id=58
but where would it get the name again in order to do the reverse?
For this, you should write a redirect_old_links.php file, which would just redirect to the new location:
http://php.net/manual/en/function.header.php
Example:
User visits
product.php?id=58
RewriteRule product.php?id=([0-9]+) redirect_old_links.php?id=$1 [L]
In redirect_old_links.php:
mysql_select("SELECT name FROM PRODUCTS WHERE ID = ".$_GET["id"]);
// the above line is just so you get the point,
// please create a proper query with PDO and proper escaping
$id = urlencode($product_id);
$name = urlencode($product_name);
header("Location: produs/$id/$name/");
Sorry, I haven't used PHP in a really long time, and you have to check the documentation for the functions yourself, I don't remember teh mysql_select/fetch procedure. Urlencode may be wrong as well.
But I hope you get the point.
I've been given a lighttpd.conf that someone else wrote and need help working out how to serve it. I'm 90% of the way there but stuck... The index.html page appears, but links and CSS files don't point to the right place.
To clarify, the links and CSS files are all pointing to a 'file:///' URL. So styles.css in the HTML header points to file:///html/styles.css, whereas it should be going to http://example.com/styles.css
Maybe url.rewrite or url.redirect isn't working properly?
server.document-root = "~/html"
server.port = 28001
mimetype.assign = (
".html" => "text/html",
".txt" => "text/plain",
".jpg" => "image/jpeg",
".png" => "image/png"
)
url.rewrite = (
"^(.*)/($|\?.*)" => "$1/index.html",
"^(.*)/([^.?]+)($|\?.*)$" => "$1/$2.html"
)
$HTTP["scheme"] == "http" {
url.redirect = (
"^/platform/index.html$" => "/platform",
"^/about/company.html$" => "/about/company",,
)
}
----- UPDATE ------
file:/// problem now solved, thanks to Marcel. However, http://example.com/about/company still doesn't find anything, whereas http://example.com/about/company.html renders OK. Is there a problem with url.rewrite? I'm using v1.4.20 of lighttpd, so maybe I need to change it to rewrite-once or rewrite-final?
About the original problem: it's not a problem of web server configuration, but of the HTML being served, likely containing the file:// protocol. Use http:// instead.
Regarding the second problem: I'm not an expert in Lighttpd configuration options, but it might help if you exchange those settings in url.redirect and get rid of the trailing commas, like:
url.redirect = (
"^/platform$" => "/platform/index.html",
"^/about/company$" => "/about/company.html"
)
(but I'm not sure). See the documentation for examples.
BTW, is mod_redirect loaded in server.modules?