Dealing with images when custom routing to remove a /stub directory

Ok, so I was trying to find a way to do custom routes so some posts could subdirectories of /content/writing but not show /writing in the URLs.

The Kirby docs about routing explain part of this, but not exactly how to handle the images in those content directories.

After a couple of hours, here’s what I came up with. It seems to work, but I’d love feedback and am also posting this in case it helps other people.

The structure of the content looks something like this:

– content
– -- writing
– -- – writing.txt
– -- – writing1.png
– -- – writing2.png
– -- – post1
– -- – -- post1-1.jpg
– -- – -- post1-2.jpg
– -- – -- post.txt
– -- – post2
– -- – -- post2-1.jpg
– -- – -- post2-2.jpg
– -- – -- post.txt
– -- some-other-page
– -- – page.txt
– -- – image.svg
– -- error
– -- – error.txt
– -- – error-image.gif

Test URLs:

  • /error/image1.jpg
  • /writing
  • /writing/post2
  • /writing/writing1.png
  • /post1
  • /post1/post1-1.jpg
  • /post2
  • /post2/post2-2.jpg
  • /some-other-page
  • /some-other-page/image.svg

Routes in config.php

/*

---------------------------------------
Custom Routing 
to hide /writing from URLs, while keeping /content tidy
note: Our assumed stub directory is /writing/ 
cf. http://getkirby.com/docs/advanced/routing#omitting-the-blog-folder-in-urls
---------------------------------------

*/

c::set('routes', array(
  array(
    'pattern' => '(:any)/([a-zA-Z0-9_-]+(.jpg|.png|.gif|.svg))',
    'action'  => function($stub, $filename) {

    /** 
      * See if the stub is a real content directory 
      * If not, see if it is a sub-directory of our
      * removed directory: /writing 
      */
      $page = @page($stub);
      if (!$page) { 
        $page = @page('writing/'.$stub); 
      }

    /**
      * If the page exists and is a real page 
      * (e.g. /error), it will have a url 
      */
      if( @$page->url() ) { 
      /** 
        * See if the file really exists in that content directory. 
        */
        $file = @$page->files()->find($filename);
        if ( !$file || $file == null ) {
        /** 
          * Handle actual 404 missing images
          */
          return false;
          // return go( 'error' );
        } else {
          $fileURL = $file->url();
        }
      } 
    
    /**
      * Load the actual image or the error page if it doesn't exist.
      */
      return go( $fileURL ? $fileURL : 'error' );
    }
  ),
  array(
    'pattern' => '([a-zA-Z0-9_-]+)', // Page slug is alphanumeric with dashes
    'action'  => function($uid) {

      $page = page($uid);

      if(!$page) $page = page('writing/' . $uid);
      if(!$page) $page = site()->errorPage();

      return site()->visit($page);

    }
  ),
  array(
    'pattern' => 'writing/([a-zA-Z0-9_-]+)',
    'action'  => function($uid) {
      
      return go( $uid );

    }
  ),
));

.htaccess

which (among other things) forces trailing slashes

################# REDIRECT LINKS (and Kirby)

<IfModule mod_rewrite.c>

	RewriteEngine on
	RewriteBase /

	#############
	### Redirects

	RewriteRule ^build-2013/?$ /writing-for-beginners/ [R=301,NC,L]
	RewriteRule ^services/?$ /what-i-do/ [R=301,NC,L]
	RewriteRule ^work/?$ /projects/ [R=301,NC,L]


	############
	### Security

	# block text files in the content folder from being accessed directly
	RewriteRule ^content/(.*)\.(txt|md|mdown)$ error [R=301,L]

	# block all files in the site folder from being accessed directly
	RewriteRule ^site/(.*) error [R=301,L]

	# block all files in the kirby folder from being accessed directly
	RewriteRule ^kirby/(.*) error [R=301,L]

	#############
	### Real Files
	## if this is an existing folder/file then leave
	RewriteCond %{REQUEST_FILENAME} -d [OR]
	RewriteCond %{REQUEST_FILENAME} -f
	RewriteRule . - [L]

	#############
	### Cache-busting of JS and CSS versions
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteRule ^(.*)\.([0-9\-]+)\.(js|css)$ $1.$3 [L]

	#############
	### Trailing Slashes
	## if no trailing slash then redirect to url with trailing slash
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]+|/)$
	RewriteRule ^(.*)$ $1/ [L,R=301]

	#############
	### The Panel
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteCond %{REQUEST_FILENAME} !-d
	RewriteRule ^panel/(.*) panel/index.php [L]

	####################
	### Kirby Site Pages
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteCond %{REQUEST_FILENAME} !-d
	RewriteRule ^(.*)/? index.php [L]

</IfModule>

Hey,

I just stumbled upon your post. I’m having an issue I think you may have found a solution for. Maybe you could have a look at this?
http://forum.getkirby.com/t/omitting-parts-of-urls/539

1 Like