【AWS】API Gateway マッピングテンプレートの設定方法
AWSのAPI Gatewayを介してlambda関数にHTTPヘッダやPOSTパラメータを渡す際の設定方法をメモ。
Lambda プロキシ統合にチェックを入れるだけでもパラメータを参照することはできますが、レスポンスに不要な情報が含まれてしまう為、そちらは利用せずにパラメータを渡したかった次第です。
ドキュメント
マッピングテンプレートのパラメータ名については、公式に一覧があります。 docs.aws.amazon.com
HTTPヘッダの設定方法
マッピングテンプレートを以下のように設定すれば、lambda関数からAuthorization
ヘッダやカスタムヘッダなどのHTTPヘッダを参照できます。
$util.escapeJavaScript
でエスケープしておくのがベターです。
HTTPヘッダは以下の記述のみで参照可能ですが、URLパラメータを参照するには「メソッドリクエスト」と「統合リクエスト」の欄から「URLクエリ文字列パラメータ」を指定する必要があります。
マッピングテンプレートの記載例
#set($allParams = $input.params()) { "params": { #foreach($type in $allParams.keySet()) #set($params = $allParams.get($type)) "$type": { #foreach($paramName in $params.keySet()) "$paramName": "$util.escapeJavaScript($params.get($paramName))" #if($foreach.hasNext),#end #end } #if($foreach.hasNext),#end #end } }
lambda関数の実装例
def lambda_handler(event, context): # `Authorization`ヘッダの取得 auth_header = event.get('params', {}).get('header', {}).get('Authorization', {}) # クエリパラメータ(GETのURLパラメータ)の取得 p = event.get('params', {}).get('querystring', {}).get('<パラメータ名>')
POSTパラメータの設定方法
POST時のリクエストパラメータのJSONは以下のように設定すると、lambda関数から参照可能となります。
マッピングテンプレートの記載例
#set($allParams = $input.params()) { "params": { "body": $input.json('$'), **←ココ** #foreach($type in $allParams.keySet()) #set($params = $allParams.get($type)) "$type": { #foreach($paramName in $params.keySet()) "$paramName": "$util.escapeJavaScript($params.get($paramName))" #if($foreach.hasNext),#end #end } #if($foreach.hasNext),#end #end } }
lambda関数の実装例
def lambda_handler(event, context): # jsonボディの取得 body = event.get('params', {}).get('body', {}) # json物理名を指定して、各パラメータを取得 p = body.get('<パラメータ名>')
【Python】toxで複数のPythonバージョンをテストする
Pythonのテストコードを実行する際に、複数のPythonバージョンで動作確認したい時があり、tox
の設定が便利だったので備忘メモ。
インストール
$ pip3 install tox
tox.ini
設定ファイルにlint
とtest
の設定を記載できます。
波括弧で複数バージョンの指定が可能です。
また、lint
のルールをflake8
の引数で変更可能です。
[tox] envlist = py3{7,8,9}-{lint,test},coverage-report [testenv] setenv = COVERAGE_FILE = .coverage.{envname} changedir = {toxinidir}/tests install_command = \ pip install \ --index-url=https://xxx.xxx.xxx:8000/xxx \ --trusted-host=xxx.xxx.xxx {opts} {packages} deps = pytest pytest-cov coverage mock commands = pytest --cov . {posargs} [lint] changedir = {toxinidir} skip_install = True deps = readme_renderer flake8 flake8-import-order pylint mock pytest commands = flake8 --import-order-style=pep8 --max-complexity=11 --max-line-length=120 <モジュールのディレクトリ名> (setup.py, testsなども指定可能) [testenv:py37-lint] skip_install = {[lint]skip_install} changedir = {[lint]changedir} deps = {[lint]deps} commands = {[lint]commands} [testenv:py38-lint] ...py37と同様 [testenv:py39-lint] ...py37と同様
実行方法
PRなどをトリガーに、CICDのパイプラインで各Pythonバージョンのコンテナを起動して、テストを自動実行するようにするとGood😎
#lint $ tox -e py38-lint # test $ tox -e py38-test
【Hive】beeline実行時のオプションについて
beeline
でHQLを実行する際のオプション指定方法について記載します。
--hiveconf
Hiveの設置をオプションで指定可能です。
$ beeline -u 'jdbc:hive2://xxx.co.jp:10000/default;...' --hiveconf hive.execution.engine=tez --hiveconf tez.queue.name=unfunded
-i <設定ファイル>
指定したいオプションが複数ある場合、--hiveconf
ではなく-i <設定ファイルのパス>
などのように別ファイルにまとめることが可能です。
セッションOPEN時の初期化処理に適用されるようです。
$ beeline -u 'jdbc:hive2://xxx.co.jp:10000/default;...' -i hiverc
hiverc
set hive.execution.engine=tez; set tez.queue.name=unfunded; set hive.exec.scratchdir=/user/xxx/tmp .....
-f <HQLファイル>
HQLファイルを実行したい場合、-f
で指定します。
$ beeline -u 'jdbc:hive2://xxx.co.jp:10000/default;...' -f /path/to/test.hql
--hivevar key1=value1
--hivevar
で変数展開が可能です。
複数ある場合は--hivevar key1=value1 --hivevar key2=value2 ...
のように続けて記載します。
$ beeline -u 'jdbc:hive2://xxx.co.jp:10000/default;...' -f /path/to/test.hql --hivevar yyyymmdd=20211101
バックグラウンド実行
HADOOP_CLIENT_OPTS
を設定する必要があります。
$ export HADOOP_CLIENT_OPTS="-Djline.terminal=jline.UnsupportedTerminal"
【React.js】makeStylesのスタイル指定方法
React.js(Next.js)で実装する際にmakeStyles
の利用方法を調べたので、忘れないようにメモ。
気になるものがあったら、順次追記していきます。
first-child
特に迷うことは無い。
const useStyles = makeStyles({ root: { '& div:first-child': { .... }, });
last-child
first-child
と同様。
const useStyles = makeStyles({ root: { '& div:last-child': { .... }, });
nth-child
スタイルを指定したい要素の中に&:nth-child(n)
という形式で定義する。
const useStyles = makeStyles({ root: { '&:nth-child(2)': { .... }, });
not
&:not(:~)
という形で指定可能。
const useStyles = makeStyles({ root: { '&:not(:nth-child(2))': { .... }, });
メディアクエリ
@media (min-width:1280px)
のような形で指定可能。
const useStyles = makeStyles({ root: { display: 'flex', '@media (max-width:1024px)': { display: 'block', .... }, });
【HiveQL】pyhiveとPrestoでテーブル操作
beeline
で実行していたクエリをpyhive
+ Presto
で再実装した際に書き方が違う部分があった為、備忘メモ。
LOCATIONを指定してテーブル作成
元のクエリはこちら。
CREATE EXTERNAL TABLE <テーブル名> (<カラム名> <型>, ...) ROW FORMAT DELIMITED FIELDS TERMINATED BY <区切文字、eg. '\t'> LOCATION <HDFSのパス>
pyhive
+ Presto
で書くと以下のようになる。
cursor = presto.connect(...).cursor() query = "CREATE TABLE test_table (id integer, note varchar) WITH (format='TEXTFILE', textfile_field_separator='\t', external_location='/path/to/hdfs')" cursor.execute(query) # fetchしないとテーブル作成後の処理が上手くいかない、エラーログも見れる print(cursor.fetchone()) cursor.execute('desc test_table') print(cursor.fetchone())
INSERT OVERWRITE
元のクエリ。
INSERT OVERWRITE <テーブル名> SELECT sum_a, b FROM ( SELECT SUM(a) AS sum_a, b FROM ( SELECT a, b FROM table1 UNION ALL SELECT a, b FROM table2 UNION ALL SELECT a, b FROM table3 ) t1 GROUP BY b ) t2 WHERE sum_a > {hivevar:a_param}
Presto
でINSERT OVERWRITE
は使用できません。
drop後にINSERT INTO
で作成する必要があります。
cursor = presto.connect(...).cursor() # drop cursor.execute('DROP TABLE IF EXISTS test_table') query = 'INSERT INTO test_table (sum_a, b) WITH tmp_tb AS ( SELECT SUM(a) AS sum_a, b FROM ( SELECT a, b FROM table1 UNION ALL SELECT a, b FROM table2 UNION ALL SELECT a, b FROM table3 ) GROUP BY b) SELECT sum_a, b FROM tmp_tb WHERE sum_a > %s' cursor.execute(query, (100,)) print(cursor.fetchall())
【Node.js】npmパッケージの脆弱性対応
CIで脆弱性チェックがエラーとなり、npm audit
以外の方法で応急処置をしたのでメモ。
修正後は要動作確認。
npm audit
まずは npm audit
等で検出されたパッケージのレポジトリを調べ、必要であれば package.json のバージョンを修正後にnpm audit fix
を実行。
node_modules や package-lock.jsonは削除した方が間違いが無さそう。
$ npm audit fix
npm-force-resolutions
npm audit fix
で解決しなかった場合に、どうにかして脆弱性のあるライブラリのバージョンを修正したい場合にnpm-force-resolutions
が使用できます。
package.jsonのscripts.preinstallにnpx npm-force-resolutions
、resolutions
にバージョンを修正したいパッケージ情報を記載します。
依存関係を無理やり変更させる為、使用する場合はバージョンアップ後の動作確認を良く行ってください。
{ "name": "xxxxx", "version": "0.0.1", "description": "", "scripts": { "preinstall": "npx npm-force-resolutions", # ここ "build": "..." }, "dependencies": { "vue": "^2.6.14", ... }, "dev-dependencies": { "vue-jest": "^4.0.1", ... }, "resolutions": { "ansi-regex": "5.0.1" # ここ } }
Dockerfileからbuildする際にエラーとなった為、.npmrcにunsafe-perm=true
を追記して解決しました。
unsafe-perm=true
で、パッケージスクリプト(preinstall)の実行時のUID/GID切り替えを抑制します。
# .npmrc registry=https://xxx.xxx.xxx/... unsafe-perm=true # ここ
【Python】urllibでプロキシ設定
urllib
で社内のプロキシサーバーを経由して外部接続という処理を実装しました。
外部接続先のAPIでBasic認証が必要で、少し詰まったのでメモ。
requests
モジュールだと、プロキシ設定 + 接続先でBasic認証が上手く動かなかった為、urllib
モジュールを使用しています。
上手いやり方などあれば、教えてください😊
実装
import os import base64 import json import urllib.request def exec_proxy_request(usename: str, passwd: str, token: str): user_pass = f'{usename}:{passwd}' header = { # アクセス先のBasic認証 'Authorization': f"Basic {base64.b64encode(user_pass.encode('utf-8')).decode('utf-8')}" # プロキシサーバの認証情報、必要に応じて 'Proxy-Authorization': f'Bearer {token}' } req = urllib.request.Request('<アクセス先URL>', headers=header, method='GET') # プロキシの設定 req.set_proxy('xxx.proxy.jp', 'http') req.set_proxy('xxx.proxy.jp', 'https') with urllib.request.urlopen(req) as res: status_code = res.getcode() res_body = res.read().decode('utf-8') if not status_code == 200: raise Exception(res_body) json_data = json.loads(res_body) return json_data