はじめに
前回はWorkersとD1の疎通確認をしました。
今回はPagesからWorkersを呼び出してデータを取得してみようと思います。
Pages準備
なんてことはない、ただ単にurlを指定するだけ。
Localでテストするときはlocalhost:8787で。
<template>
<div>
<h1>cloudflare testpage</h1>
<p>{{ helloWorld }}</p>
<p>{{ response }}</p>
</div>
</template>
<script setup lang="ts">
import axios from "axios";
const helloWorld = "Hello World!";
const fetchTest = async () => {
const response = axios
.get("https://[workers_url]/db-test")
.then((res) => {
return res.data;
})
.catch((err) => {
console.log(err);
});
return response;
};
const response = await fetchTest();
</script>
パラメータ付きリクエスト
フロントからパラメータ付きリクエストを送るのは簡単です。axiosのgetメソッドでパスパラメータで送るなりクエリで送るなりするだけです。
const fetchTest = async () => {
const response = axios
.get(`http://localhost:8787/db-test-with-params/${50}`)
.then((res) => {
return res.data;
})
.catch((err) => {
console.log(err);
});
return response;
};
axumではExtractorを使います
関数
#[worker::send]
async fn db_test_with_params(
State(state): State<Arc<Env>>,
Path(customer_id): Path<f64>,
) -> Json<Value> {
let db = state.d1("DB").expect("DB not found");
let statement = db.prepare("SELECT * FROM Customers WHERE customer_id = ?1");
let statement = statement
.bind(&[wasm_bindgen::JsValue::from_f64(customer_id)])
.expect("Failed to bind params");
let result = statement.all().await.expect("Failed to execute query");
let vec: Vec<Customers> = result.results().unwrap_or_else(|_| vec![]);
Json(json!(vec))
}
ルーター
fn router(env: Arc<Env>) -> Router {
Router::new()
.route("/", get(root))
.route("/db-test", get(db_test))
.route(
"/db-test-with-params/:customer_id",
get(db_test_with_params),
)
.with_state(env)
.layer(
CorsLayer::new()
.allow_origin(tower_http::cors::Any) // 現状面倒なのでAnyに設定してるだけです
.allow_methods([
Method::GET,
Method::POST,
Method::PUT,
Method::DELETE,
Method::OPTIONS,
]),
)
}
プリフライトリクエスト
で、insertなんですが、プリフライトリクエストを受信した段階でWorkersの処理が止まってしまいました。
corsの設定でプリフライトリクエストを受けられるようにしてあげましょう。今回足りなかったのはallow_headerの設定です。ACCEPTとCONTENT_TYPEを追加します。(AUTHORIZATIONは後々必要になる予定なので今のうちに入れておく)
ルーター
fn router(env: Arc<Env>) -> Router {
Router::new()
.route("/", get(root))
.route("/db-test", get(db_test))
.route(
"/db-test-with-params/:customer_id",
get(db_test_with_params),
)
.route("/db-insert-test", post(db_insert_test))
.with_state(env)
.layer(
CorsLayer::new()
.allow_origin(tower_http::cors::Any)
+ .allow_headers([AUTHORIZATION, ACCEPT, CONTENT_TYPE])
.allow_methods([
Method::GET,
Method::POST,
Method::PUT,
Method::DELETE,
Method::OPTIONS,
]),
)
}
Pages側は適当にボタンを付けてデータを追加/削除。処理後にデータを取得しなおして表示するようにして検証しました。
おわりに
次回は他のことをやる前に一度axumのエラーハンドリングを整えたいと思います。
その後認証、認可の勉強をしてログイン機能を作っていきたいですね。