3

I'd like to append a #fragment for the client to read on certain URLs (and used by an SPA).

<IfModule mod_rewrite.c>
 RewriteEngine On
 RewriteBase /
 RewriteRule ^foo/? /foo#bar [QSA,NE,L,R=301]
</IfModule>

However, since #bar is a fragment in the URL above, it seems to get stripped out and cause a redirect loop. I've also tried escaping the hash like RewriteRule ^foo/? /foo\#bar.

Is there some way of limiting that RewriteRule to just one redirect?

  • I'm writing this to an .htaccess file in the target directory. The webserver is httpd -v Server version: Apache/2.4.39 (centos)
Orun
  • 157
  • 1
  • 6

2 Answers2

4

I've also tried escaping the hash like ...

The problem is not the redirect response. /foo#bar is being correctly sent back to the client in the Location: header (the NE flag helps here by preventing the # being URL-encoded in the response).

The problem is that the browser does not send the fragment identifier back to the server on the redirected request (as @Gerald stated, "[Fragments] are never transmitted to the server"). So, the server repeatedly sees /foo, hence the redirect loop. There is nothing you can do about the missing fragment identifier.

From a server perspective, you would need to change the URL in some other way, perhaps by appending a query string parameter. For example:

RewriteCond %{QUERY_STRING} !^redirect
RewriteRule ^foo/? /foo?redirect=1#bar [QSA,NE,R,L]

The above appends a redirect=1 URL parameter to the redirect response and the condition makes sure that this parameter is not present before making the redirect.

However, appending a URL parameter is probably not desirable.

Since this is only for use by the client in an SPA, you should instead be using the JavaScript History API and replaceState() (or possibly pushState()) method(s) to append the #bar fragment identifier to the URL and trigger a client-side response. No server-side redirect is required.

MrWhite
  • 12,647
  • 4
  • 29
  • 41
  • Thanks. The challenge is that I have an Angular SPA within a PHP application. I'm trying to control the state of the SPA when 3rd party bots (Linkedin using Open Graph data) get the correct meta data on their first request. So JS, like manipulating the history API, doesn't work in my instance. – Orun Jun 26 '19 at 14:50
3

You can't. Fragments are only handled by the browser. They are never transmitted to the server.

Gerald Schneider
  • 23,274
  • 8
  • 57
  • 89
  • 1
    I know they are never transmitted _to_ the server, but my hope was that I could redirect and send this data _from_ the server to the client. – Orun Jun 26 '19 at 14:45
  • Nevermind, I undersood this within the context of the other answer from `@MrWhite`. > The problem is that the browser does not send the fragment identifier back to the server on the _redirected_ request – Orun Jun 26 '19 at 15:32