chromeで、Content-Type の調べ方

『Content-Type』を調べたい事がありましたので、調べ方をメモしておきます。

chromeで、Content-Type の調べ方

Content-Type について

その前に、『Content-Type』について復習です。

たとえば、インターネットでファイルのダウンロードを行う時等、ファイルに拡張子がなかったり、拡張子からファイルの種類が分からない場合がある。
その場合、「これから返すファイルの種類」をContent-Typeによって示すことで、ファイルの種類を受け取る側が知ることができる。またその種類に応じて、Webブラウザがそのまま表示したり、ファイルとして保存したり、他のアプリケーションを起動してそれを用いて出力したり、と処理を変更する。

Content-Typeとは : JavaA2Z

簡単に言うと、windowsでの拡張子に当たる部分です。
例えば、ブラウザでweb上の『.cgi』ファイルにアクセスした場合、拡張子からCGIだとわかっても、帰ってくるデータが、テキストなのか、画像なのか、scriptなのか、ダウンロードファイルなのか、ブラウザは分からは判断できません。したがって、『Content-Type』にファイル形式を明示するのです。

今までコードのお約束事として記述していた下記のような『Content-Type』は、「htmlファイルです」と、ブラウザに伝えていたのです。(HTML5からは記述しなくても、”text/html”として扱われるようです。)

# HTML
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
# php
header("Content-type: text/html; charset=utf-8");

Content-Type を調べてみる。

本題です。実際にheader情報の『Content-Type』をchromeを使って確認してみます。
chormeのアドレスバーに

chrome://net-internals/#events

を、入力します。(chrome://about/ と入力すると、開発者向けの機能が提供されています。その中の1つです。)

chrome_net-internals01

表示されたリストから、確認したい通信をクリックします。
当サイトだと、
Source Type : URL_REQUEST
Description : http://blog.cototoco.net/
です。ウィンドウ右側に詳細が表示されます。

詳細の中、さらに、HTTP_TRANSACTION_READ_RESPONSE_HEADERS、に『Content-Type』が記載されています。

chrome_net-internals02

当サイトの『Content-Type』が
Content-Type: text/html; charset=UTF-8
だとわかります。

実験

html5に『Content-Type』(metaタグ)有り無しで実験してみます。ちなみに、HTML5では省略しても”text/html”と扱われるので、省略しています。

# meta 有り無し
<meta http-equiv="content-type" content="text/html" charset="UTF-8">

html5に『Content-Type』有りの場合

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html" charset="UTF-8">
<title>Content-Typeサンプル</title>
</head>
<body>
<p>HTML5 Content-Type はどうなっているか?</p>
</body>
</html>

html5に『Content-Type』有りの場合の『Content-Type』は
Content-Type: text/html となっていることが確認できました。

# meta 有りのheader情報
HTTP_TRANSACTION_READ_RESPONSE_HEADERS
--> HTTP/1.1 200 OK
  Date: Fri, 11 Jul 2014 05:27:51 GMT
  Server: Apache
  Last-Modified: Fri, 11 Jul 2014 05:27:41 GMT
  ETag: "5e1f2e-e8-53bf75cd"
  Accept-Ranges: bytes
  Content-Length: 232
  Connection: close
  Content-Type: text/html

html5に『Content-Type』無しの場合

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Content-Typeサンプル</title>
</head>
<body>
<p>HTML5 Content-Type はどうなっているか?</p>
</body>
</html>

html5に『Content-Type』有りの場合の『Content-Type』は
明記されていないようです。(注:キャッシュが残っている場合はキャッシュが表示されているようです。)

# meta 無しのheader情報
HTTP_TRANSACTION_READ_RESPONSE_HEADERS
--> HTTP/1.1 304 Not Modified
   Date: Fri, 11 Jul 2014 05:38:35 GMT
   Server: Apache
   Connection: close
   ETag: "5e1f2e-a2-53bf782f"

以上、chromeで、Content-Type の調べ方です。
また、この方法で、header情報も同時に確認できることになります。

Content-Typeとは : JavaA2Z

gihyo.jp

docomoテザリングでは、PPTP(VPN)接続できず。

2014年7月9日時点の話です。技術的な問題みたいなので、今後もdocomoのテザリングでPPTP(VPN)接続はできないと思われます。IPSecが使える環境を構築するのがいいみたいです。

本題です。

手持ちの機材で、自宅外から自宅PCを起動する(WOL)

今回の目的は、『手持ちの機材で、自宅外から自宅PCを起動する(WOL)』です。

機材
 ・WZR-HP-G301NH(バッファロールータ)
 ・xperia z docomo SO-02E Android 4.2.2

結果的にdocomoのテザリング(SPモード)の仕様と自宅ルーター機能の兼ね合いで、接続できなかったのですが、せっかくなので将来環境を変えた時や再チャレンジのために、メモを残しておきたいと思います。

まず、WZR-HP-G301NHはWOLに対応してるとスペックには書かれていますが、直接外部からのマジックパケットを転送するのではなく、ルータ自身から発生させる方法でWOLを可能としています。

そのために、外部から一度ルータ(ルータ管理画面)にアクセスする必要があります。そこでWZR-HP-G301NHには、PPTPサーバをたてて外部からのアクセスを許可する機能があり、それを使い外部からアクセスを行います。

Android4(バージョン2の途中から)には、OSの機能としてVPNクライアントがあります。アンドロイドに、自宅PPTPサーバPPTPのパスを設定しアクセスすることで、目的のWOLが可能になるはずでした。

が、設定が正しくてもつながりません。理由はdocomoのSPモードが使っているは方式では、PPTPのアドレス変換がうまくいかないようです。この理由や、SPモードのこと、PPTPのプロトコルのことなど詳しいことは私も知りませんが、価格.comのスレッドに詳しい方がおられたので、こちら『スマホ【GALAXY:ギャラクシ】によるPPTP接続について』が参考になると思います。

WZR-HP-G301NHのPPTPサーバ設定方法とAndroidのクライアント設定はこちらの方々を参考にさせていただきました。

Androidから自宅ネットワークにVPNアクセスする 後編

Wake-on-LAN – Wikipedia

スマホ【GALAXY:ギャラクシ】によるPPTP接続について

ドコモの公式テザリングでVPNを使うのに必要な知識

SSL-VPNの導入メリット(後編):“SSL-VPN or IPSecVPN”どちらが最適ですか? – @IT

ディープコピー 【Ruby】

『オブジェクトのコピー』,『メソッドの引数(値渡し、参照渡し)』の延長です。私もよくわかっていないので、さらっと流します。

配列のコピーや、メソッドの引数に配列を渡すとき、『副作用』(コピー先の値を変更すると、コピー元の値も変更される)が発生するので、『副作用』を避ける場合、cloneメソッドで複製を作る方法を紹介しました。

しかし、多重ループの場合 cloneメソッドでは、2次以上の部分に副作用が残ります。その際に用いるのが、ディープコピー(deep copy)という方法です。

Javaではキチンと?書かないといけないようですが、rubyでは次のコードでディープコピー行えるようです。(*2)

obj_m = Marshal.load(Marshal.dump(obj))

Marshalモジュール : オブジェクトをファイル(または文字列)に書き出したり、読み戻したり する機能を提供するモジュール(*1)
渡したオブジェクトを、Marshal.dump で出力し、Marshal.loadで読み込み、オブジェクトを返すイメージです。

実際にサンプル(sample01)を見てみます、まず clone メソッドでコピーした場合の副作用を見てみます。
4, 5行目 : clone で複製したオブジェクトは別物になっています。
しかし、
6, 7行目 : arrA[0]と、arrB[0]は同じオブジェクトを参照
8, 9行目 : arrA[1]と、arrB[1]は同じオブジェクトを参照
しているので、arrA[0][1]の値を変更した際に、arrBの中の値も変更されています(副作用)。

arrA = Array.new(2){ |i| Array.new(4){ |j| i * 4 + j + 1 } }
p arrA # => [[1, 2, 3, 4], [5, 6, 7, 8]]
arrB = arrA.clone
p arrA.object_id # => 17481360
p arrB.object_id # => 17481200
p arrA[0].object_id # => 17481350
p arrB[0].object_id # => 17481350
p arrA[1].object_id # => 17481340
p arrB[1].object_id # => 17481340
arrA[0][1] = 10
p arrA # => [[1, 10, 3, 4], [5, 6, 7, 8]]
p arrB # => [[1, 10, 3, 4], [5, 6, 7, 8]]

ディープコピーを使ったサンプル(sample02)では、
6, 7, 8, 9行目 : arrA[0], arrB[0], arrA[1], arrB[1] が、それぞれ別々のオブジェクトを参照しています。
arrA[0][1]の値を変更しても、arrBの中の値は変更されていません。

arrA = Array.new(2){ |i| Array.new(4){ |j| i * 4 + j + 1 } }
p arrA # => [[1, 2, 3, 4], [5, 6, 7, 8]]
arrB = Marshal.load(Marshal.dump(arrA))
p arrA.object_id # => 7977880
p arrB.object_id # => 7977670
p arrA[0].object_id # => 7977870
p arrB[0].object_id # => 7977660
p arrA[1].object_id # => 7977860
p arrB[1].object_id # => 7977650
arrA[0][1] = 10
p arrA # => [[1, 10, 3, 4], [5, 6, 7, 8]]
p arrB # => [[1, 2, 3, 4], [5, 6, 7, 8]]

蛇足で、3次元配列もディープコピーを見てみますと、別々のオブジェクトを参照しているようです。

arrA = Array.new(3){ |i| Array.new(2){ |j| Array.new(3){|k| i * 6 + j * 3 + k + 1 }} }
p arrA # => [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]], [[13, 14, 15], [16, 17, 18]]]
p arrA[0] # => [[1, 2, 3], [4, 5, 6]]
p arrA[0][0] # => [1, 2, 3]
arrB = Marshal.load(Marshal.dump(arrA))
p arrA.object_id # => 17830590
p arrB.object_id # => 17830150
p arrA[0].object_id # => 17830580
p arrB[0].object_id # => 17830140
p arrA[0][0].object_id # => 17830570
p arrB[0][0].object_id # => 17830130

(*1)Ruby 2.1.0 リファレンスマニュアル module Marshal

(*2)Ruby 1.8.7 リファレンスマニュアル instance method Object#clone

メソッドの引数(値渡し、参照渡し)

Rubyの引数は値渡しです。

Rubyの引数は値渡しです。参照渡しではありません。ググるとそのようにまとめてらっしゃる方が多々ありますので間違いはないとおもいます。Ruby リファレンスマニュアルで探してみたんですが、記載を見つけられませんでした、確認でき次第アドレスを掲載します。
(*1)参考リンクを追加しました。

ここではRubyの引数(値渡し,参照渡し)について自分なりにまとめてみます。

Rubyist Magazine – 値渡しと参照渡しの違いを理解する

を深く読んでください。を深く読んでください。を深く読んでください。
この記事よりもよっぽど詳しいです。。。

メソッドの復習と名称

def hoge(a) # メソッド: hoge, 仮引数: a
    a += 10 # a に 10 を足す
end

x = 10 # 変数 x
hoge(x) # メソッド hoge に、実引数 x を渡す

値渡しと参照渡し

値渡しと参照渡しについて簡単に説明します。詳細は本当にググってください…

・値渡し (call by value) :実引数として変数を渡しても、その値のみが渡される。そのため、仮引数を変更しても、実変数は変更されない。

def hoge(a) # メソッド: hoge, 仮引数: a
    a += 10 # a に 10 を足す
    p a # => 20
end

x = 10 # 変数 x
hoge(x) # メソッド hoge に、実引数 x を渡す
p x # => 10

・参照渡し (call by variable) :実引数として変数を渡しすとき、変数に対する参照(メモリ番地)先を渡す。そのため、仮引数の値を変更すると、実変数の値も同様に変更されたことになる。

def hoge(a) # メソッド: hoge, 仮引数: a
    a += 10 # a に 10 を足す
end

x = 10 # 変数 x
hoge(x) # メソッド hoge に、実引数 x を渡す
p x # => 20

注)仮のコードです、rubyでは動作確認できません

引数(実引数)が配列の場合

Rubyは『値渡し』です。しかし、実引数にが配列の場合『参照渡し』のような結果になるときがあります。実引数で渡した配列が、仮引数の値を変更すると実引数の値も変わってしまう『副作用』が生じます。実はこの時『参照の値渡し』と言う値渡しが行われています。
理屈は以前の記事オブジェクトのコピーと同じで、実引数も仮引数も同じオブジェクトを見ている、仮引数にはオブジェクトの参照の値が渡されたということになります。

def hoge(a) # メソッド: hoge, 仮引数: 配列 a
    a[0] += 10 # 配列a[0] に 10 を足す
end

x = [10] # 変数: 配列 x
hoge(x) # メソッド hoge に、実引数 x を渡す
p x # => [20] # 実引数の値が変更されている

objcet_idを確認してみる

def hoge(a)
    a[0] += 10
    p a.object_id # => 17968120
end

x = [10]
p x.object_id # => 17968120
hoge(x)
p x # => [20] # 実引数の値が変更されている

*)object_idで同一性を確認しているだけです。rubyではメモリの番地を調べることはできないようです。

引数(実引数)が配列の場合の『副作用』を予防する

この副作用を予防するには、実引数と仮引数が別のオブジェクトを参照していれば良いということになります。なので、複製を作ればOKになります。

def hoge(a)
  p a.object_id # => 540724920
end

x = [1, 2, 3, 4, 5]
p x.object_id # => 539436540
temp = x.clone
hoge(temp)
def hoge(*a) # * 複数の引数を配列として受け取ります。
  p a.object_id # => 539428060
end

x = [1, 2, 3, 4, 5]
p x.object_id # => 539443780
hoge(*x) # * 展開して渡します

sample01, sample02 もobject_idが違うので、『副作用』は起こりません。

しかし・・・多重配列だと・・・別の機会追記しました。

Rubyist Magazine – 値渡しと参照渡しの違いを理解する

引数 – Wikipedia

*1)お気楽 Ruby プログラミング入門第 3 回●値呼びと参照呼び

変数や定数は,あるオブジェクトを指しています.何も代入しなくても nilオブジェクトを指しています.代入は,変数や定数が新しいオブジェクトを 指すようにします.

したがって,代入によりオブジェクトがコピーされて新しく作られることは なく,右辺の表現の表しているオブジェクトを左辺の変数や定数が指すように することが代入によって行われます.

*1)Ruby FAQ: 変数,定数,引数(文字化けします、EUCで開いてください)

オブジェクトのコピー 【Ruby】

ここでは、オブジェクトを複製するときに注意すること(特に配列オブジェクト)を記述します。
phpでは考えなくてよかったことですが、他の言語ではどうなんでしょうね。

オブジェクトの複製の説明ですが、メソッドの引数にも共通している内容だと思います。
メソッドの引数については、次回触れてみようと思います。(値渡し,参照渡し)

少し復習

rubyでは変数も何かのオブジェクトです。

変数『a』という箱に”cototoco”という文字を入れたイメージですが、「String(文字列)オブジェクト”cototoco”に、『a』とラベルを付けた」と、言うとらえ方もsample0よりわかります。
*)変数はオブジェクトにつける名札 Ruby リファレンスマニュアルの用語集 変数より

a = "cototoco"
p a.class # => String
p a.object_id # => 540010740

注) すべてオブジェクトと記載しようとして思い調べてみたら、違うようです。
メソッド,ブロック,演算子のand, or 等々はオブジェクトではないとのことです。
Rubyでは、すべてがオブジェクト。じゃないよ! – このブログは証明できない。

オブジェクトのコピー[導入部]

文字列オブジェクト『a』を『b』に代入してみます。
『a』と『b』のobject_idが同じ値になっていることから、ラベルの違う『a』と『b』は同じオブジェクトを参照していることが分かります。同じオブジェクトなので、内容も同じです。しかし、object_idが1つなのでオブジェクトはコピー(複製)されていません。

a = "cototoco"
p a.class # => String
p a.object_id # => 540009530
b = a
p b.class # => String
p b.object_id # => 540009530

ここで、『a』に別の値を入れてみます。
すると、『a』は初期化されので、新しいobject_idが振られていることが分かります。
『a』と『b』は別々のオブジェクトになり、中の文字列も別々の値になっています。
『a』の値を変更しても、『b』の値は保持されているので、複製の目的は成り立っています。

# sample1の続き
a = ".net"
p a.object_id # => 539434520
p b # => "cototoco"
p b.object_id # => 540009530

オブジェクトのコピー[本題]

さて、『a』が配列オブジェクトの場合もStringオブジェクトと同様の結果になりますが、少し注意することが必要です。
『a』の配列の中の値を変更する場合、『b』の値も変更されてしまいます。

a[1]の値を変更した結果、b[1]の値も変更されています。不思議に感じますが、object_idを調べてみると『a』と『b』は同じオブジェクトを参照していることがわかります。『a』と『b』の参照先は同じなので、『a』を変更するということは、『b』を変更することになります。

a = [3, 7, 9, 2]
b = a
p a[1] # => 7
a[1] = 10
p a # => [3, 10, 9, 2]
p b # => [3, 10, 9, 2]
a.object_id # => 540642090
b.object_id # => 540642090

『a』と『b』を別々のオブジェクトにするとこの動作がなくなります。

1, 『a』を初期化する。sample2の様に、『a』に改めて値を代入します。

a = [3, 7, 9, 2]
b = a
a = [3, 10, 9, 2]
p a # => [3, 10, 9, 2]
p b # => [3, 7, 9, 2]
a.object_id # => 539950350
b.object_id # => 539958810

2, clone, dup メソッドを使う。
cloneメソッドはオブジェクトの複製を返すメソッドです。(リファレンスマニュアル

a = [3, 7, 9, 2]
b = a.clone
a[1] = 10
p a # => [3, 10, 9, 2]
p b # => [3, 7, 9, 2]
a.object_id # => 540474720
b.object_id # => 540331010

配列オブジェクトの複製は、cloneメソッドsample5かsample4の方法を持ちいりましょう。

破壊的メソッドはレシーバ自身を変更する

以前の記事、配列 メソッドについてのように、破壊的メソッドはレシーバ自身を変更します。
この時、意図せずsample3パターンにはまってしまう時があります。

例えば、配列『arr_a』に値を追加する時、現在の値を『temp』に保存する場合を考えます。
配列に値を追加するメソッドにpushがあります。pushは破壊的メソッドなのでレシーバを変更します。
では、『arr_a』を『temp』に保存し、『arr_a』にpushで値を追加してみます。

arr_a = [3, 7, 9, 2]
temp = arr_a
arr_a.push(100)
p temp # => [3, 7, 9, 2, 100]

状態を保存したはずの『temp』の値まで変更されてしまいました。
このようなときはsample5のように、cloneメソッドを持ちいりましょう。

Rubyでは、すべてがオブジェクト。じゃないよ! – このブログは証明できない。
リファレンスマニュアル