コピペコードで快適生活

明日使えるソースを自分のために

CentOSでルート証明書はどのように配置されているか

  • ca-certificates
    • MozillaFoundationが選定したCA証明書のセット
    • yum install ca-certificates でインストールされる
    • インストール場所は、rpm -Vv ca-certificates で確認できる
    • ルート証明書/usr/share/pki/ca-trust-source 直下に配置される。
    • ca-certificatesをupgradeすることで最新の証明書に更新される
  • ルート証明書を自分で追加/削除する
  • update-ca-trustコマンド
    • ca-certificates に含まれるコマンド
    • ca-certificatesに元から含まれる証明書と、自身で配置した証明書をバンドルして出力する
    • 出力先は /etc/pki/ca-trust/extracted 以下
    • 基本的にアプリケーションは、これで出力された証明書を参照する。
      • Rubyはこれで確認できる OpenSSL::X509::DEFAULT_CERT_FILE
      • 後方互換
        • かつて(CentOS6以前?)は以下にバンドルされた証明書があった
          • /etc/pki/tls/cert.pem
          • /etc/pki/tls/certs/ca-bundle.crt
          • /etc/pki/tls/certs/ca-bundle.trust.crt
        • CentOS7以降ではこれらのパスは残されていて、/etc/pki/ca-trust/extracted/* へのシンボリックリンクとなっている
          • かつての配置場所を参照するアプリケーションとの互換性のため
            • /etc/pki/tls/cert.pem -> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
            • /etc/pki/tls/certs/ca-bundle.crt -> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
            • /etc/pki/tls/certs/ca-bundle.trust.crt -> /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt
        • LINKS

FTPのメモ

FTP

  • 2つのコネクションがある
    • コントロールコネクション: コマンドの制御用
    • データコネクション: データの送受信
  • anonymousモード
    • データのダウンロード専用
    • ログイン情報なしで利用できる
  • 転送モード
    • アスキーモード: テキスト送受信用。改行コードと文字コードが自動で変換される(いまは利用しない)
    • バイナリモード: なんでもOK
  • 接続モード
    • アクティブモード
      • データコネクション
        • サーバからクライアントに通信して確立する
        • ポート番号として20番を利用する
    • パッシブモード
      • データコネクション
        • クライアントからサーバに接続して確立する
        • ポート番号は毎回ランダムに決まる
          • ポート番号はコントロールコネクションで通知される
      • 普通はこっち使う
    • 共通

FTPS

  • SSL/TLSを利用してFTPで暗号化通信を実現するプロトコル
  • 2つの通信モード
    • Explict(明示的)モード
      • 21ポートで通信する
      • 最初は平文通信
      • クライアントのAUTHコマンド実行から通信が暗号化される
    • Implicit(暗黙的)モード
      • FTPとは別のポート(989or990)で最初から暗号化通信を行う

links

tcpdumpの基本的な使い方

macでのインストール

brew install tcpdump

よく使いそうなコマンド

# パケットの中身をアスキー文字で出力する
sudo tcpdump -A

# インターフェース指定
sudo tcpdump -i eth0

# ファイル出力
sudo tcpdump -w ~/tcp.log

# 送信元IP指定
sudo tcpdump src host 192.168.0.10

# 送信先IP指定
sudo tcpdump dst host 8.8.8.8

# 送信元port指定
sudo tcpdump src port 80

# 送信先port指定
sudo tcpdump dst port 443

# andでIP,portの組み合わせ指定
sudo tcpdump dst port 53 and dst host 8.8.8.8

RSpecで既存のクラスをモックに差し替える

本来はDependencyInjectionでやるべきかもだけど。 そうもいかないケースもあるわけで。

# 既存クラス
let(:api_client) { ::MyApp::ApiClient }
let(:api_response) { double('api_response', status: 200) }

# post_xxxメソッドを上書きして、api_responseを返す
allow(api_client).to receive(:post_xxx).and_return(api_response)

# post_xxxメソッドを上書きして、例外をraiseする
allow(api_client).to receive(:post_xxx).and_raise(::MyApp::MyApp::BadRequest)

composerで使えるライブラリを作ってみた

composerで使うライブラリを作ったことがなかったので、試しに作ってみた。

作ってみる

ソースはこんなかんじで
https://github.com/kinosuke01/convertible-romaji

作るときのコマンドメモ

# コンテナ起動してログイン
docker compose up
docker compose exec php /bin/bash

# composer.pharのインストール
curl -s http://getcomposer.org/installer | php

# composer.jsonの内容に従って
# ライブラリをインストール&autoload設定
php composer.phar install

# autoloadの更新だけ
composer dump-autoload

# テスト実行
vendor/bin/phpunit ./tests/

# composer.jsonのチェック
php composer.phar validate

# タグうち
git tag v0.0.1
git push origin v0.0.1

packagistに登録する

namaspace

よくわかってなかったのでメモ。

  • ライブラリの名前空間ベンダー名\ライブラリ名\クラス が一般的っぽい。

  • 定義の書き方

namespace Kinosuke01\ConvertibleRomaji;
class ConvertibleRomaji
{
// 略
}

// Rubyで書くならこんな
// module Kinosuke01::ConvertibleRomaji
//   class ConvertibleRomaji
//   end
// end
  • 呼び出し方
use Kinosuke01\ConvertibleRomaji\ConvertibleRomaji
// ↑は以下の略式
// use Kinosuke01\ConvertibleRomaji\ConvertibleRomaji as ConvertibleRomaji

// クラスが名前空間なしで使えるようになる。
$romaji = new ConvertibleRomaji('irohani');

作ったライブラリを使ってみる

docker-composer.yml作る

services:
  php:
    image: webdevops/php-apache-dev:7.4
    volumes:
      - "./:/var/app"
    ports:
      - "80:80"
    tty: true

コンテナ起動 & ログイン

docker compose up
docker compose exec php /bin/bash

composer.json作る

{
    "require": {
        "kinosuke01/convertible-romaji": "0.0.*"
    }
}

composer installする

# コンテナ内で実行
composer install

test.php作る

<?php
require 'vendor/autoload.php';

use Kinosuke01\ConvertibleRomaji\ConvertibleRomaji;

$romaji = new ConvertibleRomaji('irohanihoheto');
echo $romaji->toHiragana(); // いろはにほへと
echo $romaji->toKatakana(); // イロハニホヘト

test.phpを実行

# コンテナ内で実行
php test.php
# => いろはにほへとイロハニホヘト

CSSをあてる要素をどう分割するか

設計手法

責務をどのように分割するか、名前をつけるか という点でいくつかの代表的なアプローチがある。

  • OOCSS
  • BEM
  • SMACSS
  • FLOCSS

SMACSS

以下のように責務を分割する。

  • Base
    • ベースとなるデフォルトのスタイルを定義する
  • Layout
    • ページを構成するブロック要素のスタイルを定義する
    • プレフィックスとして layout-l- が使われる。
  • Module
    • 再利用可能なスタイルを定義する
  • State
    • レイアウトやモジュールの状態を表すスタイル
    • 例 is-active, is-enable
  • Theme
    • 色、形状、レイアウト、書体などの見た目や振る舞いを表すスタイル
    • プレフィックスとして theme- が使われる。

https://murashun.jp/article/programming/css/css-design.html#chapter-5

FLOCSS(フロックス)

以下のように責務を分割する。

  • Foundation
    • スタイルの初期化を行う
    • 例: reset.css
  • Layout
    • ページを構成するブロック要素のスタイルを定義する
    • 例: header, main, sidebar, footerなど
  • Object
    • Component
      • 使い回せる要素を定義する。
      • 例: btn要素
    • Project
      • プロジェクト固有のスタイルを定義する。
      • (よくわからない)
    • Utility
      • Component,Project以外の色々
      • 例: clearfix, .mbs { margin-bottom: 10px; } など

要素名にはプレフィックスを付けることが推奨されている

Component - .c-*
Project - .p-*
Utility - .u-*

参考:https://github.com/hiloki/flocss

tips

子孫セレクタは少ない方が高速

CSSは右から左に読み込まれるため、子孫セレクタの多いこっちより

.wrapper .main .list .row

少ないこっちのほうが、探し出す要素の数が少ないため高速

.list-row

idやclassには要素名をつけないほうが高速

li.list より .li-listのほうが高速

責務で要素の名前をつける

スタイルの内容やコンテンツ名で名前をつけない

# 赤じゃなくなったら、class名を全部書き換える必要あり。
.coler-red

# 見積もり表以外でも使いたくなったとき、class名を全部書き換える必要あり。
.mitsumori-table

隙間をとるマージンについて

  • 上下の要素間の隙間を空ける時は、margin-bottom にだけ適用する
  • 左右の要素間の隙間を空ける時は、margin-right にだけ適用する

参考:https://qiita.com/tera_shin/items/af90aeba49f93c76bd9e

ReactHooksを使ってみる

最近のReactでは関数コンポーネント&ReactHooksを使うのが主流らしい。
キャッチアップしたところ、state管理がコンポーネントからキレイに分離できてよさそうだった。

index.tsx

import * as React from "react";
import * as ReactDOM from "react-dom";
import Omikuji from "./Omikuji";

let element: JSX.Element = <Omikuji name="kinosuke01"/>;
let dom: HTMLElement = document.getElementById('root');
ReactDOM.render(element, dom);

Omikuji.tsx

import React from 'react';
import useOmikuji from './useOmikuji';

interface Props {
  name: string,
};

interface State {
};

export default function Omikuji(props: Props) {
  // state管理を行う処理を、関数コンポーネントに組み込む。
  let [result, updateResult] = useOmikuji();

  let message: string = '今日の運勢を占います!';
  let buttonText: string = '占う!';
  if (result) {
    message = `${props.name}さんの今日の運勢は「${result}」です!!`;
    buttonText = 'もう一度占う!';
  }

  return (
    <div>
      <p>{message}</p>
      <button onClick={() => updateResult()}>{buttonText}</button>
    </div>
  )
};

useOmikuji.ts

import { useState, useEffect } from 'react';

//
// 関数コンポーネントにstate管理を組み込む関数。
// state管理をコンポーネントから分離できる。
// 複数のコンポーネントで使い回すことができる。
// setResultやuseEffectを使うことで実現。
//
export default function useOmikuji(): [string, Function] {
  // result -> state.result
  // setResult -> setState({result: xxx});
  // に対応するイメージ
  // useStateの引数は、対象stateの初期値
  const [result, setResult] = useState(null);

  function predict(): string {
    let i: number = Math.floor(Math.random() * 10 % 5);
    let list: Array<string> = ['大吉', '吉', '中吉', '小吉', '凶'];
    return list[i];
  }

  function updateResult(): void {
    setResult('占い中...');
    setTimeout(() => {
      let predictResult: string = predict();
      setResult(predictResult);
    }, 1000);
  }

  // useEffectには、
  // componentDidMount, componentDidUpdate の
  // タイミングで呼びたい関数を渡す
  useEffect(() => {
    console.log(`「${result}」を取得しました。`);

    // 戻り値には、componentWillUnmountの
    // タイミングで呼びたい関数を渡す
    return (): void => {
      console.log('さよなら');
      return;
    };
  });

  return [result, updateResult];
}

参考