<commit_before>// @flow
import type {
  IncomingMessage,
  ServerResponse,
} from 'http'
import type {
  RequestData,
  ResponseData,
  PhenylRunner,
} from 'phenyl-interfaces'

import url from 'url'
import {
  decodeRequest,
  encodeResponse,
  getStatusCode,
} from 'phenyl-http-rules/jsnext'
import {
  createErrorResult,
} from 'phenyl-utils'

export default class PhenylHTTPServer {
  server: net$Server
  phenylCore: PhenylRunner

  constructor(server: net$Server, phenylCore: PhenylRunner) {
    this.server = server
    this.phenylCore = phenylCore
    this.onRequest = this.onRequest.bind(this)
  }

  /**
   *
   */
  listen(port: number, hostname: string, backlog: number, callback: Function) {
    this.server.on('request', this.onRequest)
    this.server.listen(port, hostname, backlog, callback)
  }

  getRequestBody(request: IncomingMessage): Promise<string> {
    return new Promise((resolve, reject) => {
      // https://nodejs.org/api/stream.html#stream_readable_read_size
      request.on('readable', () => {
        const chunks = []
        let chunk
        let totalLength = 0
        while (null !== (chunk = request.read())) {
          chunks.push(chunk)
          totalLength += chunk.length
        }
        resolve(Buffer.concat(chunks, totalLength).toString('utf8'))
      })
    })
  }

  /**
   * @private
   * @param {IncomingMessage} request
   * @param {ServerResponse} response
   */
  async onRequest(request: IncomingMessage, response: ServerResponse) {
    const requestUrl = url.parse(request.url, true)
    let responseData

    try {
      // 1. Decoding Request
      const [requestData, sessionId] = decodeRequest({
        method: request.method,
        path: requestUrl.pathname,
        body: await this.getRequestBody(request),
        headers: request.headers,
        queryString: requestUrl.query,
      })
      // 2. Invoking PhenylCore
      responseData = await this.phenylCore.run(requestData, sessionId)
    }
    catch (err) {
      responseData = { error: createErrorResult(err) }
    }

    // 3. Encoding Response
    const statusCode = getStatusCode(responseData)
    const body = JSON.stringify(encodeResponse(responseData))
    const headers = {
      'Content-Length': Buffer.byteLength(body),
      'Content-Type': 'application/json',
    }
    response.writeHead(statusCode, headers)
    response.write(body)
    res.end()
  }
}<commit_msg>:pencil2: Fix typo<commit_after>// @flow
import type {
  IncomingMessage,
  ServerResponse,
} from 'http'
import type {
  RequestData,
  ResponseData,
  PhenylRunner,
} from 'phenyl-interfaces'

import url from 'url'
import {
  decodeRequest,
  encodeResponse,
  getStatusCode,
} from 'phenyl-http-rules/jsnext'
import {
  createErrorResult,
} from 'phenyl-utils'

export default class PhenylHTTPServer {
  server: net$Server
  phenylCore: PhenylRunner

  constructor(server: net$Server, phenylCore: PhenylRunner) {
    this.server = server
    this.phenylCore = phenylCore
    this.onRequest = this.onRequest.bind(this)
  }

  /**
   *
   */
  listen(port: number, hostname: string, backlog: number, callback: Function) {
    this.server.on('request', this.onRequest)
    this.server.listen(port, hostname, backlog, callback)
  }

  getRequestBody(request: IncomingMessage): Promise<string> {
    return new Promise((resolve, reject) => {
      // https://nodejs.org/api/stream.html#stream_readable_read_size
      request.on('readable', () => {
        const chunks = []
        let chunk
        let totalLength = 0
        while (null !== (chunk = request.read())) {
          chunks.push(chunk)
          totalLength += chunk.length
        }
        resolve(Buffer.concat(chunks, totalLength).toString('utf8'))
      })
    })
  }

  /**
   * @private
   * @param {IncomingMessage} request
   * @param {ServerResponse} response
   */
  async onRequest(request: IncomingMessage, response: ServerResponse) {
    const requestUrl = url.parse(request.url, true)
    let responseData

    try {
      // 1. Decoding Request
      const [requestData, sessionId] = decodeRequest({
        method: request.method,
        path: requestUrl.pathname,
        body: await this.getRequestBody(request),
        headers: request.headers,
        queryString: requestUrl.query,
      })
      // 2. Invoking PhenylCore
      responseData = await this.phenylCore.run(requestData, sessionId)
    }
    catch (err) {
      responseData = { error: createErrorResult(err) }
    }

    // 3. Encoding Response
    const statusCode = getStatusCode(responseData)
    const body = JSON.stringify(encodeResponse(responseData))
    const headers = {
      'Content-Length': Buffer.byteLength(body),
      'Content-Type': 'application/json',
    }
    response.writeHead(statusCode, headers)
    response.write(body)
    response.end()
  }
}
{'fraction_non_alphanumeric': 0.1179635761589404, 'fraction_numerical': 0.0022764900662251655, 'mean_word_length': 2.990916597853014, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2258318', 'n_tokens_mistral': 1489, 'n_tokens_neox': 1435, 'n_words': 310}