2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

某 f 社のアドベントカレンダーAdvent Calendar 2021

Day 10

Deno + oak で任意のレスポンスヘッダでレスポンスを返すサーバーをサクっと立てた

Last updated at Posted at 2021-12-09

はじめに

この記事は 某社の Advent Calendar 10日目の記事です。
こんにちは。 mirko です。

この記事で書くこと

この記事では、 Deno と oak で任意のレスポンスヘッダでレスポンスを返すサーバーを立てる方法について解説します。
Deno と oak (と CORS 対応のために必要になる cors ライブラリ) のバージョンは以下で確認しています。

名前 バージョン
Deno 1.16.0
oak 10.0.0
cors 1.2.2

なぜ作ったか

ある API エンドポイントを叩いた時に Content-Disposition ヘッダに attachment; filename="filename.txt" のように入れるのでそれをパースしてフロントエンドで指定した filename でファイルダウンロードできるようにしておいてください、となったが、諸般の事情でバックエンドができる前にフロントエンドを着手したかったので。(また、代わりに使えそうなフリーのAPIがうまいこと見つけられなかったので)

実装

ts ファイルを書く

server.ts
import { Application } from "https://deno.land/x/oak@v10.0.0/mod.ts";
import { oakCors } from 'https://deno.land/x/cors@v1.2.2/mod.ts';

const app = new Application();

app.use(oakCors());
app.use((ctx: any) => {
  ctx.response.body = 'sample response body';
  ctx.response.headers.set('Content-Type', 'text/plain');
  ctx.response.headers.set('Access-Control-Expose-Headers', '*');
  ctx.response.headers.set('Content-Disposition', 'attachment; filename="filename.txt"');
});

await app.listen({ port: 8000 });

実行する

deno run --allow-net server.ts

これだけ。

curl を叩くと、以下のようなレスポンスが得られます。

$ curl -v http://localhost:8000
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< access-control-allow-origin: *
< access-control-expose-headers: *
< content-disposition: attachment; filename="filename.txt"
< content-type: text/plain
< content-length: 20
< date: Fri, 03 Dec 2021 15:41:43 GMT
<
* Connection #0 to host localhost left intact
sample response body* Closing connection 0

解説

HTTP サーバーを立てる

// 基本的には oak のドキュメントを通りで恐縮です。

以下のように Application class をインポートします。

import { Application } from "https://deno.land/x/oak@v10.0.0/mod.ts";

Application class を初期化したら

const app = new Application();

.use() でリクエストを指定しています。

app.use((ctx: any) => {
  ctx.response.body = 'sample response body';
  ctx.response.headers.set('Content-Type', 'text/plain');
  ctx.response.headers.set('Access-Control-Expose-Headers', '*');
  ctx.response.headers.set('Content-Disposition', 'attachment; filename="filename.txt"');
});

最後に listen するポートを指定します。

await app.listen({ port: 8000 });

今回は任意のレスポンスヘッダでレスポンスを返したかったので上記のように書いていますが、任意のレスポンスボディを返すのみでしたら、以下のコードだけでも動きます。

// https://deno.land/x/oak@v10.0.0 より引用
import { Application } from "https://deno.land/x/oak/mod.ts";

const app = new Application();

app.use((ctx) => {
  ctx.response.body = "Hello World!";
});

await app.listen({ port: 8000 });

CORS 対応をする

実は上記部分だけでも curl -v http://localhost:8000 で意図したレスポンスを得られますが、ローカル開発環境が localhost ではない場合 CORS エラーとなります。
そのため、以下のように CORS 対応をしました。

cors モジュールを import します。

import { oakCors } from 'https://deno.land/x/cors@v1.2.2/mod.ts';

公式の例 を参考に、今回は複雑な route も定義していないので、シンプルに oakCors を有効化します。

app.use(oakCors());

これで CORS 対応は完了しました。はやい!

書いてみた感想

  • めちゃくちゃサクっと書きたいものが書けた
    • 環境構築に時間をかけず気持ちよく TypeScript が書けていい感じ
  • 配布ライブラリに型が書いてあるのもサクっと書く助けになってくれた

これからも公私共に Deno を使っていきたいと思いました!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?