コンテンツにスキップ

http

Since v8.5.0

httpモジュールは、JSHアプリケーション用にNode.js互換のHTTPクライアント/サーバーAPIを提供します。

request()

ClientRequestオブジェクトを作成します。

対応するシグネチャ:

  • request(url[, options][, callback])

  • request(options[, callback])

  • 戻り値: ClientRequest

  • callbackを指定すると、応答の受信時にIncomingMessageを引数として受け取ります。

構文
request(url[, options][, callback])
request(options[, callback])
主なリクエストオプション
  • url (stringまたはURL)
  • protocol, host, hostname, port, path
  • method
  • headers
  • auth (Authorization: Basic ...に変換)
  • agent
使用例
1
2
3
4
5
6
const http = require('http');
const req = http.request('http://127.0.0.1:8080/hello');
req.on('response', (res) => {
  console.println(res.statusCode, res.statusMessage);
});
req.end();

get()

GETリクエストの短縮関数です。内部でrequest()を作成し、自動的にend()を呼び出します。

対応するシグネチャ:

  • get(url[, options][, callback])

  • get(options[, callback])

  • 戻り値: ClientRequest

  • callbackを省略した場合は、responseイベントリスナーで応答を処理できます。

構文
get(url[, options][, callback])
get(options[, callback])

status

HTTPステータスコードのマップです。

例:

  • http.status.OK
  • http.status.NotFound
  • http.status.InternalServerError

動作に関する注意

  • response.okは、ステータスコードが200299の場合にtrueです。
  • response.headersのキーは、小文字に正規化されます。
  • setHeader()getHeader()hasHeader()removeHeader()は、ヘッダー名の大文字と小文字を区別しません。
  • write()を複数回呼び出すと、リクエストボディを蓄積してから送信します。

ClientRequest

request()またはget()が返すリクエストオブジェクトです。

ClientRequestのヘッダーメソッド

  • setHeader(name, value)
  • getHeader(name)
  • hasHeader(name)
  • removeHeader(name)
  • getHeaders()
  • getHeaderNames()
使用例
1
2
3
4
5
6
const http = require('http');
const req = http.request('http://127.0.0.1:8080/hello');
req.setHeader('X-Test-Header', 'TestValue');
console.println(req.hasHeader('X-Test-Header'));
console.println(req.getHeader('X-Test-Header'));
req.end();

ClientRequest.write()

リクエストボディのチャンクを書き込みます。

  • chunkは、stringUint8Arrayに対応しています。
  • 成功時にtrue、失敗時にfalseを返します。
構文
write(chunk[, encoding][, callback])

ClientRequest.end()

リクエストを完了して送信します。

  • callbackを渡すと、応答オブジェクト(IncomingMessage)を引数として受け取ります。
構文
end([data[, encoding]][, callback])

ClientRequest.destroy()

リクエストオブジェクトを破棄し、必要に応じてエラーイベントを発生させます。

構文
destroy([err])

ClientRequest イベント

  • response (IncomingMessage)
  • error (Error)
  • end ()

IncomingMessage

HTTPレスポンスオブジェクトです。

主なプロパティ
  • statusCode
  • statusMessage
  • ok (2xxの場合はtrue)
  • headers
  • rawHeaders
  • httpVersion
  • complete
  • raw (内部のGoレスポンスオブジェクト)

IncomingMessageのボディメソッド

  • text([encoding])

  • json()

  • readBody([encoding])

  • readBodyBuffer()

  • text()readBody()の既定のエンコーディングは、utf-8です。

  • json()は、解析に失敗すると例外を発生させる場合があります。

IncomingMessageのユーティリティメソッド

  • setTimeout(msecs[, callback])
  • close()

通常の処理ではレスポンスボディは自動的に閉じます。必要に応じてclose()を明示的に呼び出せます。

使用例
1
2
3
4
5
const http = require('http');
http.get('http://127.0.0.1:8080/hello', (res) => {
  console.println(res.ok, res.statusCode);
  console.println(res.text());
});

Server

HTTPサーバーオブジェクトです。

作成
new Server([options])
オプション
  • network: tcpまたはunix(既定値:tcp
  • address: host:portまたはUnixソケットのパス
  • env: 環境オブジェクト(省略可能)。ファイルシステムへのアクセスには必要です。

Serverのルート・静的ファイル用メソッド

  • get(path, handler)
  • post(path, handler)
  • put(path, handler)
  • delete(path, handler)
  • ws(path[, options], handler)
  • static(path, root)
  • staticFile(path, file)

Serverのテンプレートメソッド

  • loadHTMLFiles(...files)
  • loadHTMLGlob(pattern)

Serverのライフサイクルメソッド

  • serve([callback])
  • close([callback])

serve(callback)は、{ network, address }を渡します。

使用例
1
2
3
4
5
6
7
const http = require('http');
const server = new http.Server({ network: 'tcp', address: '127.0.0.1:8080' });
server.get('/hello/:name', (ctx) => {
  const name = ctx.param('name');
  ctx.json(http.status.OK, { greeting: 'hello', name });
});
server.serve();

Server.ws()

Since v8.5.2

HTTPサーバーにWebSocketルートを簡単に接続する便利なAPIです。

内部でrequire('ws').WebSocketServerを作成し、現在のhttp.Serverに接続します。

構文
server.ws(path, handler)
server.ws(path, options, handler)
オプション
  • verifyClient({ origin, req })
  • handleProtocols(protocols, req)
  • clientTracking (既定値: true)
使用例
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
const http = require('http');

const server = new http.Server({ network: 'tcp', address: '127.0.0.1:8080' });

server.ws('/ws', {
  verifyClient: ({ req }) => req.query('token') === 'allow',
  handleProtocols: (protocols) => {
    if (protocols.indexOf('machbase.rpc') >= 0) {
      return 'machbase.rpc';
    }
    return false;
  },
}, (socket, request) => {
  console.println(request.path, request.httpVersion, socket.protocol);
  socket.on('message', (event) => {
    socket.send('echo:' + event.data);
  });
});

server.serve();

handler(socket, request)を受け取ります。socketws.WebSocketと同じイベントモデルを使用し、requestはハンドシェイクリクエストの情報を持つヘルパーオブジェクトです。

Server.ws() 動作に関する注意

  • verifyClient()handleProtocols()は、同期的に呼び出されます。
  • verifyClient()falseを返すと、ハンドシェイクを拒否します。
  • handleProtocols()は、選択したプロトコル文字列、または拒否を表すfalsyな値を返す必要があります。
  • requestは、Node.jsの完全なIncomingMessageではなく、JSH用のヘルパーオブジェクトです。
  • 低水準のupgradeイベントやhandleUpgrade() APIは提供しません。

Serverのコンテキスト

ハンドラーは、リクエスト・レスポンスのヘルパーを含むctxを引数として受け取ります。

リクエストヘルパー
  • ctx.request.path
  • ctx.request.query
  • ctx.request.body
  • ctx.request.getHeader(name)
  • ctx.param(name)
  • ctx.query(name)
レスポンスヘルパー
  • ctx.setHeader(name, value)
  • ctx.redirect(status, url)
  • ctx.abort()
  • ctx.text(status, format[, ...args])
  • ctx.html(status, template, data)
  • ctx.yaml(status, data)
  • ctx.toml(status, data)
  • ctx.json(status, data[, { space: number|string }])
  • ctx.xml(status, data[, { root: string }])

ctx.json()は、インデント用のspaceオプションに対応しています。

ctx.json(http.status.OK, { greeting: 'hello', name: 'neo' }, { space: 2 });
ctx.json(http.status.OK, { greeting: 'hello', name: 'neo' }, { space: '\t' });

ctx.xml()は、既定でオブジェクトをルート要素<map>として出力します。最上位の要素名を変更するには、オプションオブジェクトのrootフィールドを指定します。

1
2
3
4
5
6
7
svr.get('/formats/xml', (ctx) => {
  ctx.xml(http.status.OK, { str: 'Hello World', num: 123, bool: true });
});

svr.get('/formats/xml-root', (ctx) => {
  ctx.xml(http.status.OK, { name: 'neo', count: 2 }, { root: 'user' });
});

既定のXML出力:

<map><str>Hello World</str><num>123</num><bool>true</bool></map>

rootを指定したXML出力:

<user><name>neo</name><count>2</count></user>

クライアントの例

GETリクエスト(コールバック)

1
2
3
4
5
6
const http = require('http');

http.get('http://127.0.0.1:8080/hello', (res) => {
  console.println('Status:', res.statusCode, res.statusMessage);
  console.println('Body:', res.text());
});

GETリクエスト(イベントリスナー)

1
2
3
4
5
6
7
const http = require('http');

const req = http.get('http://127.0.0.1:8080/hello');
req.on('response', (res) => {
  console.println('Status:', res.statusCode, res.statusMessage);
  console.println('Body:', res.text());
});

リクエストヘッダーの設定と取得

1
2
3
4
5
6
7
const http = require('http');

const req = http.request('http://127.0.0.1:8080/hello');
req.setHeader('X-Trace-Id', 'trace-001');
console.println(req.hasHeader('x-trace-id'));
console.println(req.getHeader('X-Trace-Id'));
req.end();

レスポンスヘッダーとボディの読み取り

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const http = require('http');

http.get('http://127.0.0.1:8080/hello', (res) => {
  const contentType = res.headers['content-type'];
  const contentLength = res.headers['content-length'];

  console.println('Content-Type:', contentType);
  console.println('Content-Length:', contentLength);
  console.println('Body:', res.text());
});

POST JSONリクエスト

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
const http = require('http');

const req = http.request('http://127.0.0.1:8080/echo', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  }
});

req.on('response', (res) => {
  if (!res.ok) {
    throw new Error('request failed: ' + res.statusCode);
  }
  console.println(res.json());
});

req.on('error', (err) => {
  console.println('Request error:', err.message);
});

req.write('{"message":"hello"}');
req.end();

404レスポンスの処理

1
2
3
4
5
6
7
8
const http = require('http');

http.get('http://127.0.0.1:8080/notfound', (res) => {
  console.println('Status:', res.statusCode, res.statusMessage);
  if (!res.ok) {
    console.println('Request failed');
  }
});

URLオブジェクトによるリクエスト

サーバーの実行中にGETリクエストを送信し、JSONボディを解析します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
const http = require('http');

try {
  const url = new URL('http://127.0.0.1:56802/hello/Steve');
  const req = http.request(url);
  req.end((response) => {
    const { statusCode, statusMessage } = response;
    console.println('Status Code:', statusCode);
    console.println('Status Message:', statusMessage);
    console.println('Body:', response.json());
  });
} catch (e) {
  console.println(e.message);
}

サーバーの例

簡単なHTTPサーバー

127.0.0.1:56802でサーバーを起動し、/hello/:nameパスでJSONを返します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const http = require('http');

const svr = new http.Server({ network: 'tcp', address: '127.0.0.1:56802' });

svr.get('/hello/:name', (ctx) => {
  const name = ctx.param('name');
  ctx.json(http.status.OK, {
    message: 'greetings',
    name: name,
  });
});

svr.serve((result) => {
  console.println('server started', result.network, result.address);
});
curl -o - http://127.0.0.1:56802/hello/Karl
{"message":"greetings","name":"Karl"}

静的コンテンツとリダイレクト

1
2
3
4
5
6
svr.staticFile('/readme', '/path/to/file.txt');
svr.static('/static', '/path/to/static_dir');

svr.get('/readme', (ctx) => {
  ctx.redirect(http.status.Found, '/docs/readme.html');
});

RESTful API

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
let list = [
  { title: 'Indiana Jones', id: 59793, studio: ['Paramount'] },
  { title: 'Star Wars', id: 64821, studio: ['Lucasfilm'] },
];

svr.get('/movies', (ctx) => {
  ctx.json(http.status.OK, list);
});

svr.post('/movies', (ctx) => {
  const obj = ctx.request.body;
  list.push(obj);
  ctx.json(http.status.Created, obj);
});

svr.delete('/movies/:id', (ctx) => {
  const id = parseInt(ctx.param('id'));
  list = list.filter((item) => item.id !== id);
  ctx.json(http.status.NoContent);
});

次のコマンドで、各呼び出しを確認できます。

  • GETリクエスト
curl -o - http://127.0.0.1:56802/movies
[
  { "id": 59793, "studio": [ "Paramount" ], "title": "Indiana Jones" },
  { "id": 64821, "studio": [ "Lucasfilm" ], "title": "Star Wars" }
]
  • POSTリクエスト
curl -o - -X POST http://127.0.0.1:56802/movies \
    -H "Content-Type: application/json" \
    -d '{"title":"new movie", "id":12345, "studio":["HomeVideo"]}'
  • DELETEリクエスト
curl -v -o - -X DELETE http://127.0.0.1:56802/movies/12345
< HTTP/1.1 204 No Content
< Content-Type: text/plain; charset=utf-8
< Date: Thu, 08 May 2025 20:39:34 GMT
<

HTMLテンプレート

以下の設定は、/*.htmlパターンに一致するすべてのHTMLテンプレートを読み込みます。 テンプレートを使用すると、定義済みのレイアウトと実行時のデータを組み合わせて、HTMLレスポンスを動的に生成できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
svr.loadHTMLGlob('/*.html');

svr.get('/movielist', (ctx) => {
  const obj = {
    subject: 'Movie List',
    list: [
      { title: 'Indiana Jones', id: 59793, studio: ['Paramount'] },
      { title: 'Star Wars', id: 64821, studio: ['Lucasfilm'] },
    ],
  };
  ctx.html(http.status.OK, 'movie_list.html', obj);
});
  • HTMLテンプレートのコードmovie_list.html
<html>
    <body>
        <h1>{{.subject}}</h1>
        <ol>
        {{range .list }}
            <li> {{.id}} {{.title}} {{.studio}}
        {{end}}
        </ol>
    </body>
</html>

/movielistエンドポイントにGETリクエストを送信すると、 サーバーは、movie_list.htmlテンプレートとobjデータを使ってHTMLページを生成します。

curl -o - http://127.0.0.1:56802/movielist
<html>
    <body>
        <h1>Movie List</h1>
        <ol>
            <li> 59793 Indiana Jones [Paramount]
            <li> 64821 Star Wars [Lucasfilm]
        </ol>
    </body>
</html>
最終更新日