わいの日記

ありがちエンジニアブログ

DNSのまとめメモ

先日、DNSでめっちゃ頭悩まされたので復習とメモがてら


DNS(Domain Name System)

DNSサーバは下記の2種類から構成される

  • ネームサーバー(DNSコンテンツサーバー or 権威DNSサーバー とも呼ばれる)

  -> ドメインIPアドレスを結びつける

  • フルリゾルバ(DNSキャッシュサーバ or フルサービスリゾルバ とも呼ばれる)

  -> ドメインからIPアドレスを調べてくれる(一定期間は、調べた結果をキャッシュしてくれる)


個人のPCにはスタブリゾルバってのがある
Macだと/etc/resolv.confに設定されている

cat  /etc/resolv.conf // nameserverがresolver

その中身
f:id:exhikkii:20181123153234p:plain

それぞれのIPを調べたらGoogleDNSサーバみたい

whois 8.8.8.8
whois 4.4.4.4


ここで名前解決の流れを整理しとく

ドメインでwebページを見ようとする

  • > スタブリゾルバがフルリゾルバに問い合わせ
  • > フルリゾルバがルートネームサーバに問い合わせる
  • > ルートネームサーバが返り値を元に、ネームサーバにipアドレスが取得できまで問い合わせる
  • > ipアドレスが取得できたら、webサーバーに問い合わせ

リソースレコード

ドメインIPアドレスの結びつきのこと

A

ドメインIPアドレス

// ドメインのAレコード(IPアドレス)の調べ方

dig ドメイン名 a +short

// IPアドレスの持ち主を調べる

whois IPアドレス

NS

ドメインのゾーンを管理するネームサーバ

// NSの調べ方

dig ドメイン名 ns +short

MX

ドメインのメール受信サーバ

// MXの調べ方

dig ドメイン名 mx +short

googleのメールサーバ
先頭の10とか30はプリファレンス値 といってメールサーバが複数台ある場合の優先度を表す

f:id:exhikkii:20181123201210p:plain

これでaレコードを調べれば、IPアドレスまで調べられる

MXレコードがない場合は、
AレコードのIPアドレスにメールを送ろうとする

TXT(SPF(Sender Policy Framework))

ドメインのメール送信サーバ
用途:メールの送信元が詐称されていないか調べられる
そのドメインで、メール送信が許可されているサーバのリストが書かれている

// SPFの調べ方

dig ドメイン名 txt +short

SOA

ドメインのゾーン管理情報

PTR

IPアドレスからドメインを逆びきできる

// PTRの調べ方

dig -x IPアドレス +short

CNAME

ドメインの別名のリソースレコードの参照先
ドメイン名のCNAMEレコードのドメインのAレコードを探しに行く
これをIPアドレスが見つけられるまで繰り返す、最終的に見つかったものがcanonical name(正式名)

// CNAMEの調べ方

dig ドメイン名前 cname +short

CNAMEで先日ハマったところ

CNAMEを設定すると、他のレコードを設定できない
例えば下みたいなのが無理

waichan.work IN CNAME www.waichan.work
waichan.work IN NS hoge.example.com

awsのRoute53ではそもそも設定すら無理

ZONE APEX(サブドメインを含まないドメイン)はCNAMEを使えない
そもそもZONE APEXはNSレコードとSOAレコードがあるから。。。

Route53のAliasレコードならZONE APEXでも設定可能
しかも名前解決が1回で済むという機能も!
こうじゃなく CNAME -> A-> IP
こう Alias -> IP


しっかりawsもだけど、インフラの基本勉強しないと

AdonisJS クエリパラメータの取得の仕方

タイトルまんま

以下はhttp://localhost:3333?hoge=testにアクセスするとする

start/routes.js

Route.get('/',  ({ request }) => {
  console.log('query parameter', request.input('hoge’)
});

コンソールを確認する
f:id:exhikkii:20181121215252p:plain

クエリがしっかり取れてる

AdonisJSでLaravel(5.1)のチュートリアルしてみた

AdonisJSの紹介

adonisjs.com

MVCに則ったJavaScriptフレームワークです

PHPフレームワークの1つLaravelにめっちゃそっくりです

こちらを紹介する目的:JavaScripter人口増えたらいいな
PHPerがNode.jsに入る時にexpressだと取っつきにくいと思うんです
自分はめっちゃ苦労しました
それに比べたらAdonisJSはMVCなのでめっちゃ取っつきやすいと思います
Ruby on Rails使っている人にとっても学びやすいフレームワークかなと思います

そこでLaravelにそっくりということでLaravelのチュートリアルをAdonisJSでやってみます
基本のタスクリスト 5.1 Laravel


では早速
(AdonisJSのversionは4.1です)

// validateファイルの作成

npm i --global @adonisjs/cli

// プロジェクト作成

adonis new laravel-tutorial

ディレクトリ構造です
migrationsがあったりroutes.jsがあったりでLaravel使いには馴染みのある構成ですね!
f:id:exhikkii:20181119174616p:plain


// devサーバー立ち上げ

cd laravel-tutorial
adonis serve --dev

動作確認 localhost:3333にアクセス
f:id:exhikkii:20181119174811p:plain

今回は簡単のためdatabaseにsqlite3を使います
// sqlite3を追加

yarn add sqlite3

早速tasksテーブルを作ります
// tasksテーブルのマイグレーションファイル作成

adonis make:migration tasks

// 上記のコマンドのあと、「Choose an action Create table」この選択肢を選んでください

出来上がったmigrationファイル修正
upやdownの書き方もLaravelおなじみですね

'use strict'

/** @type {import('@adonisjs/lucid/src/Schema')} */
const Schema = use('Schema')

class TasksSchema extends Schema {
  up () {
    this.create('tasks', (table) => {
      table.increments()
      table.string('name') // この1文をを追記
      table.timestamps()
    })
  }

  down () {
    this.drop('tasks')
  }
}

module.exports = TasksSchema

// migration実行

adonis migration:run

// Taskモデルの作成

adonis make:model Task

下記の内容のmdoelクラスが作られる
// app/Models/Task.js

'use strict'

/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
const Model = use('Model')

class Task extends Model {
}

module.exports = Task

次にルーティングの設定
// start/routes.js

'use strict';

const Route = use('Route');
const Task = use('App/Models/Task');

Route.get('/', async ({ view }) => {
  const tasks = await Task.all();
  console.log('tasks', tasks.toJSON())
  return view.render('tasks', { tasks: tasks.toJSON() });
});

Route.post('/task', async ({request, response}) => {
  await Task.create(request.only(['name']));
  return response.redirect('/');
}).validator('Task'); // 後述するvalidatorを指定する

Route.delete('/task/:id', async ({params, response}) => {
  const task = await Task.find(params.id);
  await task.delete();
  return response.redirect('/');
});

次はview
AdonisJSはedgeテンプレートを採用しています
これもまたLaravelのbladeファイルの記法とそっくり
レイアウトファイルから作ります
// view/layouts/app.edge

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Laravel Tutorial with AdonisJs</title>
  // bootstrapをcdnで読み込む
  {{ style('https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u') }}  
</head>
<body>
  <div class="container">
    <nav class="navbar navbar-default">
    </nav>
  </div>
  @!section('content') // section前の! を忘れないで
</body>
</html>

さらにtask.edge
// resources/views/task.edge

@layout('layouts.app')  //レイアウトファイルを指定

@section('content') // レイアウトファイルの@!section('content')に埋め込まれる
<div class="panel-body">
  @include('common.errors') // partialファイル(resources/views/common.errors)を読み込む
  <form action="/task" method="POST" class="form-horizontal">
    {{ csrfField() }} // CSRF「トークン」を生成
    <div class="form-group">
      <label for="task" class="col-sm-3 control-label">Task</label>
      <div class="col-sm-6">
        <input type="text" name="name" id="task" class="form-control">
      </div>
    </div>

    <div class="form-group">
      <div class="col-sm-offset-3 col-sm-6">
        <button class="btn btn-default">
          <i class="fa fa-plus"></i> タスク追加
        </button>
      </div>
    </div>
  </form>
</div>
@if(tasks.length > 0)
<div class="panel panel-default">
  <div class="panle-heading">
    現在のタスク
  </div>
  <div class="panel-body">
    <div class="table table-striped task-table">
      <thead>
        <th>Task</th>
        <th>&nbsp;</th>
      </thead>
      <tbody>
        @each(task in tasks) // tasksを一覧表示するためのループ
          <tr>
            <td class="table-text">
              <div>{{ task.name }}</div> // taskの名前を表示
            </td>
            <td>
    // deleteメソッドにするときはactionの末尾に_method=DELETEをつける
              <form action="/task/{{task.id}}?_method=DELETE" method="POST">
                {{ csrfField() }}
                <button>タスク削除</button>
              </form>
            </td>
          </tr>
        @endeach
      </tbody>
    </div>
  </div>
</div>
@endif
@endsection

// resources/views/common/errors.jsの作成

@if(hasErrorFor('name')) nameをkeyにするflashメッセージがあるか確認
  <div>
    <strong>おや?何かがおかしいようです!</strong>
    <br><br>
    <p>{{ getErrorFor('name') }}</p> // あれば表示
  </div>
@endif

最後にバリデーション
バリデーションは別途設定する必要があります
// validationの追加

adonis install @adonisjs/validator

// start/app.jsの修正してバリデーションを使えるようにする

const providers = [
  '@adonisjs/framework/providers/AppProvider',
  '@adonisjs/framework/providers/ViewProvider',
  '@adonisjs/lucid/providers/LucidProvider',
  '@adonisjs/bodyparser/providers/BodyParserProvider',
  '@adonisjs/cors/providers/CorsProvider',
  '@adonisjs/shield/providers/ShieldProvider',
  '@adonisjs/session/providers/SessionProvider',
  '@adonisjs/auth/providers/AuthProvider',
  '@adonisjs/validator/providers/ValidatorProvider' // ここを追加してください
]

// validateファイルの作成

adonis make:validator Task

// app/Validators/Task.js

'use strict'

class Task {
  // バリデーションのルールを決める
  get rules () {
    return {
      name: 'required|max:30'
    }
  }

  // エラーメッセージの設定
  get messages() {
    return {
      'required': '{{ field }} is required.',
      'max': 'max 30 characters'
    }
  }

  // sessionにエラーメッセージを設定
  async fails(error) {
    this.ctx.session.withErrors(error)
      .flashAll();

    return this.ctx.response.redirect('back');
  }
}

module.exports = Task

実際のコードを下記のリポジトリに置いています
github.com

このチュートリアルではcontrollerなども利用していないのですが、
AdonisJSにもちゃんとcontrollerがあります

他にもIOCなど類似の機能はあるのでぜひ公式リファレンスをご覧ください

個人的にはAdonisJSはバックエンドのapiサーバーをして利用する際に力を発揮すると考えます
expressに比べcorsなど設定が楽だと思います(個人比)
(adonis newする際にapiモードを指定すればviewが作成されなくなります)
またapiの方も紹介しようと思います

公式ドキュメントが一番信用できる

一番に参照すべきなのはやはり公式ドキュメントだなと思いました

JavaScriptではべき乗は従来はMath.powを使います

// 2の10乗
Math.pow(2,10) // 1024

es2016から下記のように書けます

// 2の10乗
2 ** 10 // 1024

JavaScriptのべき乗演算子に関して調べいたのですが、
その時にwikibooksというサイトを参照しました

JavaScript/演算子 - Wikibooks

下記のスクショをご覧ください

べき乗(**)がない!?

f:id:exhikkii:20181114200432p:plain

(修正はしておきました)

f:id:exhikkii:20181114200742p:plain

やはりMDNが最強ですね
developer.mozilla.org

キータだったり個人ブログでもわかりやすい記事や勉強になる記事が多いのも事実だと思います
(実際、私もかなりお世話になっております)

ただ、初めはや公式ドキュメントを参照するように心がけております

なんやかんや公式が一番信用できますからね

私がメンターを務めるTECH PLAY Academyでも
公式ドキュメントをなるべく参照するように生徒さんにお伝えしています

techplay.jp

あの及川卓也さんも以前イベントでやはり参照すべきは公式だと以前仰っていました

techplay.jp


ということで、公式が最強だねって話でした

書籍としてはこちらをリファレンス代わりに使っております

Rails復習始めたよ(改訂4版 基礎 Ruby on Rails)

なつかしい

 

ああ、こんな書き方やったな

基礎的な内容で復習にはちょうどよかった

不満をあげるとすれば、サンプルアプリのデザインがとてもダサい

 

あとActive Storageなんて機能ができてたんやね

いい機能なだけにしっかり解説して欲しかったな

ターゲット読者層を考えると、

awsとかgcpの各画面をスクショとか載せながらじゃないと、

多分設定に四苦八苦すると思う

railsが主眼の本だから仕方ないのかもしれないけどね

 

もう少しrails復習しよう

 

 

『プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで 』よんだよ

とても良い本だ

 

テスト駆動開発を使って、

手を動かしながら学べる点がとてもよい

 

具体的な使い道も紹介しているので、学んだ文法の使い道もイメージしやすい

 

思い返せば、

2016年末にwebエンジニアになりたいなって思って、

プログラミングスクールなDIVE INTO CODEでRubyを学んだ

 

diveintocode.jp

 

そんな折に

Rubyやりたいの?ならうちにおいでよ」とses企業に誘われ、

入社する、phpやることになる なんでや

 

しばらくして尊敬するエンジニアから

「Vue.jsいいっすよ」って言われ、やってみる ハマる

 

それからJSに夢中になって、

いつのまにかTECH PLAY Academyのメンターをすることに

 

techplay.jp

 

紆余曲折あったけど、ようやくRubyのキャリア積めそう

わいはやるぞ〜

 
 

Builder Pattern [Design Pattern]

タイトルまんま

欲しい状態のArticleをメソッドチェーンで作成できるのでとても便利ですね!

builderクラスではconstructorで初期化
各メソッドではプロパティを設定し、自分自身(this)をreturnする
最後にbuildメソッドで欲しいクラス(ここでいうArticle)に自分自身を突っ込むで初期化するって流れですね!

//Article
class Article {
    constructor(builder) {
        this.title = builder.title;
        this.category = builder.category;
        this.isPublic = builder.isPublic
        this.isFree = builder.isFree;
        this.price = builder.price || 0;
    }
    render(){
        console.log(this)
    }
}

// builder
class ArticleBuilder {
    constructor(title, category){
        this.title = title;
        this.category = category
        this.isPublic = false
        this.isFree = true
    }
    makePublic(){
        this.isPublic = true;
        return this;
    }
    makePaid(price){
        this.isFree = false;
        this.price = price;
        return this;
    }
    build(){
        return new Article(this)
    }
}

const firstArticle = new ArticleBuilder('First Article', 'News').makePaid(100).makePublic().build();
const secondArticle = new ArticleBuilder('Second Article', 'Music').build()
firstArticle.render()
secondArticle.render()

jsfiddleに書いておきました
consoleで結果が見れるはずです

jsfiddle.net