59673
node.jsの勉強をしています。  
httpモジュールのcreateServerの引数について質問です。  
`getFormClient`関数は引数が2つありますが、  
呼び出す側の`http.createServer(getFormClient)`は引数がありません。  
これは、デフォルト引数ということで理解しました。

しかし、デフォルト引数であるならば、`getFormClient`関数の引数は`undefined`になり、  
`res.writeHead(200, {'Content-Type': 'text/html'});`などでエラーになるのではないでしょうか？

```

    const http = require('http');
    const fs = require('fs');
    
    var server = http.createServer(getFormClient)
    function getFormClient(req, res){
      fs.readFile('index.html', 'UTF-8',
        (err, data) => {
          res.writeHead(200, {'Content-Type': 'text/html'});
          res.write(data);
          res.end();
        }
      );
    }
```
CC BY-SA 4.0
2019-10-11T07:35:19.167
59638
2019-10-12T18:59:33.277
2019-10-12T18:59:33.277
32986
25837
question
javascript node.js
httpモジュールのcreateServerの引数について
> これは、デフォルト引数ということで理解しました。

いいえ、デフォルト引数ではありません。

そのコールバック関数 (`getFormClient` 関数) を呼び出すのは Node.js であり、
**内部で生成されたオブジェクトを引数として、当該コールバック関数を呼び出し** ます。そのため、今回の場合デフォルト引数は関係がなく、
`getFormClient` 関数の引数は `undefined` になりません。念のため、 Node.js
がどのように当該コールバック関数を呼び出すのかを、以下に粗く書いておきます。

* * *

`http.createServer` メソッドは、 `http.Server`
クラスのインスタンスを返します[[1]](https://github.com/nodejs/node/blob/8507485fb242dfcaf07092414871aa9c185a28e4/lib/http.js#L39)。この
`http.Server` クラスは、 `requestListener` 関数 (`getFormClient` 関数) をリスナー関数として、
`request`
イベントを登録します[[2]](https://nodejs.org/api/http.html#http_http_createserver_options_requestlistener)。また、この処理は以下のコードから、
`http.Server`
クラスのコンストラクタで行なわれていることがわかります[[3]](https://github.com/nodejs/node/blob/8507485fb242dfcaf07092414871aa9c185a28e4/lib/_http_server.js#L329)。

> ## node/http.js at 8507485fb242dfcaf07092414871aa9c185a28e4 · nodejs/node ·
> GitHub[[1]](https://github.com/nodejs/node/blob/8507485fb242dfcaf07092414871aa9c185a28e4/lib/http.js#L39)
```

>     function createServer(opts, requestListener) {
>       return new Server(opts, requestListener);
>     }
>  
```

>
> * * *
>
> ## http.createServer([options][,
> requestlistener])[[2]](https://nodejs.org/api/http.html#http_http_createserver_options_requestlistener)
>
> Returns a new instance of http.Server.
>
> The `requestListener` is a function which is automatically added to the
> 'request' event.
>
> * * *
>
> ## node/_http_server.js at 8507485fb242dfcaf07092414871aa9c185a28e4 ·
> nodejs/node ·
> GitHub[[3]](https://github.com/nodejs/node/blob/8507485fb242dfcaf07092414871aa9c185a28e4/lib/_http_server.js#L329)
```

>      function Server(options, requestListener) {
>       if (!(this instanceof Server)) return new Server(options,
> requestListener);
>  
>       if (typeof options === 'function') {
>         requestListener = options;
>         options = {};
>       } else if (options == null || typeof options === 'object') {
>         options = { ...options };
>       } else {
>         throw new ERR_INVALID_ARG_TYPE('options', 'object', options);
>       }
>  
>       this[kIncomingMessage] = options.IncomingMessage || IncomingMessage;
>       this[kServerResponse] = options.ServerResponse || ServerResponse;
>  
>       net.Server.call(this, { allowHalfOpen: true });
>  
>       if (requestListener) {
>         this.on('request', requestListener);
>       }
>  
>       // 省略
>  
```

実際に通信が確立され、 HTTP リクエストヘッダの解析が完了すると、 `http.ServerResponse`
オブジェクトが生成されます。そしてその後、 `request` イベントに登録されたリスナー関数 (`getFormClient` 関数) が、
**`http.IncomingMessage` オブジェクトと `http.ServerResponse`
オブジェクトを引数として呼び出され**ます。[[4]](https://github.com/nodejs/node/blob/458a38c904c78b072f4b49c45dda7c63987bb60b/lib/_http_server.js#L742)。

> ## node/_http_server.js at 458a38c904c78b072f4b49c45dda7c63987bb60b ·
> nodejs/node ·
> GitHub[[4]](https://github.com/nodejs/node/blob/458a38c904c78b072f4b49c45dda7c63987bb60b/lib/_http_server.js#L742)。
```

>       if (req.headers.expect !== undefined &&
>           (req.httpVersionMajor === 1 && req.httpVersionMinor === 1)) {
>         if (continueExpression.test(req.headers.expect)) {
>           res._expect_continue = true;
>  
>           if (server.listenerCount('checkContinue') > 0) {
>             server.emit('checkContinue', req, res);
>           } else {
>             res.writeContinue();
>             server.emit('request', req, res);
>           }
>         } else if (server.listenerCount('checkExpectation') > 0) {
>           server.emit('checkExpectation', req, res);
>         } else {
>           res.writeHead(417);
>           res.end();
>         }
>       } else {
>         server.emit('request', req, res);
>       }
>       return 0;  // No special treatment.
>     }
>  
```
CC BY-SA 4.0
2019-10-12T18:56:35.673
59673
2019-10-12T18:56:35.673
32986
59638
answer