コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

ソフト404とは何なのかざっくりまとめる

ソフト404って結局何がどういうことなんだっけ、というざっくりまとめ

出典

ソフト 404 エラー - Search Console ヘルプ

初出(と思われるもの)

HTTP 404 - Wikipedia 曰く ソフト404という用語は Sic Transit Gloria Telae : Towards an understanding of the Web's decay にて紹介されたとされている。

この論文では死んだページとその検出アルゴリズムについて書かれているのだが、その説明の中で下記のように語られている

ただし、今日の多くのWebサーバーは、存在しないページに対するHTTPリクエストを受信しても、エラーコードを返さないことがわかりました。 代わりに、OKコード(200)といくつかの代替ページを返します。 通常、この代替は、エラーメッセージページ、そのホストのホームページ、またはまったく関連のないページです。 上記のように動作する、存在しないページを「ソフト404ページ」と呼びます。

このように定義が書かれており、この用語がままつかわれるようになっている。

具体的にはどのようなページか

「ソフト404」と言われるものは、以下の要素をもちあわせている

  • HTTPステータスコードは200OK
  • ただし画面上の表記は「コンテンツが見つかりませんでした」などの表記で、汎用的な対応するページがないエラー(広い意味での 404 の状態)

ソフト404は何が良くないのか

この状態が芳しくない理由をGoogleのヘルプでは以下のように記載されている。

検索エンジンでは、成功コードが返されると、その URL に実際のページがあるものと判断します。その結果、ページが検索結果に表示され、検索エンジンは実際のページをクロールする代わりに、存在しない URL を引き続きクロールしようとします。

この状態が起きると具体的に何が良くないかがわかりにくいが、ことGooglebotにおいては以下のようなことになる可能性がある。

  1. 存在しないページなのに存在するステータスコードを返すため、検索ボットクローラーが「意義のああるページ」と誤認する
  2. ソフト404ページの実際の中身は「ページがない」という旨を知らせる共通HTMLであることが多いので、クローラーは同じページがたくさんあると誤認する
  3. 同じ構成のページがたくさんあると重複コンテンツにあたるため、どれが正しいページが見定めようとする
  4. 正しいページの見解を見誤ると検索に引っ掛けるための精度が下がるため、適切なページが検索結果に出にくくなる

※3,4に関しては重複コンテンツの説明である下記ページ参照のこと 重複した URL を統合する - Search Console ヘルプ

直接的にはソフト404自体でペナルティになる…ということはないが「重複コンテンツ」の仕組みとかけあわさると、正確な情報がクローリングされなくなる恐れがある、という問題に発展する可能性がある、というレベルが現在の実態の様子だった。

関連サイト

URLで//(スラッシュスラッシュ)から記述してschema(プロトコル)を省略すると、現在のページのschemaで動く

いい感じにわかる情報がなかったので

出典

RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax

要約

//example.com などと http の部分(schema/プロトコル)を省略して記述した場合は、開いているページのものをそのまま使う。

内容と考え方

// で始まる net_path として定義されている。

net_path = "//" authority [ abs_path ]

また、この net_path は相対参照であることが記載されている・

The syntax for relative URI takes advantage of the <hier_part> syntax of (Section 3) in order to express a reference that is relative to the namespace of another hierarchical URI.
relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
A relative reference beginning with two slash characters is termed a network-path reference, as defined by <net_path> in Section 3. Such references are rarely used.

これを和訳すると以下の通り

相対URIの構文は、別の階層URIの名前空間に関連する参照を表すために、(セクション3)の<hier_part>構文を利用します。
relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
セクション3の<net_path>で定義されているように、2つのスラッシュ文字で始まる相対参照は、ネットワークパス参照と呼ばれます。このような参照はほとんど使用されません。

これらより以下のことでschema部が補完される。

  • // から始まるURIは相対参照(ネットワークパス参照)と呼ばれるの相対URI扱い
  • 相対URIなので通常の https://example.com/a.html<img src="images/sample.gif"> 記述したときに <img src="https://example.com/images/sample.gif"> と補完されるのと同じ原理でschema部が補完される。

参考サイト

GitHubのカバレッジなどのバッチと同じような画像が作れるサイト shields.io

カバレッジバッジとかの画像と似たようなものが自作できるのでメモ

サイト

Shields.io: Quality metadata badges for open source projects

このサイトの便利ポイント

画像生成サイトは数多があるが、このサイトの便利なところはURLで画像の中身を設定できるところ。

命名規則は簡単で

https://img.shields.io/badge/{{ラベル名}}-{{メッセージ名}}-{{色名称}}

例えばテストが通過したなどのアイコンを作りたい場合は以下のような感じのURLを指し示せばOK

https://img.shields.io/badge/test-complete-green

sample

なお、日本語も使える。

sample

また、動的につくる仕組みも用意しているので自前のサイトでシンプルなバッジを用意する際などには便利。

  • JSONの在り処を示すと、そのJSONを元にバッジを作るなど動的に作る仕組みのEndpoint
  • 既存の配信データから特定の部分を指し示すことで任意のデータを見せるDynamic

Dynamicについて

DynamicはJSONの指定位置を指し示してデータを取得する方法。

データの指定としては以下のようなルールになっている(ドキュメントらしいドキュメントがないのでざっとの説明)

UI上の名前 入れるデータ
label 左側に記載される文字
data url 今回の情報取得元のURL
query 取得したい情報の位置を示す文字列。JSONの場合は$. から初めてキー名を指定してあげる。
color 右側に記載される動的文字列の色名
prefix 動的取得した文字の前に記載する文字
prefix 動的取得した文字の後に記載する文字

QiitaAPIを使った事例

たとえばQiitaの記事APIは以下のようなJSONになっている(完全な資料はAPIドキュメント参照

{
  "rendered_body": "<h1>Example</h1>",
  "body": "# Example",
  "coediting": false,
  "comments_count": 100,
  "created_at": "2000-01-01T00:00:00+00:00",
  "group": {
    "created_at": "2000-01-01T00:00:00+00:00",
    "id": 1,
    "name": "Dev",
    "private": false,
    "updated_at": "2000-01-01T00:00:00+00:00",
    "url_name": "dev"
  },
  "id": "c686397e4a0f4f11683d",
  "likes_count": 100,
  "private": false,
  "reactions_count": 100,
  "tags": [
    {
      "name": "Ruby",
      "versions": [
        "0.0.1"
      ]
    }
  ]
 //#### 以下略 ###
}

この場合LGTM数はlikes_countなので下記のようにURLを指定するとLGTM数を交えたアイコンが作れる。

そのため今回は下記のようにデータを指定した

UI上の名前 入れるデータ
label Qiita
data url https://qiita.com/api/v2/items/f2651073fb71416b6cd7
query $.likes_count
color green
prefix LGTM数は
prefix LGTM

そうすると下記のようなURLが生成され、動的に画像が表示される。

https://img.shields.io/badge/dynamic/json?color=green&label=Qiita&prefix=LGTM%E6%95%B0%E3%81%AF&query=%24.likes_count&suffix=LGTM&url=https%3A%2F%2Fqiita.com%2Fapi%2Fv2%2Fitems%2Ff2651073fb71416b6cd7

badge

関連リンク

広告在庫の概念がわかりにくいのであっさり味にまとめる

仕入れてないのに在庫って何やねん。という流通視点で行くとだいぶ混乱するので整理

その前の大前提

Web広告においてはエンドユーザーに表示される数がすべての根底にあり、その表示される数のことをインプレッション(略称:imp)と呼ばれる。

Web広告における在庫とは

基本的にはこの広告の表示が成立がすると、その表示にたいしてお金がはいるのがWeb広告となる。

そのため、広告を表示するWebサイトとしては「広告を表示するとお金が入る」ということになり、言い換えると「広告の1インプレッションを売る」ということになる。その考え方の流れに準ずると「 広告1表示 というものを売る」という考えになるので、広告在庫 = インプレッション数となる。

一般概念の在庫と乖離する部分

在庫は確実に用意できない場合がある

広告在庫というのは「ある一定期間のimpの予想値」であるので、必ずしもそのPVがその期間に取れるとは限らない(『その期間にサーバートラブルを起こしてページが表示されない』などで予想とズレるなどはある)

そのため、在庫を作るためにリアルタイムで工夫する必要があったり、他のページから無理くり誘導させる必要などがある。

在庫が余る

当該枠に関して枠があるが、買い手がいないのでただただ表示してimpを得れるが、広告がない状況になる。このような場合のことを在庫が余るなどと表現される。商品在庫はあるのに買い手がついていないと考えるといいと思う。

参考リンク

広告費におけるネット、グロス、マージンとは

いつもわからなくなるので図で書き留めておく

用語

ネット(Net)

ベースとなる費用のこと。意味としては「網」の方ではなく「正味」を表す英単語から。

マージン(Margin)

上乗せする手数料費用などの費用のこと

グロス(Gross)

ネットとマージンを足した総合計の費用。

図で表した例

例えば

  • ベースの費用が80万
  • マージンとしての手数料が20万
  • 総合計の費用が100万

だとすると、各用語の意味は以下のようになる

f:id:shinkufencer:20200821235620p:plain
ネット、マージン、グロスのまとめ図

補足

ちなみにパッケージ商品にも「NET」の表記があったりするが、こちらも同様の意味。そちらに関しては下記サイトが写真付きで紹介しているのでそちらをご参照のこと。

kw-note.com

参考リンク

HTTPヘッダのX-Forwarded-Forとは何か、そしてForwaredとは何かをざっくりまとめる

そもそもXがつくヘッダはどんなものなのか

別の記事でざっくり書いたのでそちらを参照

shinkufencer.hateblo.jp

X-Forwarded-Forとは

クライアントからレスポンス戻る際にロードバランサーなどの仲介する某かを通る場合がある。そのような場合は純粋に送信元IPを基準に考えると、もともとのクライアントのIPがわからなくなってしまう。

そこでHTTPヘッダに元のクライアントIPの情報を乗せるときに使われるヘッダが X-Forwarded-For である。

使われ方

フォーマットと意義

クライアントのIPから始まり、あとはクライアント起点で経由したプロキシのIPをカンマ区切りで追記していく形式

X-Forwarded-For: クライアントのIP, プロキシのIPその1, プロキシのIPその2 ...

こう記述することで、クライアントのIPと経由したプロキシのIPが順番も含めてわかる。

X-Forwarded-Forに増えるタイミング

プロキシにあたるものを一つしか挟まない場合は、クライアントのIPのみしか記録されない。そのため クライアントIPが記載されるのはX-Forwarded-For と勘違いされがち。

X-Forwarded-Forの歴史

これはRFCで標準化された仕様ではなく、Squidのキャシング/プロキシサーバで使われ始めて、それがデファクトスタンダードになったものだとされている。(ここに関しては原初が何の仕様だったのかまではたどることができなかった)

X-Real-IPとの違い

似たような拡張仕様に X-Real-IP ヘッダが存在するが、仕様としてはあまり他での利用が見かけられないがOracleのドキュメントには以下のような記述がある。

クライアントのIPアドレスを指定します。 ロード・バランシング・サービスの場合、クライアントは最後のリモート・ピアです。 - HTTP "X-"ヘッダー

X-Real−IPは純粋にクライアントのIPのみを記載する目的のヘッダの様子。

置き換えとなるRFCの仕様 Fowarded

デファクトスタンダードだった仕様に対し、RFCで明確に定められた仕様が Forwarded

RFC 7239 - Forwarded HTTP Extension

X-Forwarded-For と同列で語られるデファクトスタンダード仕様である X-Forwarded-Host (クライアントのホスト名), X-Forwarded-Proto (クライアントが利用しているHTTPのプロトコル,http or https) も格納できるフォーマットとなっている。

ヘッダなので偽装もできる

X-Forwarded-ForもForwardedもどちらもヘッダに付与するものなので偽装は容易にできる。そのため、インターネットに接する面ではあまり効力を発揮しない。そのため現在では内部ネットワークでのリクエストのやりとり経路を確認するためのヘッダとして使う、というのが最近の使い方のスタンダードだと思われる。

参考リンク

今回調査をしようと思ったきっかけのツイート

RSpec3でbe_trueとbe_falseはなくなり、be_truthyとbe_falsey(be_falsy)になった

変化の経緯がなるほどなーと思ったのでまとめる。

出典

Notable Changes in RSpec 3

解説

RSpec3のリリースノートいわく

RSpec 2 had a pair of matchers (be_true and be_false) that mirror Ruby's conditional semantics: be_true would pass for any value besides nil or false, and be_false would pass for nil or false. In RSpec 3, we've renamed these to be_truthy and be_falsey (or be_falsy, if you prefer that spelling) to make their semantics more explicit and to reduce confusion with be true/be false (which read the same as be_true/be_false but only pass when given exact true/false values).

和訳すると

RSpec 2には、Rubyの条件付きセマンティクスを反映するマッチャーのペア(be_trueとbe_false)がありました。be_trueはnilまたはfalse以外の値を渡し、be_falseはnilまたはfalseを渡します。 RSpec 3では、これらの名前をbe_truthyとbe_falsey(またはそのスペルが望ましい場合はbe_falsy)に名前を変更して、セマンティクスをより明確にし、be true / be falseとの混同を減らします(be_true / be_falseと同じように読み取りますが、正確なtrue / false値が与えられたときに渡します)。

和訳だけだとわかりづらいかもしれませんが、意図を汲み取ると以下の通り

  • RSpec2までは be_true は 「nilかfalse以外の値のとき」 be_false は 「nilまたはfalseのとき」というマッチャになっていた。
  • 上記の場合、be trueという「trueと同一である」という名前に反してtrueと合致しないものも判定していた
  • そのためRSpec3では挙動に合わせてマッチャ名を変更し be_truthybe_falsey/be_falsy にリネームを行った

もし本来の意味のbe true、つまり「trueと同一である」というのを調べたい場合は be マッチャでtrueか同一か調べればいいということになる。

expect(check_value).to be(true)

なお be(true) ではなく be だけにすると be_truthy と同じ挙動になるので気をつけること

余談

PHPは両方あるので紛らわしい(参考:いつから俺は、be_truthy/be_falseyの仕様を勘違いしていたのだ - type holyshared = Engineer

参考リンク