ようへいの日々精進XP

よかろうもん

Nginx の rewrite を使ったリダイレクトで URL に #(アンカーリンク)が付いていたらどうなるの?

追記

以下、同僚のぐっさんに教えて頂いたので追記。

tl;dr

http://xxx.xxx.xx.xxx/index.html#foo のようなリンクを http://xxx.xxx.xx.xxx/maintenance.html にリダイレクトさせた場合に、#foo ってどうなのかなと思って調べてみた。

出来れば、リダイレクト先では #foo を削除出来たら嬉しい。

memo

試した環境

bash-3.2$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G31

bash-3.2$ docker-machine -version
docker-machine version 0.6.0, build e27fb87

bash-3.2$ docker exec -t -i nginx nginx -v
nginx version: nginx/1.11.3

結論

  • リダイレクト先にも # はくっついてくる

雑な Nginx 設定

server {

    listen 80;
    server_name example.org;
    charset utf-8;

    location / {
        root   html;
        index  index.html index.htm;
        rewrite /index.html /maintenance.html permanent;
    }
}

Dockerfile は以下のように用意。

FROM nginx:alpine
RUN rm /etc/nginx/conf.d/default.conf
RUN mkdir /etc/nginx/html
ADD maintenance.html /etc/nginx/html/
ADD index.html /etc/nginx/html/
ADD demo.conf /etc/nginx/conf.d/

各コンテンツ。

bash-3.2$ cat index.html
index.html
bash-3.2$ cat maintenance.html
maintenance.html

以下のようにコンテナを起動。

docker run --name=nginx -d -p 80:80 inokappa/nginx-demo

curl で試す

bash-3.2$ curl -vL 'http://xxx.xxx.xx.xxx/index.html#foo'
*   Trying xxx.xxx.xx.xxx...
* Connected to xxx.xxx.xx.xxx (xxx.xxx.xx.xxx) port 80 (#0)
> GET /index.html HTTP/1.1
> Host: xxx.xxx.xx.xxx
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.11.3
< Date: Tue, 20 Sep 2016 13:59:40 GMT
< Content-Type: text/html
< Content-Length: 185
< Location: http://xxx.xxx.xx.xxx/maintenance.html
< Connection: keep-alive
<
* Ignoring the response-body
* Connection #0 to host xxx.xxx.xx.xxx left intact
* Issue another request to this URL: 'http://xxx.xxx.xx.xxx/maintenance.html'
* Found bundle for host xxx.xxx.xx.xxx: 0x7fed63d10e70
* Re-using existing connection! (#0) with host xxx.xxx.xx.xxx
* Connected to xxx.xxx.xx.xxx (xxx.xxx.xx.xxx) port 80 (#0)
> GET /maintenance.html HTTP/1.1
> Host: xxx.xxx.xx.xxx
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.11.3
< Date: Tue, 20 Sep 2016 13:59:40 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 17
< Last-Modified: Tue, 20 Sep 2016 07:12:24 GMT
< Connection: keep-alive
< ETag: "57e0e158-11"
< Accept-Ranges: bytes
<
maintenance.html
* Connection #0 to host xxx.xxx.xx.xxx left intact

よく見ると...

< Location: http://192.168.99.100/maintenance.html

Response ヘッダの Location は http://192.168.99.100/maintenance.html で返ってきているのでなんか期待できそうだ。

ブラウザで見る

f:id:inokara:20160920230716p:plain

それ、リダイレクト。

f:id:inokara:20160920230729p:plain

うおお、#foo が付いたままや。

アクセスログ見てみる

とりあえず、アクセスログを見てみる。

# curl でアクセスした場合
xxx.xxx.xx.x - - [20/Sep/2016:13:59:40 +0000] "GET /index.html HTTP/1.1" 301 185 "-" "curl/7.43.0" "-"
xxx.xxx.xx.x - - [20/Sep/2016:13:59:40 +0000] "GET /maintenance.html HTTP/1.1" 200 17 "-" "curl/7.43.0" "-"

# ブラウザでアクセスした場合
xxx.xxx.xx.x - - [20/Sep/2016:14:03:49 +0000] "GET /index.html HTTP/1.1" 301 185 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36" "-"
xxx.xxx.xx.x - - [20/Sep/2016:14:03:49 +0000] "GET /maintenance.html HTTP/1.1" 200 17 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36" "-"

あら、ログには #foo はくっついてきてませんがな。イメージとしてクエリパラメータ(?foo=bar)と同じような内容を想定していたけど。ちなみに、クエリパラメータをくっつけた場合には以下のようなログが記録される。

# curl でアクセスした場合
xxx.xxx.xx.x - - [20/Sep/2016:14:11:34 +0000] "GET /index.html?foo=bar HTTP/1.1" 301 185 "-" "curl/7.43.0" "-"
xxx.xxx.xx.x - - [20/Sep/2016:14:11:34 +0000] "GET /maintenance.html?foo=bar HTTP/1.1" 200 17 "-" "curl/7.43.0" "-"

# ブラウザでアクセスした場合
xxx.xxx.xx.x - - [20/Sep/2016:14:12:10 +0000] "GET /index.html?foo=bar HTTP/1.1" 301 185 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36" "-"
xxx.xxx.xx.x - - [20/Sep/2016:14:12:10 +0000] "GET /maintenance.html?foo=bar HTTP/1.1" 200 17 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36" "-"

ちゃんとクエリパラメータがログに記録されている。これであればサーバーサイドでパラメータを削除したり、書き換えたりすることができそう。ちなみに、クエリパラメータを削除したい場合には以下のような設定を書くことでクエリパラメータを削除した状態でリダイレクトされる。

server {

    listen 80;
    server_name example.org;
    charset utf-8;

    location / {
        root   html;
        index  index.html index.htm;
        rewrite /index.html /maintenance.html? permanent;
    }
}

ということで

アンカーリンクは...

リダイレクト先にも引き継がれてしまう。

なんで?

アンカーリンクでサーバーサイドというよりもブラウザで解釈されるものだからかなと。

誤り等あればご指摘頂ければ幸いです。