11
7

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 5 years have passed since last update.

TypeScript: node-http-proxyを用いリクエスト/レスポンスを書き換えるリバースプロキシを作る方法

Last updated at Posted at 2019-09-24

本稿では、node-http-proxyを使い、TypeScriptでプログラマブルなリバースプロキシを作る方法を紹介する。

本稿のゴール

HTTPリクエストやレスポンスの内容を書き換えるリバースプロキシをTypeScriptで書けるようになる。

node-http-proxy とは

node-http-proxyは、プログラマブルなHTTPプロキシライブラリで、WebSocketもサポートしている。リバースプロキシやロードバランサを実装するのに向いている。

node-http-proxyをインストールする

yarn add http-proxy
yarn add -D @types/http-proxy

最も単純なリバースプロキシを実装する

ここでは一番シンプルな形でリバースプロキシを実装してみる。

import http, {IncomingMessage, ServerResponse} from 'http'
import httpProxy from 'http-proxy'

// HTTPサーバ
http.createServer((req: IncomingMessage, res: ServerResponse): void => {
    res.writeHead(200, {'Content-Type': 'text/plain'})
    res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, null, 2))
    res.end()
}).listen(9000)

// プロキシサーバ
httpProxy.createProxyServer({target: 'http://127.0.0.1:9000'}).listen(8000)

このサンプルコードでは、次のことをする。

  • プロキシサーバをポート8000で起動する。
  • HTTPサーバをポート9000で起動する。
  • プロキシサーバはHTTPサーバにリクエストを転送する。
  • プロキシサーバはリクエストやレスポンスを変更したりはしない。

この実装のプロキシサーバに次のHTTPリクエストを送ると、

GET /foo/bar HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8000
User-Agent: HTTPie/1.0.2


下記のとおりのレスポンスが来る:

HTTP/1.1 200 OK
connection: close
content-type: text/plain
date: Tue, 24 Sep 2019 07:42:20 GMT
transfer-encoding: chunked

request successfully proxied!
{
  "connection": "close",
  "accept": "*/*",
  "accept-encoding": "gzip, deflate",
  "user-agent": "HTTPie/1.0.2",
  "host": "localhost:8000"
}

リクエストやレスポンスを書き換えるリバースプロキシを実装する

ここでは、HTTPリクエストやHTTPレスポンスを書き換えるロジックを持ったリバースプロキシを実装する。下記コードがその実装例の完成形になる。

import http, {ClientRequest, IncomingMessage, ServerResponse} from 'http'
import httpProxy from 'http-proxy'

// HTTPサーバ
http.createServer((req: IncomingMessage, res: ServerResponse): void => {
    res.writeHead(200, {'Content-Type': 'text/plain'})
    res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, null, 2))
    res.end()
}).listen(9000)

// プロキシサーバ
const proxy = httpProxy.createProxyServer({target: 'http://127.0.0.1:9000'})

// HTTPリクエストの書き換え
proxy.on('proxyReq', (proxyReq: ClientRequest): void => {
    proxyReq.setHeader('X-Proxy', 'special header for request')
})

// HTTPレスポンスの書き換え
proxy.on('proxyRes', (proxyRes: IncomingMessage): void => {
    proxyRes.headers['X-Proxy'] = 'special header for response'
})

proxy.listen(8000)

このサンプルコードの要点をかいつまんで説明する。

まず、HTTPリクエストを書き換えるためには、proxyReqイベントのコールバックを実装する。この実装例では、HTTPサーバにリクエストを転送する前に、X-Proxyヘッダをセットするロジックにしている。

// HTTPリクエストの書き換え
proxy.on('proxyReq', (proxyReq: ClientRequest): void => {
    proxyReq.setHeader('X-Proxy', 'special header for request')
})

次に、HTTPレスポンスを書き換えるロジックは、proxyResイベントのコールバック関数として実装する。例では、HTTPサーバから返されたレスポンスに、X-Proxyヘッダを追加するロジックになっている。

// HTTPレスポンスの書き換え
proxy.on('proxyRes', (proxyRes: IncomingMessage): void => {
    proxyRes.headers['X-Proxy'] = 'special header for response'
})

このサンプルコードで起動したプロキシサーバに次のようなHTTPリクエストを送信すると、

GET /foo/bar HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: localhost:8000
User-Agent: HTTPie/1.0.2


下記のようなレスポンスが返ってくる:

HTTP/1.1 200 OK
X-Proxy: special header for response
connection: close
content-type: text/plain
date: Tue, 24 Sep 2019 08:05:48 GMT
transfer-encoding: chunked

request successfully proxied!
{
  "connection": "close",
  "accept": "*/*",
  "accept-encoding": "gzip, deflate",
  "user-agent": "HTTPie/1.0.2",
  "host": "localhost:8000",
  "x-proxy": "special header for request"
}

参考文献

関連記事

11
7
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
11
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?